diff --git a/.gitignore b/.gitignore index 4d962c0c..1fccba17 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ spec/examples.txt spec/reports test/executable/source.rb.html test/executable/source.rb.json +test/executable/*.actual.html +test/executable/*.actual.json test/scanners diff --git a/lib/coderay/helpers/file_type.rb b/lib/coderay/helpers/file_type.rb index 7de34d58..09819cca 100644 --- a/lib/coderay/helpers/file_type.rb +++ b/lib/coderay/helpers/file_type.rb @@ -97,6 +97,8 @@ def type_from_shebang filename 'java' => :java, 'js' => :java_script, 'json' => :json, + 'kt' => :kotlin, + 'kts' => :kotlin, 'lua' => :lua, 'mab' => :ruby, 'pas' => :delphi, diff --git a/lib/coderay/scanners/kotlin.rb b/lib/coderay/scanners/kotlin.rb new file mode 100644 index 00000000..d2b52a07 --- /dev/null +++ b/lib/coderay/scanners/kotlin.rb @@ -0,0 +1,192 @@ +module CodeRay + module Scanners + load :java + + class Kotlin < Java + register_for :kotlin + file_extension 'kt' + + KOTLIN_KEYWORDS = %w[ + package import + as? as is + val var + class interface object fun init get set + in out + if when else for while do return break continue + ] + + KOTLIN_MODIFIERS = %w[ + annotation enum data sealed companion + abstract open final + public protected private internal + inline suspend + inner + ] + + TYPES = %w[ + Boolean Byte Char class Double Float Int Long Short Unit Nothing Any + ] + + STRING_CONTENT_PATTERN = { + "'" => /[^\\'$]+/, + '"' => /[^\\"$]+/ + } # :nodoc:s + + IDENT_KIND = Java::IDENT_KIND.dup. + add(TYPES, :type). + add(KOTLIN_KEYWORDS, :keyword). + add(KOTLIN_MODIFIERS, :keyword) # :nodoc: + + def setup + @state = :initial + end + + def scan_tokens encoder, options + string_delimiter = nil + state = options[:state] || @state + last_token_dot = false + class_name_follows = false + delimiters = [] + states = [] + + until eos? + + case state + + when :initial + if (match = scan(/ \s+ | \\\n /x)) + encoder.text_token match, :space + next + elsif (match = scan(%r! // [^\n\\]* (?: \\. [^\n\\]* )* | /\* (?: .*? \*/ | .* ) !mx)) + encoder.text_token match, :comment + next + elsif (match = scan(/ TODO \( /ox)) + encoder.text_token "TODO", :comment + encoder.text_token "(", :operator + elsif (match = scan(/ #{IDENT} /ox)) + kind = IDENT_KIND[match] + if last_token_dot + kind = :ident + elsif class_name_follows + kind = :class + class_name_follows = false + else + # noinspection RubyEmptyElseBlockInspection + case match + when 'import' + :include + when 'package' + :namespace + when 'class', 'interface' + class_name_follows = true + end + end + encoder.text_token match, kind + elsif (match = scan(/ \.(?!\d) | [,?:()\[\]] | -- | \+\+ | && | \|\| | \*\*=? | [-+*\/%^~&|<>=!]=? /x)) + encoder.text_token match, :operator + elsif (match = scan(/\{/)) + class_name_follows = false + encoder.text_token match, :operator + states << :initial + elsif (match = scan(/\}/)) + encoder.text_token match, :operator + + unless states.empty? + state = states.pop + + if [:multiline_string, :string].include? state + string_delimiter = delimiters.pop + encoder.end_group :initial + end + end + elsif (match = scan(/"""/)) + state = :multiline_string + encoder.begin_group :string + encoder.text_token match, :delimiter + elsif (match = scan(/["']/)) + state = :string + encoder.begin_group state + string_delimiter = match + encoder.text_token match, :delimiter + elsif check(/[\d.]/) + if (match = scan(/0[xX][0-9A-Fa-f]+/)) + encoder.text_token match, :hex + elsif (match = scan(/(?>0[0-7]+)(?![89.eEfF])/)) + encoder.text_token match, :octal + elsif (match = scan(/\d+[fFdD]|\d*\.\d+(?:[eE][+-]?\d+)?[fFdD]?|\d+[eE][+-]?\d+[fFdD]?/)) + encoder.text_token match, :float + elsif (match = scan(/\d+[lL]?/)) + encoder.text_token match, :integer + end + + elsif (match = scan(/ @ #{IDENT} /ox)) + encoder.text_token match, :annotation + + else + encoder.text_token getch, :error + end + + when :string + if (match = scan(/\$\{/)) + encoder.text_token match, :operator + + state = :initial + encoder.begin_group state + + delimiters << string_delimiter + states << :string + string_delimiter = nil + elsif (match = scan(/ \$ #{IDENT} /ox)) + encoder.text_token match, :ident + elsif (match = scan(STRING_CONTENT_PATTERN[string_delimiter])) + encoder.text_token match, :content + elsif (match = scan(/ \\ (?: #{ESCAPE} | #{UNICODE_ESCAPE} ) /mox)) + if string_delimiter == "'" && !(%W[\\\\ \\'].include? match) + encoder.text_token match, :content + else + encoder.text_token match, :char + end + elsif (match = scan(/["']/)) + encoder.text_token match, :delimiter + encoder.end_group state + state = :initial + string_delimiter = nil + elsif (match = scan(/ \\ | $ /x)) + encoder.end_group state + state = :initial + encoder.text_token match, :error unless match.empty? + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + when :multiline_string + if (match = scan(/\$\{/)) + encoder.text_token match, :operator + + state = :initial + encoder.begin_group state + + delimiters << nil + states << :multiline_string + elsif (match = scan(/ \$ #{IDENT} /ox)) + encoder.text_token match, :ident + elsif (match = scan(/ [^$\\"]+ /x)) + encoder.text_token match, :content + elsif (match = scan(/"""/x)) + encoder.text_token match, :delimiter + encoder.end_group :string + state = :initial + string_delimiter = nil + elsif (match = scan(/"/)) + encoder.text_token match, :content + else + raise_inspect "else case \" reached; %p not handled." % peek(1), encoder + end + else + raise_inspect 'Unknown state', encoder + end + + end + end + end + end +end diff --git a/test/executable/source.kt b/test/executable/source.kt new file mode 100644 index 00000000..290f9d6a --- /dev/null +++ b/test/executable/source.kt @@ -0,0 +1,38 @@ +class Test { + val text1: String = "abc \' def \u0000 \n \" hehe " + val text2: List = listOf('a', '\n', '\'', '"', '\"') + val numbers = listOf(0, 12, 1.0f, 1.0, 1L, 0x1f, -1, -12, -1.0f, -1.0, -1L) + + val template = "abc${1 + "b"}def" + val template2 = "abc${1 + 'b'}def" + val template3 = "abc $var def" + + val multiline = """ first line $var ${1 + 1} + second line + and quotes: ' " '' "" ok + """ + + val innerBraces = " before ${ if (true) { 1 } else { 2 } }" + + var v: Int = 0 + + fun function(): ReturnType { + } + + fun parametrizedFunction(): T = TODO() + + fun references() { + super.references() + this.references() + } + + @Annotation + class Annotated + + inner class Inner + + object O + + companion object { + } +} \ No newline at end of file diff --git a/test/executable/source.kt.expected.json b/test/executable/source.kt.expected.json new file mode 100644 index 00000000..f4f2643b --- /dev/null +++ b/test/executable/source.kt.expected.json @@ -0,0 +1 @@ +[{"type":"text","text":"class","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"Test","kind":"class"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"text1","kind":"ident"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"String","kind":"predefined_type"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":"abc ","kind":"content"},{"type":"text","text":"\\'","kind":"char"},{"type":"text","text":" def ","kind":"content"},{"type":"text","text":"\\u0000","kind":"char"},{"type":"text","text":" ","kind":"content"},{"type":"text","text":"\\n","kind":"char"},{"type":"text","text":" ","kind":"content"},{"type":"text","text":"\\\"","kind":"char"},{"type":"text","text":" hehe ","kind":"content"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"text2","kind":"ident"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"List","kind":"predefined_type"},{"type":"text","text":"<","kind":"operator"},{"type":"text","text":"Char","kind":"type"},{"type":"text","text":">","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"listOf","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"a","kind":"content"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"\\n","kind":"content"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"\\'","kind":"char"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"\"","kind":"content"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"\\\"","kind":"content"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"numbers","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"listOf","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":"0","kind":"integer"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"12","kind":"integer"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"1.0f","kind":"float"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"1.0","kind":"float"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"1L","kind":"integer"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"0x1f","kind":"hex"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"-","kind":"operator"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"-","kind":"operator"},{"type":"text","text":"12","kind":"integer"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"-","kind":"operator"},{"type":"text","text":"1.0f","kind":"float"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"-","kind":"operator"},{"type":"text","text":"1.0","kind":"float"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"-","kind":"operator"},{"type":"text","text":"1L","kind":"integer"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"template","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":"abc","kind":"content"},{"type":"text","text":"${","kind":"operator"},{"type":"block","action":"open","kind":"initial"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"+","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":"b","kind":"content"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"}","kind":"operator"},{"type":"block","action":"close","kind":"initial"},{"type":"text","text":"def","kind":"content"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"template2","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":"abc","kind":"content"},{"type":"text","text":"${","kind":"operator"},{"type":"block","action":"open","kind":"initial"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"+","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"'","kind":"delimiter"},{"type":"text","text":"b","kind":"content"},{"type":"text","text":"'","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"}","kind":"operator"},{"type":"block","action":"close","kind":"initial"},{"type":"text","text":"def","kind":"content"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"template3","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":"abc ","kind":"content"},{"type":"text","text":"$var","kind":"ident"},{"type":"text","text":" def","kind":"content"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"multiline","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"\"\"","kind":"delimiter"},{"type":"text","text":" first line ","kind":"content"},{"type":"text","text":"$var","kind":"ident"},{"type":"text","text":" ","kind":"content"},{"type":"text","text":"${","kind":"operator"},{"type":"block","action":"open","kind":"initial"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"+","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":"}","kind":"operator"},{"type":"block","action":"close","kind":"initial"},{"type":"text","text":"\n second line\n and quotes: ' ","kind":"content"},{"type":"text","text":"\"","kind":"content"},{"type":"text","text":" '' ","kind":"content"},{"type":"text","text":"\"","kind":"content"},{"type":"text","text":"\"","kind":"content"},{"type":"text","text":" ok\n ","kind":"content"},{"type":"text","text":"\"\"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"val","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"innerBraces","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"block","action":"open","kind":"string"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"text","text":" before ","kind":"content"},{"type":"text","text":"${","kind":"operator"},{"type":"block","action":"open","kind":"initial"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"if","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":"true","kind":"predefined_constant"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"1","kind":"integer"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"else","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"2","kind":"integer"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"block","action":"close","kind":"initial"},{"type":"text","text":"\"","kind":"delimiter"},{"type":"block","action":"close","kind":"string"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"var","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"v","kind":"ident"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"Int","kind":"type"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"0","kind":"integer"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"fun","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"function","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"ReturnType","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"fun","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"<","kind":"operator"},{"type":"text","text":"T","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"Any","kind":"type"},{"type":"text","text":">","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"parametrizedFunction","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":":","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"T","kind":"ident"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"=","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"TODO","kind":"comment"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"fun","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"references","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"super","kind":"local_variable"},{"type":"text","text":".","kind":"operator"},{"type":"text","text":"references","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"this","kind":"local_variable"},{"type":"text","text":".","kind":"operator"},{"type":"text","text":"references","kind":"ident"},{"type":"text","text":"(","kind":"operator"},{"type":"text","text":")","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"@Annotation","kind":"annotation"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"class","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"Annotated","kind":"class"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"inner","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"class","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"Inner","kind":"class"},{"type":"text","text":"<","kind":"operator"},{"type":"text","text":"in","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"T","kind":"ident"},{"type":"text","text":",","kind":"operator"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"out","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"E","kind":"ident"},{"type":"text","text":">","kind":"operator"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"object","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"O","kind":"ident"},{"type":"text","text":"\n\n ","kind":"space"},{"type":"text","text":"companion","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"object","kind":"keyword"},{"type":"text","text":" ","kind":"space"},{"type":"text","text":"{","kind":"operator"},{"type":"text","text":"\n ","kind":"space"},{"type":"text","text":"}","kind":"operator"},{"type":"text","text":"\n","kind":"space"},{"type":"text","text":"}","kind":"operator"}] diff --git a/test/executable/suite.rb b/test/executable/suite.rb index a6f40972..155ef39e 100644 --- a/test/executable/suite.rb +++ b/test/executable/suite.rb @@ -195,6 +195,26 @@ def coderay args, options = {} end end + context 'Kotlin smoke test' do + source_file = ROOT_DIR + 'test/executable/source.kt' + + should 'generate json' do + coderay("#{source_file} #{source_file}.actual.json") + # coderay("#{source_file} #{source_file}.actual.html") + + result = JSON.parse(File.read ("#{source_file}.actual.json")) + expected = JSON.parse(File.read ("#{source_file}.expected.json")) + + assert_equal expected, result + end + + # should 'respect the file extension and highlight the input as Kotlin' do + # target = coderay(command) + # assert_equal %w(keyword class), target[pre, 1].scan(tag_class).flatten + # end + + end + context 'highlighting a file with explicit input and output type (-ruby source.py -span)' do source_file = ROOT_DIR + 'test/executable/source.py' command = "-ruby #{source_file} -span"