Tree-Sitter Kotlin Grammar Issues
February 19, 2026 · View on GitHub
Structural mismatches between tree-sitter-kotlin and JetBrains PSI reference parser, categorized by root cause and difficulty. Each issue represents a grammar.js fix needed to match JetBrains' expected AST structure.
Current state: 96/122 clean parses match structurally (78.7%)
Fix these issues iteratively — after each grammar fix, re-run the cross-validation
and move fixed files from excluded.txt to the vendored corpus.
How to Use
- Pick an issue category below (start with EASY)
- Fix the grammar in
grammar.js - Run
npm run generate && npm testto verify existing tests still pass - Run
npm run cross-validateto check if affected files now match - Remove fixed files from
excluded.txt - Re-run
npm run vendor-jetbrainsto update corpus - Commit
EASY (5 files, 4 issues)
block_comment_file_start (2 files)
Problem: Block comments containing operators (e.g. /* 1 + 2 */) at file start
are parsed as BINARY_EXPRESSION instead of being treated as comments.
Files:
BlockCommentAtBeginningOfFile3BlockCommentAtBeginningOfFile4
Likely fix: Comment tokenization in extras or scanner — block comments with
arithmetic content aren't being consumed as comments in certain positions.
duplicate_accessor (1 file)
Problem: Property with duplicate get/set accessor produces 3 PROPERTY_ACCESSOR
children where PSI expects only 2.
Files:
DuplicateAccessor
Likely fix: Grammar allows more than 2 accessor declarations per property. Add constraint or let the grammar accept it (PSI may handle this as an error).
object_literal (1 file)
Problem: OBJECT_LITERAL used as a statement has wrong internal nesting structure.
Files:
ObjectLiteralAsStatement
Likely fix: Check object_literal rule — may need to adjust how object
expression wraps its delegation specifiers and class body.
typealias_keyword (1 file)
Problem: typealias not recognized as a separate declaration in some contexts;
parsed as a property instead.
Files:
TypealiasIsKeyword
Likely fix: typealias may not be in the keyword list or may conflict with
soft keyword handling.
MEDIUM (17 files, 6 issues)
enum_entry_constructor (4 files)
Problem: ENUM_ENTRY with constructor arguments: tree-sitter nests
VALUE_ARGUMENT_LIST inside the entry where PSI expects USER_TYPE +
VALUE_ARGUMENT_LIST as siblings under ENUM_ENTRY.
Files:
EnumMissingNameEnumShortCommasEnumShortWithOverloadEnums
Likely fix: enum_entry rule needs to produce a USER_TYPE child for the
supertype constructor call, with VALUE_ARGUMENT_LIST as a sibling, not nested
inside it.
file_annotations (4 files)
Problem: Multiple @file: annotations not grouped correctly in
FILE_ANNOTATION_LIST. ANNOTATION_TARGET and ANNOTATION_ENTRY structure
doesn't match PSI — PSI wraps each annotation in ANNOTATION_ENTRY with an
ANNOTATION_TARGET child.
Files:
DocCommentAfterFileAnnotationsLineCommentAfterFileAnnotationstopJvmPackageNametopJvmPackageNameMultifile
Likely fix: file_annotation rule needs to emit proper ANNOTATION_ENTRY >
ANNOTATION_TARGET nesting for each @file: annotation.
by_delegation (3 files)
Problem: DELEGATED_SUPER_TYPE_ENTRY with by clause produces extra
CALL_EXPRESSION child and missing CLASS_BODY. The by expression is
being absorbed into the delegation entry instead of being a separate construct.
Files:
ByClausesdelegationSimpleClassMembers
Likely fix: delegation_specifier rule — the by clause needs to be
structured so the delegated expression is properly separated from the class body.
class_body_nesting (3 files)
Problem: CLASS_BODY missing or inner class nesting structure differs from PSI.
Files:
NonTypeBeforeDotInBaseClassdependencyOnNestedClassesinnerTypes
Likely fix: Check how nested class declarations interact with the parent class body structure.
super_expression (1 file)
Problem: super expression with type qualifier (super<Foo>) has wrong
structural nesting compared to PSI.
Files:
Super
Likely fix: super_expression rule — type argument in angle brackets needs
correct nesting.
value_parameter_defaults (2 files)
Problem: Default parameter values (fun f(x: Int = 5)) are not nested inside
VALUE_PARAMETER. The default value expression appears as a sibling instead of
a child of the parameter.
Files:
SimpleExpressionstopLevelMembers
Likely fix: value_parameter rule — default value expression should be a
child of the parameter node, not promoted to the parameter list level.
HARD (20 files, 5 issues)
prefix_vs_binary (2 files)
Problem: Unary minus/plus after line breaks parsed as BINARY_EXPRESSION
instead of PREFIX_EXPRESSION. This is a newline-sensitivity issue — Kotlin
treats newlines as statement separators in some contexts.
Files:
EOLsInCommentsNewlinesInParentheses
Likely fix: Requires newline-aware precedence handling in the grammar or
scanner. Tree-sitter's extras treats newlines as whitespace by default,
losing the statement-termination semantics.
lambda_nesting (3 files)
Problem: Lambda bodies have wrong CALL_EXPRESSION vs BLOCK nesting.
FUNCTION_LITERAL children are in the wrong order or at the wrong depth.
Files:
CommentsBindingInLambdaFunctionLiteralslocalClass
Likely fix: lambda_literal and function_literal rules need restructuring.
The interaction between trailing lambdas and call expressions creates cascading
nesting differences.
type_argument_placement (7 files)
Problem: TYPE_ARGUMENT_LIST placed at wrong nesting level in USER_TYPE.
Affects generics like Foo<A>.Bar<B> — tree-sitter attaches type arguments
to the wrong part of the qualified type chain.
Files:
ExtensionsWithQNReceivercomplicateLTGTincorrectLTGTFallbackdefinitelyNotNullTypestypestypeParamstypeAliasExpansion
Likely fix: user_type rule — type arguments need to be attached per-segment
in dot-qualified types, not hoisted to the outermost type.
type_modifiers (3 files)
Problem: suspend and other type modifiers not mapped to correct PSI structure.
MODIFIER_LIST placement differs from JetBrains expectations.
Files:
TypeModifierstypeModifiers2suspendLambda
Likely fix: Type modifier handling in function types and lambda types needs
restructuring to match PSI's MODIFIER_LIST placement.
annotation_structure (5 files)
Problem: ANNOTATION_ENTRY / ANNOTATION_TARGET / CONSTRUCTOR_CALLEE
nesting differs from PSI. Annotations with arguments, use-site targets, and
annotations on type parameters all have structural differences.
Files:
annotationsannotationsOnParenthesizedTypesannotationValuesannotatedParameterInEnumConstructorTypeParametersBeforeName
Likely fix: Annotation rules need comprehensive restructuring to match PSI's
three-level nesting: ANNOTATION_ENTRY > ANNOTATION_TARGET + CONSTRUCTOR_CALLEE.