lib/rouge/lexers/kotlin.rb



# -*- coding: utf-8 -*- #
# frozen_string_literal: true

module Rouge
  module Lexers
    class Kotlin < RegexLexer
      # https://kotlinlang.org/docs/reference/grammar.html

      title "Kotlin"
      desc "Kotlin Programming Language (http://kotlinlang.org)"

      tag 'kotlin'
      filenames '*.kt', '*.kts'
      mimetypes 'text/x-kotlin'

      keywords = %w(
        abstract annotation as break by catch class companion const
        constructor continue crossinline do dynamic else enum
        external false final finally for fun get if import in infix
        inline inner interface internal is lateinit noinline null
        object open operator out override package private protected
        public reified return sealed set super tailrec this throw
        true try typealias typeof val var vararg when where while
        yield
      )

      name = %r'@?[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Nl}][\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Nl}\p{Nd}\p{Pc}\p{Cf}\p{Mn}\p{Mc}]*'
      name_backtick = %r'#{name}|`#{name}`'

      id = %r'(#{name_backtick})'

      state :root do
        rule %r'(\))(\s*)(:)(\s+)(#{name_backtick})(<)' do
          groups Punctuation, Text, Punctuation, Text, Name::Class, Punctuation
          push :generic_parameters
        end
        rule %r'(\))(\s*)(:)(\s+)(#{name_backtick})' do
          groups Punctuation, Text, Punctuation, Text, Name::Class
        end
        rule %r'\b(companion)(\s+)(object)\b' do
          groups Keyword, Text, Keyword
        end
        rule %r'\b(class|data\s+class|interface|object)(\s+)' do
          groups Keyword::Declaration, Text
          push :class
        end
        rule %r'\b(fun)(\s+)' do
          groups Keyword, Text
          push :function
        end
        rule %r'(#{name_backtick})(:)(\s+)(#{name_backtick})(<)' do
          groups Name::Variable, Punctuation, Text, Name::Class, Punctuation
          push :generic_parameters
        end
        rule %r'(#{name_backtick})(:)(\s+)(#{name_backtick})' do
          groups Name::Variable, Punctuation, Text, Name::Class
        end
        rule %r'\b(package|import)(\s+)' do
          groups Keyword, Text
          push :package
        end
        rule %r'\b(val|var)(\s+)(\()' do
          groups Keyword::Declaration, Text, Punctuation
          push :destructure
        end
        rule %r'\b(val|var)(\s+)' do
          groups Keyword::Declaration, Text
          push :property
        end
        rule %r/\bfun\b/, Keyword
        rule /\b(?:#{keywords.join('|')})\b/, Keyword
        rule %r'^\s*\[.*?\]', Name::Attribute
        rule %r'[^\S\n]+', Text
        rule %r'\\\n', Text # line continuation
        rule %r'//.*?$', Comment::Single
        rule %r'/[*].*?[*]/'m, Comment::Multiline
        rule %r'\n', Text
        rule %r'::|!!|\?[:.]', Operator
        rule %r"(\.\.)", Operator
        rule %r'[~!%^&*()+=|\[\]:;,.<>/?-]', Punctuation
        rule %r'[{}]', Punctuation
        rule %r'@"(""|[^"])*"'m, Str
        rule %r'""".*?"""'m, Str
        rule %r'"(\\\\|\\"|[^"\n])*["\n]'m, Str
        rule %r"'\\.'|'[^\\]'", Str::Char
        rule %r"[0-9](\.[0-9]+)?([eE][+-][0-9]+)?[flFL]?|0[xX][0-9a-fA-F]+[Ll]?", Num
        rule /@#{id}/, Name::Decorator
        rule id, Name
      end

      state :package do
        rule /\S+/, Name::Namespace, :pop!
      end

      state :class do
        rule id, Name::Class, :pop!
      end

      state :function do
        rule %r'(<)', Punctuation, :generic_parameters
        rule %r'(\s+)', Text
        rule %r'(#{name_backtick})(\.)' do
          groups Name::Class, Punctuation
        end
        rule id, Name::Function, :pop!
      end

      state :generic_parameters do
        rule id, Name::Class
        rule %r'(,)', Punctuation
        rule %r'(\s+)', Text
        rule %r'(>)', Punctuation, :pop!
      end

      state :property do
        rule id, Name::Property, :pop!
      end

      state :destructure do
        rule %r'(,)', Punctuation
        rule %r'(\))', Punctuation, :pop!
        rule %r'(\s+)', Text
        rule id, Name::Property
      end
    end
  end
end