diff --git a/Dart.g b/Dart.g deleted file mode 100644 index 6605bd9..0000000 --- a/Dart.g +++ /dev/null @@ -1,2169 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// CHANGES: -// -// v0.33 This commit does not change the derived language at all. It just -// changes several rules to use the regexp-like grammar operators to simplify -// onParts, recordLiteralNoConst, functionTypeTails, and functionType. -// -// v0.32 Remove unused non-terminal `patterns`. -// -// v0.31 Inline `identifierNotFUNCTION` into `identifier`. Replace all -// other references with `identifier` to match the spec. -// -// v0.30 Add support for the class modifiers `sealed`, `final`, `base`, -// `interface`, and for `mixin class` declarations. Also add support for -// unnamed libraries (`library;`). Introduce `otherIdentifier` to help -// maintaining consistency when the grammar is modified to mention any words -// that weren't previously mentioned, yet are not reserved or built-in. -// -// v0.29 Add an alternative in the `primary` rule to enable method invocations -// of the form `super(...)` and `super<...>(...)`. This was added to the -// language specification in May 21, b26e7287c318c0112610fe8b7e175289792dfde2, -// but the corresponding update here wasn't done here at the time. -// -// v0.28 Add support for `new` in `enumEntry`, e.g., `enum E { x.new(); }`. -// Add `identifierOrNew` non-terminal to simplify the grammar. -// -// v0.27 Remove unused non-terminals; make handling of interpolation in URIs -// consistent with the language specification. Make `partDeclaration` a -// start symbol in addition to `libraryDefinition` (such that no special -// precautions are needed in order to parse a part file). Corrected spacing -// in several rules. -// -// v0.26 Add missing `metadata` in `partDeclaration`. -// -// v0.25 Update pattern rules following changes to the patterns feature -// specification since v0.24. -// -// v0.24 Change constant pattern rules to allow Symbols and negative numbers. -// -// v0.23 Change logical pattern rules to || and &&. -// -// v0.22 Change pattern rules, following updated feature specification. -// -// v0.21 Add support for patterns. -// -// v0.20 Adjust record syntax such that () is allowed (denoting the empty -// record type and the empty record value). -// -// v0.19 Add support for super parameters, named arguments everywhere, and -// records. -// -// v0.18 Add support for enhanced `enum` declarations. -// -// v0.17 (58d917e7573c359580ade43845004dbbc62220d5) Correct `uri` to allow -// multi-line strings (raw and non-raw). -// -// v0.16 (284695f1937c262523a9a11b9084213f889c83e0) Correct instance variable -// declaration syntax such that `covariant late final` is allowed. -// -// v0.15 (6facd6dfdafa2953e8523348220d3129ea884678) Add support for -// constructor tearoffs and explicitly instantiated function tearoffs and -// type literals. -// -// v0.14 (f65c20124edd9e04f7b3a6f014f40c16f51052f6) Correct `partHeader` -// to allow uri syntax in a `PART OF` directive. -// -// v0.13 (bb5cb79a2fd57d6a480b922bc650d5cd15948753) Introduce non-terminals -// `builtinIdentifier` and `reservedWord`; update `typeAlias` to enable -// non-function type aliases; add missing `metadata` to formal parameter -// declarations; correct `symbolLiteral` to allow `VOID`; - -// v0.12 (82403371ac00ddf004be60fa7b705474d2864509) Cf. language issue #1341: -// correct `metadata`. Change `qualifiedName` such that it only includes the -// cases with a '.'; the remaining case is added where `qualifiedName` is used. -// -// v0.11 (67c703063d5b68c9e132edbaf34dfe375851f5a6) Corrections, mainly: -// `fieldFormalParameter` now allows `?` on the parameter type; cascade was -// reorganized in the spec, it is now reorganized similarly here; `?` was -// removed from argumentPart (null-aware invocation was never added). -// -// v0.10 (8ccdb9ae796d543e4ad8f339c847c02b09018d2d) Simplify grammar by making -// `constructorInvocation` an alternative in `primary`. -// -// v0.9 (f4d7951a88e1b738e22b768c3bc72bf1a1062365) Introduce abstract and -// external variables. -// -// v0.8 (a9ea9365ad8a3e3b59115bd889a55b6aa2c5a5fa) Change null-aware -// invocations of `operator []` and `operator []=` to not have a period. -// -// v0.7 (6826faf583f6a543b1a0e2e85bd6a8042607ce00) Introduce extension and -// mixin declarations. Revise rules about string literals and string -// interpolation. Reorganize "keywords" (built-in identifiers, reserved words, -// other words that are specified in the grammar and not parsed as IDENTIFIER) -// into explicitly marked groups. Change the cascade syntax to be -// compositional. -// -// v0.6 (a58052974ec2b4b334922c5227b043ed2b9c2cc5) Introduce syntax associated -// with null safety. -// -// v0.5 (56793b3d4714d4818d855a72074d5295489aef3f) Stop treating `ASYNC` as a -// conditional reserved word (only `AWAIT` and `YIELD` get this treatment). -// -// v0.4 Added support for 'unified collections' (spreads and control flow -// in collection literals). -// -// v0.3 Updated to use ANTLR v4 rather than antlr3. -// -// v0.2 Changed top level variable declarations to avoid redundant and -// misleading occurrence of (FINAL|CONST). -// -// v0.1 First version available in the SDK github repository. Covers the -// Dart language as specified in the language specification based on the -// many grammar rule snippets. That grammar was then adjusted to remove -// known issues (e.g., misplaced metadata) and to resolve ambiguities. - -grammar Dart; - -@parser::header{ -import java.util.Stack; -} - -@lexer::header{ -import java.util.Stack; -} - -@parser::members { - static String filePath = null; - static boolean errorHasOccurred = false; - - /// Must be invoked before the first error is reported for a library. - /// Will print the name of the library and indicate that it has errors. - static void prepareForErrors() { - errorHasOccurred = true; - System.err.println("Syntax error in " + filePath + ":"); - } - - /// Parse library, return true if success, false if errors occurred. - public boolean parseLibrary(String filePath) throws RecognitionException { - this.filePath = filePath; - errorHasOccurred = false; - startSymbol(); - return !errorHasOccurred; - } - - // Enable the parser to treat AWAIT/YIELD as keywords in the body of an - // `async`, `async*`, or `sync*` function. Access via methods below. - private Stack asyncEtcAreKeywords = new Stack(); - { asyncEtcAreKeywords.push(false); } - - // Use this to indicate that we are now entering an `async`, `async*`, - // or `sync*` function. - void startAsyncFunction() { asyncEtcAreKeywords.push(true); } - - // Use this to indicate that we are now entering a function which is - // neither `async`, `async*`, nor `sync*`. - void startNonAsyncFunction() { asyncEtcAreKeywords.push(false); } - - // Use this to indicate that we are now leaving any function. - void endFunction() { asyncEtcAreKeywords.pop(); } - - // Whether we can recognize AWAIT/YIELD as an identifier/typeIdentifier. - boolean asyncEtcPredicate(int tokenId) { - if (tokenId == AWAIT || tokenId == YIELD) { - return !asyncEtcAreKeywords.peek(); - } - return false; - } -} - -@lexer::members{ - public static final int BRACE_NORMAL = 1; - public static final int BRACE_SINGLE = 2; - public static final int BRACE_DOUBLE = 3; - public static final int BRACE_THREE_SINGLE = 4; - public static final int BRACE_THREE_DOUBLE = 5; - - // Enable the parser to handle string interpolations via brace matching. - // The top of the `braceLevels` stack describes the most recent unmatched - // '{'. This is needed in order to enable/disable certain lexer rules. - // - // NORMAL: Most recent unmatched '{' was not string literal related. - // SINGLE: Most recent unmatched '{' was `'...${`. - // DOUBLE: Most recent unmatched '{' was `"...${`. - // THREE_SINGLE: Most recent unmatched '{' was `'''...${`. - // THREE_DOUBLE: Most recent unmatched '{' was `"""...${`. - // - // Access via functions below. - private Stack braceLevels = new Stack(); - - // Whether we are currently in a string literal context, and which one. - boolean currentBraceLevel(int braceLevel) { - if (braceLevels.empty()) return false; - return braceLevels.peek() == braceLevel; - } - - // Use this to indicate that we are now entering a specific '{...}'. - // Call it after accepting the '{'. - void enterBrace() { - braceLevels.push(BRACE_NORMAL); - } - void enterBraceSingleQuote() { - braceLevels.push(BRACE_SINGLE); - } - void enterBraceDoubleQuote() { - braceLevels.push(BRACE_DOUBLE); - } - void enterBraceThreeSingleQuotes() { - braceLevels.push(BRACE_THREE_SINGLE); - } - void enterBraceThreeDoubleQuotes() { - braceLevels.push(BRACE_THREE_DOUBLE); - } - - // Use this to indicate that we are now exiting a specific '{...}', - // no matter which kind. Call it before accepting the '}'. - void exitBrace() { - // We might raise a parse error here if the stack is empty, but the - // parsing rules should ensure that we get a parse error anyway, and - // it is not a big problem for the spec parser even if it misinterprets - // the brace structure of some programs with syntax errors. - if (!braceLevels.empty()) braceLevels.pop(); - } -} - -// ---------------------------------------- Grammar rules. - -startSymbol - : libraryDefinition - | partDeclaration - ; - -libraryDefinition - : FEFF? SCRIPT_TAG? - libraryName? - importOrExport* - partDirective* - (metadata topLevelDefinition)* - EOF - ; - -topLevelDefinition - : classDeclaration - | mixinDeclaration - | extensionDeclaration - | enumType - | typeAlias - | EXTERNAL functionSignature ';' - | EXTERNAL getterSignature ';' - | EXTERNAL setterSignature ';' - | EXTERNAL finalVarOrType identifierList ';' - | getterSignature functionBody - | setterSignature functionBody - | functionSignature functionBody - | (FINAL | CONST) type? staticFinalDeclarationList ';' - | LATE FINAL type? initializedIdentifierList ';' - | LATE? varOrType identifier ('=' expression)? - (',' initializedIdentifier)* ';' - ; - -declaredIdentifier - : COVARIANT? finalConstVarOrType identifier - ; - -finalConstVarOrType - : LATE? FINAL type? - | CONST type? - | LATE? varOrType - ; - -finalVarOrType - : FINAL type? - | varOrType - ; - -varOrType - : VAR - | type - ; - -initializedIdentifier - : identifier ('=' expression)? - ; - -initializedIdentifierList - : initializedIdentifier (',' initializedIdentifier)* - ; - -functionSignature - : type? identifier formalParameterPart - ; - -functionBody - : '=>' { startNonAsyncFunction(); } expression { endFunction(); } ';' - | { startNonAsyncFunction(); } block { endFunction(); } - | ASYNC '=>' - { startAsyncFunction(); } expression { endFunction(); } ';' - | (ASYNC | ASYNC '*' | SYNC '*') - { startAsyncFunction(); } block { endFunction(); } - ; - -block - : LBRACE statements RBRACE - ; - -formalParameterPart - : typeParameters? formalParameterList - ; - -formalParameterList - : '(' ')' - | '(' normalFormalParameters ','? ')' - | '(' normalFormalParameters ',' optionalOrNamedFormalParameters ')' - | '(' optionalOrNamedFormalParameters ')' - ; - -normalFormalParameters - : normalFormalParameter (',' normalFormalParameter)* - ; - -optionalOrNamedFormalParameters - : optionalPositionalFormalParameters - | namedFormalParameters - ; - -optionalPositionalFormalParameters - : '[' defaultFormalParameter (',' defaultFormalParameter)* ','? ']' - ; - -namedFormalParameters - : LBRACE defaultNamedParameter (',' defaultNamedParameter)* ','? RBRACE - ; - -normalFormalParameter - : metadata normalFormalParameterNoMetadata - ; - -normalFormalParameterNoMetadata - : functionFormalParameter - | fieldFormalParameter - | simpleFormalParameter - | superFormalParameter - ; - -// NB: It is an anomaly that a functionFormalParameter cannot be FINAL. -functionFormalParameter - : COVARIANT? type? identifier formalParameterPart '?'? - ; - -simpleFormalParameter - : declaredIdentifier - | COVARIANT? identifier - ; - -// NB: It is an anomaly that VAR can be a return type (`var this.x()`). -fieldFormalParameter - : finalConstVarOrType? THIS '.' identifier (formalParameterPart '?'?)? - ; - -superFormalParameter - : type? SUPER '.' identifier (formalParameterPart '?'?)? - ; - -defaultFormalParameter - : normalFormalParameter ('=' expression)? - ; - -defaultNamedParameter - : REQUIRED? normalFormalParameter ((':' | '=') expression)? - ; - -typeWithParameters - : typeIdentifier typeParameters? - ; - -classDeclaration - : (classModifiers | mixinClassModifiers) - CLASS typeWithParameters superclass? interfaces? - LBRACE (metadata classMemberDeclaration)* RBRACE - | classModifiers CLASS mixinApplicationClass - ; - -classModifiers - : SEALED - | ABSTRACT? (BASE | INTERFACE | FINAL)? - ; - -mixinClassModifiers - : ABSTRACT? BASE? MIXIN - ; - -superclass - : EXTENDS typeNotVoidNotFunction mixins? - | mixins - ; - -mixins - : WITH typeNotVoidNotFunctionList - ; - -interfaces - : IMPLEMENTS typeNotVoidNotFunctionList - ; - -classMemberDeclaration - : methodSignature functionBody - | declaration ';' - ; - -mixinApplicationClass - : typeWithParameters '=' mixinApplication ';' - ; - -mixinDeclaration - : mixinModifier? MIXIN typeIdentifier typeParameters? - (ON typeNotVoidNotFunctionList)? interfaces? - LBRACE (metadata mixinMemberDeclaration)* RBRACE - ; - -mixinModifier - : SEALED - | BASE - | INTERFACE - | FINAL - ; - -// TODO: We might want to make this more strict. -mixinMemberDeclaration - : classMemberDeclaration - ; - -extensionDeclaration - : EXTENSION identifier? typeParameters? ON type - LBRACE (metadata extensionMemberDefinition)* RBRACE - ; - -// TODO: We might want to make this more strict. -extensionMemberDefinition - : classMemberDeclaration - ; - -methodSignature - : constructorSignature initializers - | factoryConstructorSignature - | STATIC? functionSignature - | STATIC? getterSignature - | STATIC? setterSignature - | operatorSignature - | constructorSignature - ; - -declaration - : EXTERNAL factoryConstructorSignature - | EXTERNAL constantConstructorSignature - | EXTERNAL constructorSignature - | (EXTERNAL STATIC?)? getterSignature - | (EXTERNAL STATIC?)? setterSignature - | (EXTERNAL STATIC?)? functionSignature - | EXTERNAL (STATIC? finalVarOrType | COVARIANT varOrType) identifierList - | ABSTRACT (finalVarOrType | COVARIANT varOrType) identifierList - | EXTERNAL? operatorSignature - | STATIC (FINAL | CONST) type? staticFinalDeclarationList - | STATIC LATE FINAL type? initializedIdentifierList - | STATIC LATE? varOrType initializedIdentifierList - | COVARIANT LATE FINAL type? identifierList - | COVARIANT LATE? varOrType initializedIdentifierList - | LATE? (FINAL type? | varOrType) initializedIdentifierList - | redirectingFactoryConstructorSignature - | constantConstructorSignature (redirection | initializers)? - | constructorSignature (redirection | initializers)? - ; - -staticFinalDeclarationList - : staticFinalDeclaration (',' staticFinalDeclaration)* - ; - -staticFinalDeclaration - : identifier '=' expression - ; - -operatorSignature - : type? OPERATOR operator formalParameterList - ; - -operator - : '~' - | binaryOperator - | '[' ']' - | '[' ']' '=' - ; - -binaryOperator - : multiplicativeOperator - | additiveOperator - | shiftOperator - | relationalOperator - | '==' - | bitwiseOperator - ; - -getterSignature - : type? GET identifier - ; - -setterSignature - : type? SET identifier formalParameterList - ; - -constructorSignature - : constructorName formalParameterList - ; - -constructorName - : typeIdentifier ('.' identifierOrNew)? - ; - -// TODO: Add this in the language specification, use it in grammar rules. -identifierOrNew - : identifier - | NEW - ; - -redirection - : ':' THIS ('.' identifierOrNew)? arguments - ; - -initializers - : ':' initializerListEntry (',' initializerListEntry)* - ; - -initializerListEntry - : SUPER arguments - | SUPER '.' identifierOrNew arguments - | fieldInitializer - | assertion - ; - -fieldInitializer - : (THIS '.')? identifier '=' initializerExpression - ; - -initializerExpression - : conditionalExpression - | cascade - ; - -factoryConstructorSignature - : CONST? FACTORY constructorName formalParameterList - ; - -redirectingFactoryConstructorSignature - : CONST? FACTORY constructorName formalParameterList '=' - constructorDesignation - ; - -constantConstructorSignature - : CONST constructorName formalParameterList - ; - -mixinApplication - : typeNotVoidNotFunction mixins interfaces? - ; - -enumType - : ENUM typeIdentifier typeParameters? mixins? interfaces? LBRACE - enumEntry (',' enumEntry)* (',')? - (';' (metadata classMemberDeclaration)*)? - RBRACE - ; - -enumEntry - : metadata identifier argumentPart? - | metadata identifier typeArguments? '.' identifierOrNew arguments - ; - -typeParameter - : metadata typeIdentifier (EXTENDS typeNotVoid)? - ; - -typeParameters - : '<' typeParameter (',' typeParameter)* '>' - ; - -metadata - : ('@' metadatum)* - ; - -metadatum - : constructorDesignation arguments - | identifier - | qualifiedName - ; - -expression - : patternAssignment - | functionExpression - | throwExpression - | assignableExpression assignmentOperator expression - | conditionalExpression - | cascade - ; - -expressionWithoutCascade - : functionExpressionWithoutCascade - | throwExpressionWithoutCascade - | assignableExpression assignmentOperator expressionWithoutCascade - | conditionalExpression - ; - -expressionList - : expression (',' expression)* - ; - -primary - : thisExpression - | SUPER unconditionalAssignableSelector - | SUPER argumentPart - | functionPrimary - | literal - | identifier - | newExpression - | constObjectExpression - | constructorInvocation - | '(' expression ')' - | constructorTearoff - | switchExpression - ; - -constructorInvocation - : typeName typeArguments '.' NEW arguments - | typeName '.' NEW arguments - ; - -literal - : nullLiteral - | booleanLiteral - | numericLiteral - | stringLiteral - | symbolLiteral - | setOrMapLiteral - | listLiteral - | recordLiteral - ; - -nullLiteral - : NULL - ; - -numericLiteral - : NUMBER - | HEX_NUMBER - ; - -booleanLiteral - : TRUE - | FALSE - ; - -stringLiteral - : (multiLineString | singleLineString)+ - ; - -setOrMapLiteral - : CONST? typeArguments? LBRACE elements? RBRACE - ; - -listLiteral - : CONST? typeArguments? '[' elements? ']' - ; - -recordLiteral - : CONST? recordLiteralNoConst - ; - -recordLiteralNoConst - : '(' ')' - | '(' expression ',' ')' - | '(' label expression ','? ')' - | '(' recordField (',' recordField)+ ','? ')' - ; - -recordField - : label? expression - ; - -elements - : element (',' element)* ','? - ; - -element - : expressionElement - | mapElement - | spreadElement - | ifElement - | forElement - ; - -expressionElement - : expression - ; - -mapElement - : expression ':' expression - ; - -spreadElement - : ('...' | '...?') expression - ; - -ifElement - : ifCondition element (ELSE element)? - ; - -forElement - : AWAIT? FOR '(' forLoopParts ')' element - ; - -constructorTearoff - : typeName typeArguments? '.' NEW - ; - -switchExpression - : SWITCH '(' expression ')' - LBRACE switchExpressionCase (',' switchExpressionCase)* ','? RBRACE - ; - -switchExpressionCase - : guardedPattern '=>' expression - ; - -throwExpression - : THROW expression - ; - -throwExpressionWithoutCascade - : THROW expressionWithoutCascade - ; - -functionExpression - : formalParameterPart functionExpressionBody - ; - -functionExpressionBody - : '=>' { startNonAsyncFunction(); } expression { endFunction(); } - | ASYNC '=>' { startAsyncFunction(); } expression { endFunction(); } - ; - -functionExpressionWithoutCascade - : formalParameterPart functionExpressionWithoutCascadeBody - ; - -functionExpressionWithoutCascadeBody - : '=>' { startNonAsyncFunction(); } - expressionWithoutCascade { endFunction(); } - | ASYNC '=>' { startAsyncFunction(); } - expressionWithoutCascade { endFunction(); } - ; - -functionPrimary - : formalParameterPart functionPrimaryBody - ; - -functionPrimaryBody - : { startNonAsyncFunction(); } block { endFunction(); } - | (ASYNC | ASYNC '*' | SYNC '*') - { startAsyncFunction(); } block { endFunction(); } - ; - -thisExpression - : THIS - ; - -newExpression - : NEW constructorDesignation arguments - ; - -constObjectExpression - : CONST constructorDesignation arguments - ; - -arguments - : '(' (argumentList ','?)? ')' - ; - -argumentList - : argument (',' argument)* - ; - -argument - : label? expression - ; - -cascade - : cascade '..' cascadeSection - | conditionalExpression ('?..' | '..') cascadeSection - ; - -cascadeSection - : cascadeSelector cascadeSectionTail - ; - -cascadeSelector - : '[' expression ']' - | identifier - ; - -cascadeSectionTail - : cascadeAssignment - | selector* (assignableSelector cascadeAssignment)? - ; - -cascadeAssignment - : assignmentOperator expressionWithoutCascade - ; - -assignmentOperator - : '=' - | compoundAssignmentOperator - ; - -compoundAssignmentOperator - : '*=' - | '/=' - | '~/=' - | '%=' - | '+=' - | '-=' - | '<<=' - | '>' '>' '>' '=' - | '>' '>' '=' - | '&=' - | '^=' - | '|=' - | '??=' - ; - -conditionalExpression - : ifNullExpression - ('?' expressionWithoutCascade ':' expressionWithoutCascade)? - ; - -ifNullExpression - : logicalOrExpression ('??' logicalOrExpression)* - ; - -logicalOrExpression - : logicalAndExpression ('||' logicalAndExpression)* - ; - -logicalAndExpression - : equalityExpression ('&&' equalityExpression)* - ; - -equalityExpression - : relationalExpression (equalityOperator relationalExpression)? - | SUPER equalityOperator relationalExpression - ; - -equalityOperator - : '==' - | '!=' - ; - -relationalExpression - : bitwiseOrExpression - (typeTest | typeCast | relationalOperator bitwiseOrExpression)? - | SUPER relationalOperator bitwiseOrExpression - ; - -relationalOperator - : '>' '=' - | '>' - | '<=' - | '<' - ; - -bitwiseOrExpression - : bitwiseXorExpression ('|' bitwiseXorExpression)* - | SUPER ('|' bitwiseXorExpression)+ - ; - -bitwiseXorExpression - : bitwiseAndExpression ('^' bitwiseAndExpression)* - | SUPER ('^' bitwiseAndExpression)+ - ; - -bitwiseAndExpression - : shiftExpression ('&' shiftExpression)* - | SUPER ('&' shiftExpression)+ - ; - -bitwiseOperator - : '&' - | '^' - | '|' - ; - -shiftExpression - : additiveExpression (shiftOperator additiveExpression)* - | SUPER (shiftOperator additiveExpression)+ - ; - -shiftOperator - : '<<' - | '>' '>' '>' - | '>' '>' - ; - -additiveExpression - : multiplicativeExpression (additiveOperator multiplicativeExpression)* - | SUPER (additiveOperator multiplicativeExpression)+ - ; - -additiveOperator - : '+' - | '-' - ; - -multiplicativeExpression - : unaryExpression (multiplicativeOperator unaryExpression)* - | SUPER (multiplicativeOperator unaryExpression)+ - ; - -multiplicativeOperator - : '*' - | '/' - | '%' - | '~/' - ; - -unaryExpression - : prefixOperator unaryExpression - | awaitExpression - | postfixExpression - | (minusOperator | tildeOperator) SUPER - | incrementOperator assignableExpression - ; - -prefixOperator - : minusOperator - | negationOperator - | tildeOperator - ; - -minusOperator - : '-' - ; - -negationOperator - : '!' - ; - -tildeOperator - : '~' - ; - -awaitExpression - : AWAIT unaryExpression - ; - -postfixExpression - : assignableExpression postfixOperator - | primary selector* - ; - -postfixOperator - : incrementOperator - ; - -selector - : '!' - | assignableSelector - | argumentPart - | typeArguments - ; - -argumentPart - : typeArguments? arguments - ; - -incrementOperator - : '++' - | '--' - ; - -assignableExpression - : SUPER unconditionalAssignableSelector - | primary assignableSelectorPart - | identifier - ; - -assignableSelectorPart - : selector* assignableSelector - ; - -unconditionalAssignableSelector - : '[' expression ']' - | '.' identifier - ; - -assignableSelector - : unconditionalAssignableSelector - | '?.' identifier - | '?' '[' expression ']' - ; - -identifier - : IDENTIFIER - | builtInIdentifier - | otherIdentifier - | { asyncEtcPredicate(getCurrentToken().getType()) }? (AWAIT|YIELD) - ; - -qualifiedName - : typeIdentifier '.' identifierOrNew - | typeIdentifier '.' typeIdentifier '.' identifierOrNew - ; - -typeIdentifier - : IDENTIFIER - | DYNAMIC // Built-in identifier that can be used as a type. - | otherIdentifier // Occur in grammar rules, are not built-in. - | { asyncEtcPredicate(getCurrentToken().getType()) }? (AWAIT|YIELD) - ; - -typeTest - : isOperator typeNotVoid - ; - -isOperator - : IS '!'? - ; - -typeCast - : asOperator typeNotVoid - ; - -asOperator - : AS - ; - -pattern - : logicalOrPattern - ; - -logicalOrPattern - : logicalAndPattern ('||' logicalAndPattern)* - ; - -logicalAndPattern - : relationalPattern ('&&' relationalPattern)* - ; - -relationalPattern - : (equalityOperator | relationalOperator) bitwiseOrExpression - | unaryPattern - ; - -unaryPattern - : castPattern - | nullCheckPattern - | nullAssertPattern - | primaryPattern - ; - -primaryPattern - : constantPattern - | variablePattern - | parenthesizedPattern - | listPattern - | mapPattern - | recordPattern - | objectPattern - ; - -castPattern - : primaryPattern AS type - ; - -nullCheckPattern - : primaryPattern '?' - ; - -nullAssertPattern - : primaryPattern '!' - ; - -constantPattern - : booleanLiteral - | nullLiteral - | '-'? numericLiteral - | stringLiteral - | symbolLiteral - | identifier - | qualifiedName - | constObjectExpression - | CONST typeArguments? '[' elements? ']' - | CONST typeArguments? LBRACE elements? RBRACE - | CONST '(' expression ')' - ; - -variablePattern - : (VAR | FINAL | FINAL? type)? identifier - ; - -parenthesizedPattern - : '(' pattern ')' - ; - -listPattern - : typeArguments? '[' listPatternElements? ']' - ; - -listPatternElements - : listPatternElement (',' listPatternElement)* ','? - ; - -listPatternElement - : pattern - | restPattern - ; - -restPattern - : '...' pattern? - ; - -mapPattern - : typeArguments? LBRACE mapPatternEntries? RBRACE - ; - -mapPatternEntries - : mapPatternEntry (',' mapPatternEntry)* ','? - ; - -mapPatternEntry - : expression ':' pattern - | '...' - ; - -recordPattern - : '(' patternFields? ')' - ; - -patternFields - : patternField (',' patternField)* ','? - ; - -patternField - : (identifier? ':')? pattern - ; - -objectPattern - : typeName typeArguments? '(' patternFields? ')' - ; - -patternVariableDeclaration - : (FINAL | VAR) outerPattern '=' expression - ; - -outerPattern - : parenthesizedPattern - | listPattern - | mapPattern - | recordPattern - | objectPattern - ; - -patternAssignment - : outerPattern '=' expression - ; - -statements - : statement* - ; - -statement - : label* nonLabelledStatement - ; - -// Exception in the language specification: An expressionStatement cannot -// start with LBRACE. We force anything that starts with LBRACE to be a block, -// which will prevent an expressionStatement from starting with LBRACE, and -// which will not interfere with the recognition of any other case. If we -// add another statement which can start with LBRACE we must adjust this -// check. -nonLabelledStatement - : block - | localVariableDeclaration - | forStatement - | whileStatement - | doStatement - | switchStatement - | ifStatement - | rethrowStatement - | tryStatement - | breakStatement - | continueStatement - | returnStatement - | localFunctionDeclaration - | assertStatement - | yieldStatement - | yieldEachStatement - | expressionStatement - ; - -expressionStatement - : expression? ';' - ; - -localVariableDeclaration - : metadata initializedVariableDeclaration ';' - | metadata patternVariableDeclaration ';' - ; - -initializedVariableDeclaration - : declaredIdentifier ('=' expression)? (',' initializedIdentifier)* - ; - -localFunctionDeclaration - : metadata functionSignature functionBody - ; - -ifStatement - : ifCondition statement (ELSE statement)? - ; - -ifCondition - : IF '(' expression (CASE guardedPattern)? ')' - ; - -forStatement - : AWAIT? FOR '(' forLoopParts ')' statement - ; - -// TODO: Include `metadata` in the pattern form? -forLoopParts - : metadata declaredIdentifier IN expression - | metadata identifier IN expression - | forInitializerStatement expression? ';' expressionList? - | metadata (FINAL | VAR) outerPattern IN expression - ; - -// The localVariableDeclaration cannot be CONST, but that can -// be enforced in a later phase, and the grammar allows it. -forInitializerStatement - : localVariableDeclaration - | expression? ';' - ; - -whileStatement - : WHILE '(' expression ')' statement - ; - -doStatement - : DO statement WHILE '(' expression ')' ';' - ; - -switchStatement - : SWITCH '(' expression ')' - LBRACE switchStatementCase* switchStatementDefault? RBRACE - ; - -switchStatementCase - : label* CASE guardedPattern ':' statements - ; - -guardedPattern - : pattern (WHEN expression)? - ; - -switchStatementDefault - : label* DEFAULT ':' statements - ; - -rethrowStatement - : RETHROW ';' - ; - -tryStatement - : TRY block (onPart+ finallyPart? | finallyPart) - ; - -onPart - : catchPart block - | ON typeNotVoid catchPart? block - ; - -catchPart - : CATCH '(' identifier (',' identifier)? ')' - ; - -finallyPart - : FINALLY block - ; - -returnStatement - : RETURN expression? ';' - ; - -label - : identifier ':' - ; - -breakStatement - : BREAK identifier? ';' - ; - -continueStatement - : CONTINUE identifier? ';' - ; - -yieldStatement - : YIELD expression ';' - ; - -yieldEachStatement - : YIELD '*' expression ';' - ; - -assertStatement - : assertion ';' - ; - -assertion - : ASSERT '(' expression (',' expression)? ','? ')' - ; - -libraryName - : metadata LIBRARY dottedIdentifierList? ';' - ; - -dottedIdentifierList - : identifier ('.' identifier)* - ; - -importOrExport - : libraryImport - | libraryExport - ; - -libraryImport - : metadata importSpecification - ; - -importSpecification - : IMPORT configurableUri (DEFERRED? AS identifier)? combinator* ';' - ; - -combinator - : SHOW identifierList - | HIDE identifierList - ; - -identifierList - : identifier (',' identifier)* - ; - -libraryExport - : metadata EXPORT uri combinator* ';' - ; - -partDirective - : metadata PART uri ';' - ; - -partHeader - : metadata PART OF (dottedIdentifierList | uri)';' - ; - -partDeclaration - : FEFF? partHeader (metadata topLevelDefinition)* EOF - ; - -uri - : stringLiteral - ; - -configurableUri - : uri configurationUri* - ; - -configurationUri - : IF '(' uriTest ')' uri - ; - -uriTest - : dottedIdentifierList ('==' stringLiteral)? - ; - -type - : functionType '?'? - | typeNotFunction - ; - -typeNotVoid - : functionType '?'? - | recordType '?'? - | typeNotVoidNotFunction '?'? - ; - -typeNotFunction - : typeNotVoidNotFunction '?'? - | recordType '?'? - | VOID - ; - -typeNotVoidNotFunction - : typeName typeArguments? - | FUNCTION - ; - -typeName - : typeIdentifier ('.' typeIdentifier)? - ; - -typeArguments - : '<' typeList '>' - ; - -typeList - : type (',' type)* - ; - -recordType - : '(' ')' - | '(' recordTypeFields ',' recordTypeNamedFields ')' - | '(' recordTypeFields ','? ')' - | '(' recordTypeNamedFields ')' - ; - -recordTypeFields - : recordTypeField (',' recordTypeField)* - ; - -recordTypeField - : metadata type identifier? - ; - -recordTypeNamedFields - : LBRACE recordTypeNamedField (',' recordTypeNamedField)* ','? RBRACE - ; - -recordTypeNamedField - : metadata typedIdentifier - ; - -typeNotVoidNotFunctionList - : typeNotVoidNotFunction (',' typeNotVoidNotFunction)* - ; - -typeAlias - : TYPEDEF typeIdentifier typeParameters? '=' type ';' - | TYPEDEF functionTypeAlias - ; - -functionTypeAlias - : functionPrefix formalParameterPart ';' - ; - -functionPrefix - : type identifier - | identifier - ; - -functionTypeTail - : FUNCTION typeParameters? parameterTypeList - ; - -functionTypeTails - : (functionTypeTail '?'?)* functionTypeTail - ; - -functionType - : typeNotFunction? functionTypeTails - ; - -parameterTypeList - : '(' ')' - | '(' normalParameterTypes ',' optionalParameterTypes ')' - | '(' normalParameterTypes ','? ')' - | '(' optionalParameterTypes ')' - ; - -normalParameterTypes - : normalParameterType (',' normalParameterType)* - ; - -normalParameterType - : metadata typedIdentifier - | metadata type - ; - -optionalParameterTypes - : optionalPositionalParameterTypes - | namedParameterTypes - ; - -optionalPositionalParameterTypes - : '[' normalParameterTypes ','? ']' - ; - -namedParameterTypes - : LBRACE namedParameterType (',' namedParameterType)* ','? RBRACE - ; - -namedParameterType - : metadata REQUIRED? typedIdentifier - ; - -typedIdentifier - : type identifier - ; - -constructorDesignation - : typeIdentifier - | qualifiedName - | typeName typeArguments ('.' identifierOrNew)? - ; - -symbolLiteral - : '#' (operator | (identifier ('.' identifier)*) | VOID) - ; - -singleLineString - : RAW_SINGLE_LINE_STRING - | SINGLE_LINE_STRING_SQ_BEGIN_END - | SINGLE_LINE_STRING_SQ_BEGIN_MID expression - (SINGLE_LINE_STRING_SQ_MID_MID expression)* - SINGLE_LINE_STRING_SQ_MID_END - | SINGLE_LINE_STRING_DQ_BEGIN_END - | SINGLE_LINE_STRING_DQ_BEGIN_MID expression - (SINGLE_LINE_STRING_DQ_MID_MID expression)* - SINGLE_LINE_STRING_DQ_MID_END - ; - -multiLineString - : RAW_MULTI_LINE_STRING - | MULTI_LINE_STRING_SQ_BEGIN_END - | MULTI_LINE_STRING_SQ_BEGIN_MID expression - (MULTI_LINE_STRING_SQ_MID_MID expression)* - MULTI_LINE_STRING_SQ_MID_END - | MULTI_LINE_STRING_DQ_BEGIN_END - | MULTI_LINE_STRING_DQ_BEGIN_MID expression - (MULTI_LINE_STRING_DQ_MID_MID expression)* - MULTI_LINE_STRING_DQ_MID_END - ; - -reservedWord - : ASSERT - | BREAK - | CASE - | CATCH - | CLASS - | CONST - | CONTINUE - | DEFAULT - | DO - | ELSE - | ENUM - | EXTENDS - | FALSE - | FINAL - | FINALLY - | FOR - | IF - | IN - | IS - | NEW - | NULL - | RETHROW - | RETURN - | SUPER - | SWITCH - | THIS - | THROW - | TRUE - | TRY - | VAR - | VOID - | WHILE - | WITH - ; - -builtInIdentifier - : ABSTRACT - | AS - | COVARIANT - | DEFERRED - | DYNAMIC - | EXPORT - | EXTENSION - | EXTERNAL - | FACTORY - | FUNCTION - | GET - | IMPLEMENTS - | IMPORT - | INTERFACE - | LATE - | LIBRARY - | OPERATOR - | MIXIN - | PART - | REQUIRED - | SET - | STATIC - | TYPEDEF - ; - -otherIdentifier - : ASYNC - | BASE - | HIDE - | OF - | ON - | SEALED - | SHOW - | SYNC - | WHEN - ; - -// ---------------------------------------- Lexer rules. - -fragment -LETTER - : 'a' .. 'z' - | 'A' .. 'Z' - ; - -fragment -DIGIT - : '0' .. '9' - ; - -fragment -EXPONENT - : ('e' | 'E') ('+' | '-')? DIGIT+ - ; - -fragment -HEX_DIGIT - : ('a' | 'b' | 'c' | 'd' | 'e' | 'f') - | ('A' | 'B' | 'C' | 'D' | 'E' | 'F') - | DIGIT - ; - -// Reserved words (if updated, update `reservedWord` as well). - -ASSERT - : 'assert' - ; - -BREAK - : 'break' - ; - -CASE - : 'case' - ; - -CATCH - : 'catch' - ; - -CLASS - : 'class' - ; - -CONST - : 'const' - ; - -CONTINUE - : 'continue' - ; - -DEFAULT - : 'default' - ; - -DO - : 'do' - ; - -ELSE - : 'else' - ; - -ENUM - : 'enum' - ; - -EXTENDS - : 'extends' - ; - -FALSE - : 'false' - ; - -FINAL - : 'final' - ; - -FINALLY - : 'finally' - ; - -FOR - : 'for' - ; - -IF - : 'if' - ; - -IN - : 'in' - ; - -IS - : 'is' - ; - -NEW - : 'new' - ; - -NULL - : 'null' - ; - -RETHROW - : 'rethrow' - ; - -RETURN - : 'return' - ; - -SUPER - : 'super' - ; - -SWITCH - : 'switch' - ; - -THIS - : 'this' - ; - -THROW - : 'throw' - ; - -TRUE - : 'true' - ; - -TRY - : 'try' - ; - -VAR - : 'var' - ; - -VOID - : 'void' - ; - -WHILE - : 'while' - ; - -WITH - : 'with' - ; - -// Built-in identifiers (if updated, update `builtInIdentifier` as well). - -ABSTRACT - : 'abstract' - ; - -AS - : 'as' - ; - -COVARIANT - : 'covariant' - ; - -DEFERRED - : 'deferred' - ; - -DYNAMIC - : 'dynamic' - ; - -EXPORT - : 'export' - ; - -EXTENSION - : 'extension' - ; - -EXTERNAL - : 'external' - ; - -FACTORY - : 'factory' - ; - -FUNCTION - : 'Function' - ; - -GET - : 'get' - ; - -IMPLEMENTS - : 'implements' - ; - -IMPORT - : 'import' - ; - -INTERFACE - : 'interface' - ; - -LATE - : 'late' - ; - -LIBRARY - : 'library' - ; - -OPERATOR - : 'operator' - ; - -MIXIN - : 'mixin' - ; - -PART - : 'part' - ; - -REQUIRED - : 'required' - ; - -SET - : 'set' - ; - -STATIC - : 'static' - ; - -TYPEDEF - : 'typedef' - ; - -// "Contextual keywords". - -AWAIT - : 'await' - ; - -YIELD - : 'yield' - ; - -// Other words used in the grammar (if updated, update `otherIdentifier`, too). - -ASYNC - : 'async' - ; - -BASE - : 'base' - ; - -HIDE - : 'hide' - ; - -OF - : 'of' - ; - -ON - : 'on' - ; - -SEALED - : 'sealed' - ; - -SHOW - : 'show' - ; - -SYNC - : 'sync' - ; - -WHEN - : 'when' - ; - -// Lexical tokens that are not words. - -NUMBER - : DIGIT+ '.' DIGIT+ EXPONENT? - | DIGIT+ EXPONENT? - | '.' DIGIT+ EXPONENT? - ; - -HEX_NUMBER - : '0x' HEX_DIGIT+ - | '0X' HEX_DIGIT+ - ; - -RAW_SINGLE_LINE_STRING - : 'r' '\'' (~('\'' | '\r' | '\n'))* '\'' - | 'r' '"' (~('"' | '\r' | '\n'))* '"' - ; - -RAW_MULTI_LINE_STRING - : 'r' '"""' (.)*? '"""' - | 'r' '\'\'\'' (.)*? '\'\'\'' - ; - -fragment -SIMPLE_STRING_INTERPOLATION - : '$' IDENTIFIER_NO_DOLLAR - ; - -fragment -ESCAPE_SEQUENCE - : '\\n' - | '\\r' - | '\\b' - | '\\t' - | '\\v' - | '\\x' HEX_DIGIT HEX_DIGIT - | '\\u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT - | '\\u{' HEX_DIGIT_SEQUENCE '}' - ; - -fragment -HEX_DIGIT_SEQUENCE - : HEX_DIGIT HEX_DIGIT? HEX_DIGIT? - HEX_DIGIT? HEX_DIGIT? HEX_DIGIT? - ; - -fragment -STRING_CONTENT_COMMON - : ~('\\' | '\'' | '"' | '$' | '\r' | '\n') - | ESCAPE_SEQUENCE - | '\\' ~('n' | 'r' | 'b' | 't' | 'v' | 'x' | 'u' | '\r' | '\n') - | SIMPLE_STRING_INTERPOLATION - ; - -fragment -STRING_CONTENT_SQ - : STRING_CONTENT_COMMON - | '"' - ; - -SINGLE_LINE_STRING_SQ_BEGIN_END - : '\'' STRING_CONTENT_SQ* '\'' - ; - -SINGLE_LINE_STRING_SQ_BEGIN_MID - : '\'' STRING_CONTENT_SQ* '${' { enterBraceSingleQuote(); } - ; - -SINGLE_LINE_STRING_SQ_MID_MID - : { currentBraceLevel(BRACE_SINGLE) }? - { exitBrace(); } '}' STRING_CONTENT_SQ* '${' - { enterBraceSingleQuote(); } - ; - -SINGLE_LINE_STRING_SQ_MID_END - : { currentBraceLevel(BRACE_SINGLE) }? - { exitBrace(); } '}' STRING_CONTENT_SQ* '\'' - ; - -fragment -STRING_CONTENT_DQ - : STRING_CONTENT_COMMON - | '\'' - ; - -SINGLE_LINE_STRING_DQ_BEGIN_END - : '"' STRING_CONTENT_DQ* '"' - ; - -SINGLE_LINE_STRING_DQ_BEGIN_MID - : '"' STRING_CONTENT_DQ* '${' { enterBraceDoubleQuote(); } - ; - -SINGLE_LINE_STRING_DQ_MID_MID - : { currentBraceLevel(BRACE_DOUBLE) }? - { exitBrace(); } '}' STRING_CONTENT_DQ* '${' - { enterBraceDoubleQuote(); } - ; - -SINGLE_LINE_STRING_DQ_MID_END - : { currentBraceLevel(BRACE_DOUBLE) }? - { exitBrace(); } '}' STRING_CONTENT_DQ* '"' - ; - -fragment -QUOTES_SQ - : - | '\'' - | '\'\'' - ; - -// Read string contents, which may be almost anything, but stop when seeing -// '\'\'\'' and when seeing '${'. We do this by allowing all other -// possibilities including escapes, simple interpolation, and fewer than -// three '\''. -fragment -STRING_CONTENT_TSQ - : QUOTES_SQ - (STRING_CONTENT_COMMON | '"' | '\r' | '\n' | '\\\r' | '\\\n') - ; - -MULTI_LINE_STRING_SQ_BEGIN_END - : '\'\'\'' STRING_CONTENT_TSQ* '\'\'\'' - ; - -MULTI_LINE_STRING_SQ_BEGIN_MID - : '\'\'\'' STRING_CONTENT_TSQ* QUOTES_SQ '${' - { enterBraceThreeSingleQuotes(); } - ; - -MULTI_LINE_STRING_SQ_MID_MID - : { currentBraceLevel(BRACE_THREE_SINGLE) }? - { exitBrace(); } '}' STRING_CONTENT_TSQ* QUOTES_SQ '${' - { enterBraceThreeSingleQuotes(); } - ; - -MULTI_LINE_STRING_SQ_MID_END - : { currentBraceLevel(BRACE_THREE_SINGLE) }? - { exitBrace(); } '}' STRING_CONTENT_TSQ* '\'\'\'' - ; - -fragment -QUOTES_DQ - : - | '"' - | '""' - ; - -// Read string contents, which may be almost anything, but stop when seeing -// '"""' and when seeing '${'. We do this by allowing all other possibilities -// including escapes, simple interpolation, and fewer-than-three '"'. -fragment -STRING_CONTENT_TDQ - : QUOTES_DQ - (STRING_CONTENT_COMMON | '\'' | '\r' | '\n' | '\\\r' | '\\\n') - ; - -MULTI_LINE_STRING_DQ_BEGIN_END - : '"""' STRING_CONTENT_TDQ* '"""' - ; - -MULTI_LINE_STRING_DQ_BEGIN_MID - : '"""' STRING_CONTENT_TDQ* QUOTES_DQ '${' - { enterBraceThreeDoubleQuotes(); } - ; - -MULTI_LINE_STRING_DQ_MID_MID - : { currentBraceLevel(BRACE_THREE_DOUBLE) }? - { exitBrace(); } '}' STRING_CONTENT_TDQ* QUOTES_DQ '${' - { enterBraceThreeDoubleQuotes(); } - ; - -MULTI_LINE_STRING_DQ_MID_END - : { currentBraceLevel(BRACE_THREE_DOUBLE) }? - { exitBrace(); } '}' STRING_CONTENT_TDQ* '"""' - ; - -LBRACE - : '{' { enterBrace(); } - ; - -RBRACE - : { currentBraceLevel(BRACE_NORMAL) }? { exitBrace(); } '}' - ; - -fragment -IDENTIFIER_START_NO_DOLLAR - : LETTER - | '_' - ; - -fragment -IDENTIFIER_PART_NO_DOLLAR - : IDENTIFIER_START_NO_DOLLAR - | DIGIT - ; - -fragment -IDENTIFIER_NO_DOLLAR - : IDENTIFIER_START_NO_DOLLAR IDENTIFIER_PART_NO_DOLLAR* - ; - -fragment -IDENTIFIER_START - : IDENTIFIER_START_NO_DOLLAR - | '$' - ; - -fragment -IDENTIFIER_PART - : IDENTIFIER_START - | DIGIT - ; - -SCRIPT_TAG - : '#!' (~('\r' | '\n'))* NEWLINE - ; - -IDENTIFIER - : IDENTIFIER_START IDENTIFIER_PART* - ; - -SINGLE_LINE_COMMENT - : '//' (~('\r' | '\n'))* NEWLINE? - { skip(); } - ; - -MULTI_LINE_COMMENT - : '/*' (MULTI_LINE_COMMENT | .)*? '*/' - { skip(); } - ; - -fragment -NEWLINE - : ('\r' | '\n' | '\r\n') - ; - -FEFF - : '\uFEFF' - ; - -WS - : (' ' | '\t' | '\r' | '\n')+ - { skip(); } - ; diff --git a/pubspec.yaml b/pubspec.yaml index f8fba57..21cad26 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: _internal environment: - sdk: '>=3.0.0-0 <3.2.0' + sdk: '>=3.2.0 <4.0.0' dependencies: - path: ^1.8.3 \ No newline at end of file + path: ^1.9.1 \ No newline at end of file diff --git a/tester/pubspec.yaml b/tester/pubspec.yaml index a460e5d..330f539 100644 --- a/tester/pubspec.yaml +++ b/tester/pubspec.yaml @@ -1,9 +1,9 @@ name: tree_sitter_dart_tester environment: - sdk: '>=3.0.0-0 <3.2.0' + sdk: '>=3.1.5 <4.0.0' dependencies: - glob: ^2.1.1 - path: ^1.8.3 + glob: ^2.1.3 + path: ^1.9.1 dev_dependencies: - dcli: ^2.1.0 \ No newline at end of file + dcli: ^7.1.1 \ No newline at end of file diff --git a/tree_sitter/CHANGELOG.md b/tree_sitter/CHANGELOG.md index bb8f838..06d424a 100644 --- a/tree_sitter/CHANGELOG.md +++ b/tree_sitter/CHANGELOG.md @@ -1,3 +1,14 @@ +## 0.1.3 (Unreleased) +- Added `@Native` annotation support for the Dart language grammar +- Added `Parser.fromLanguage()` constructor for use with native bindings +- Added `treeSitterDart()` function for efficient static linking (Dart 3.0+) +- Updated examples and tests to demonstrate both dynamic and native binding approaches +- Configured ffigen to generate `@Native` annotations for tree-sitter C API bindings +- Updated api_config.yaml and parser_config.yaml to enable ffi-native code generation +- Regenerated bindings with `@Native` annotations (requires Dart SDK 3.0+) +- Updated SDK constraint to <4.0.0 for compatibility with newer Dart versions +- Fixed TSInputEncoding enum to match tree-sitter 0.26.x API changes + ## 0.1.2 - Fix issue with string encoding length diff --git a/tree_sitter/README.md b/tree_sitter/README.md index c0dd5d5..7cd7826 100644 --- a/tree_sitter/README.md +++ b/tree_sitter/README.md @@ -11,23 +11,76 @@ Then set the library location using: TreeSitterConfig.setLibraryPath('/path/to/libtree-sitter.so'); ``` -Next create a parser for your language by first creating a dynamic library for your language's grammar. +## Usage + +### Option 1: Native Binding (Recommended for Dart 3.0+) + +Use the `@Native` annotation binding for efficient static linking: + +```dart +import 'package:tree_sitter/tree_sitter.dart'; + +void main() { + // Use the native binding for the Dart language grammar + final parser = Parser.fromLanguage(treeSitterDart()); + final program = "class A {}"; + final tree = parser.parse(program); + print(tree.root.string); +} +``` + +This approach provides: +- Better performance through static linking +- Compile-time symbol validation +- Zero runtime overhead for library loading +- Simplified deployment + +### Option 2: Dynamic Library Loading (Traditional) + +Load the language grammar dynamically at runtime: -Then load and use the parser: ```dart -import 'package:ffi/ffi.dart'; +import 'package:dylib/dylib.dart'; import 'package:tree_sitter/tree_sitter.dart'; void main() { - final parser = - Parser(sharedLibrary: 'libdart.dylib', entryPoint: 'tree_sitter_dart'); + final parser = Parser( + sharedLibrary: resolveDylibPath('dart', path: Directory.current.path), + entryPoint: 'tree_sitter_dart'); final program = "class A {}"; final tree = parser.parse(program); print(tree.root.string); } ``` -You can access other apis via the top level `treeSitterApi` ffi wrapper +## Regenerating Bindings + +The tree-sitter C API bindings are configured to use `@Native` annotations for better performance (Dart 3.0+). To regenerate the bindings after updating the tree-sitter library: + +```bash +# Make sure the tree-sitter submodule is initialized +git submodule update --init --recursive + +# Build tree-sitter library +cd tree-sitter && make && cd .. + +# Regenerate bindings +dart run ffigen --config api_config.yaml +dart run ffigen --config parser_config.yaml +``` + +This will generate updated bindings in `lib/src/generated_bindings.dart` and `lib/src/parser_generated_bindings.dart` with `@Native` annotations enabled. + +**Note:** The generated bindings use `@Native` without asset IDs, which means they rely on `DynamicLibrary.process()` for symbol resolution. You'll need to preload the libraries when running tests: + +```bash +export LD_PRELOAD="./libtree-sitter.so:./libdart.so" +dart test +``` + +## Advanced Usage + +You can access other APIs via the top level `treeSitterApi` ffi wrapper. Or you can help contribute to an idiomatic dart api on top of the ffi wrapper. Many of the apis are started but not complete. diff --git a/tree_sitter/api_config.yaml b/tree_sitter/api_config.yaml index c53bcf9..adadaec 100644 --- a/tree_sitter/api_config.yaml +++ b/tree_sitter/api_config.yaml @@ -13,4 +13,16 @@ functions: - 'ts_tree_delete' - 'ts_tree_cursor_delete' - 'ts_query_delete' - - 'ts_query_cursor_delete' \ No newline at end of file + - 'ts_query_cursor_delete' +silence-enum-warning: true +# Configure ffigen to generate @Native annotations (Dart 3.0+) +# This enables efficient static linking instead of dynamic library loading +# Note: assetId is omitted to allow fallback to process lookup +ffi-native: +llvm-path: + - '/usr/lib/llvm-18' + - '/usr/lib/llvm-17' + - '/usr/lib/llvm-16' + - '/usr/lib/llvm-14' + - '/usr/lib/llvm-11' + - '/usr/local/opt/llvm' \ No newline at end of file diff --git a/tree_sitter/example/tree_sitter.dart b/tree_sitter/example/tree_sitter.dart index c635c52..35b976d 100644 --- a/tree_sitter/example/tree_sitter.dart +++ b/tree_sitter/example/tree_sitter.dart @@ -1,13 +1,22 @@ +// ignore_for_file: avoid_print + import 'dart:io'; import 'package:dylib/dylib.dart'; import 'package:tree_sitter/tree_sitter.dart'; void main() { + print('=== Example 1: Using dynamic library loading (traditional) ==='); + exampleWithDynamicLoading(); + + print('\n=== Example 2: Using @Native annotation (Dart 3.0+) ==='); + exampleWithNativeBinding(); +} + +void exampleWithDynamicLoading() { final parser = Parser( sharedLibrary: resolveDylibPath('dart', path: Directory.current.path), entryPoint: 'tree_sitter_dart'); - // const program = "class A {}"; const program = r""" void main() { test('', () { @@ -20,3 +29,18 @@ void main() { print(tree.root.string); print(parser.getText(tree.root.child(0).namedChild(0))); } + +void exampleWithNativeBinding() { + // Use the @Native binding for efficient static linking (Dart 3.0+) + final parser = Parser.fromLanguage(treeSitterDart()); + const program = r""" +class MyClass { + void myMethod() { + print('Hello from Dart!'); + } +} +"""; + final tree = parser.parse(program); + print(tree.root.string); + print('Root node type: ${tree.root.nodeType}'); +} diff --git a/tree_sitter/lib/src/dart_language.dart b/tree_sitter/lib/src/dart_language.dart new file mode 100644 index 0000000..b36062e --- /dev/null +++ b/tree_sitter/lib/src/dart_language.dart @@ -0,0 +1,35 @@ +/// Native binding for tree-sitter-dart language grammar. +/// +/// This module provides a `@Native` binding to the tree_sitter_dart() +/// function which returns the Dart language grammar for use with +/// tree-sitter parsers. +library; + +import 'dart:ffi'; + +import '../tree_sitter.dart' show TSLanguage; + +/// Get the tree-sitter Language for Dart grammar. +/// +/// This function returns a pointer to the TSLanguage struct that defines +/// the Dart grammar. It uses Dart's `@Native` annotation for efficient +/// static linking to the native C function. +/// +/// This is the preferred method for accessing the Dart language grammar +/// when using Dart 3.0+, as it provides better performance through +/// static linking compared to dynamic library loading. +/// +/// Example: +/// ```dart +/// import 'package:tree_sitter/tree_sitter.dart'; +/// +/// void main() { +/// // Use the native binding with Parser.fromLanguage +/// final parser = Parser.fromLanguage(treeSitterDart()); +/// final tree = parser.parse('class A {}'); +/// print(tree.root.string); +/// } +/// ``` +@Native Function()>( + symbol: 'tree_sitter_dart', isLeaf: true) +external Pointer treeSitterDart(); diff --git a/tree_sitter/lib/src/generated_bindings.dart b/tree_sitter/lib/src/generated_bindings.dart index 523358f..39d230e 100644 --- a/tree_sitter/lib/src/generated_bindings.dart +++ b/tree_sitter/lib/src/generated_bindings.dart @@ -3,2197 +3,1567 @@ // Generated by `package:ffigen`. // ignore_for_file: type=lint import 'dart:ffi' as ffi; - -/// C Bindings to the TreeSitter library -class TreeSitter { - /// Holds the symbol lookup function. - final ffi.Pointer Function(String symbolName) - _lookup; - - /// The symbols are looked up in [dynamicLibrary]. - TreeSitter(ffi.DynamicLibrary dynamicLibrary) - : _lookup = dynamicLibrary.lookup; - - /// The symbols are looked up with [lookup]. - TreeSitter.fromLookup( - ffi.Pointer Function(String symbolName) - lookup) - : _lookup = lookup; - - /// Create a new parser. - ffi.Pointer ts_parser_new() { - return _ts_parser_new(); - } - - late final _ts_parser_newPtr = - _lookup Function()>>( - 'ts_parser_new'); - late final _ts_parser_new = - _ts_parser_newPtr.asFunction Function()>(); - - /// Delete the parser, freeing all of the memory that it used. - void ts_parser_delete( - ffi.Pointer parser, - ) { - return _ts_parser_delete( - parser, - ); - } - - late final _ts_parser_deletePtr = - _lookup)>>( - 'ts_parser_delete'); - late final _ts_parser_delete = - _ts_parser_deletePtr.asFunction)>(); - - /// Set the language that the parser should use for parsing. - /// - /// Returns a boolean indicating whether or not the language was successfully - /// assigned. True means assignment succeeded. False means there was a version - /// mismatch: the language was generated with an incompatible version of the - /// Tree-sitter CLI. Check the language's version using `ts_language_version` - /// and compare it to this library's `TREE_SITTER_LANGUAGE_VERSION` and - /// `TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION` constants. - bool ts_parser_set_language( - ffi.Pointer self, - ffi.Pointer language, - ) { - return _ts_parser_set_language( - self, - language, - ); - } - - late final _ts_parser_set_languagePtr = _lookup< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, - ffi.Pointer)>>('ts_parser_set_language'); - late final _ts_parser_set_language = _ts_parser_set_languagePtr.asFunction< - bool Function(ffi.Pointer, ffi.Pointer)>(); - - /// Get the parser's current language. - ffi.Pointer ts_parser_language( - ffi.Pointer self, - ) { - return _ts_parser_language( - self, - ); - } - - late final _ts_parser_languagePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('ts_parser_language'); - late final _ts_parser_language = _ts_parser_languagePtr - .asFunction Function(ffi.Pointer)>(); - - /// Set the ranges of text that the parser should include when parsing. - /// - /// By default, the parser will always include entire documents. This function - /// allows you to parse only a *portion* of a document but still return a syntax - /// tree whose ranges match up with the document as a whole. You can also pass - /// multiple disjoint ranges. - /// - /// The second and third parameters specify the location and length of an array - /// of ranges. The parser does *not* take ownership of these ranges; it copies - /// the data, so it doesn't matter how these ranges are allocated. - /// - /// If `length` is zero, then the entire document will be parsed. Otherwise, - /// the given ranges must be ordered from earliest to latest in the document, - /// and they must not overlap. That is, the following must hold for all - /// `i` < `length - 1`: ranges[i].end_byte <= ranges[i + 1].start_byte - /// - /// If this requirement is not satisfied, the operation will fail, the ranges - /// will not be assigned, and this function will return `false`. On success, - /// this function returns `true` - bool ts_parser_set_included_ranges( - ffi.Pointer self, - ffi.Pointer ranges, - int length, - ) { - return _ts_parser_set_included_ranges( - self, - ranges, - length, - ); - } - - late final _ts_parser_set_included_rangesPtr = _lookup< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, ffi.Pointer, - ffi.Uint32)>>('ts_parser_set_included_ranges'); - late final _ts_parser_set_included_ranges = - _ts_parser_set_included_rangesPtr.asFunction< - bool Function(ffi.Pointer, ffi.Pointer, int)>(); - - /// Get the ranges of text that the parser will include when parsing. - /// - /// The returned pointer is owned by the parser. The caller should not free it - /// or write to it. The length of the array will be written to the given - /// `length` pointer. - ffi.Pointer ts_parser_included_ranges( - ffi.Pointer self, - ffi.Pointer length, - ) { - return _ts_parser_included_ranges( - self, - length, - ); - } - - late final _ts_parser_included_rangesPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>>('ts_parser_included_ranges'); - late final _ts_parser_included_ranges = - _ts_parser_included_rangesPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - /// Use the parser to parse some source code and create a syntax tree. - /// - /// If you are parsing this document for the first time, pass `NULL` for the - /// `old_tree` parameter. Otherwise, if you have already parsed an earlier - /// version of this document and the document has since been edited, pass the - /// previous syntax tree so that the unchanged parts of it can be reused. - /// This will save time and memory. For this to work correctly, you must have - /// already edited the old syntax tree using the `ts_tree_edit` function in a - /// way that exactly matches the source code changes. - /// - /// The `TSInput` parameter lets you specify how to read the text. It has the - /// following three fields: - /// 1. `read`: A function to retrieve a chunk of text at a given byte offset - /// and (row, column) position. The function should return a pointer to the - /// text and write its length to the `bytes_read` pointer. The parser does - /// not take ownership of this buffer; it just borrows it until it has - /// finished reading it. The function should write a zero value to the - /// `bytes_read` pointer to indicate the end of the document. - /// 2. `payload`: An arbitrary pointer that will be passed to each invocation - /// of the `read` function. - /// 3. `encoding`: An indication of how the text is encoded. Either - /// `TSInputEncodingUTF8` or `TSInputEncodingUTF16`. - /// - /// This function returns a syntax tree on success, and `NULL` on failure. There - /// are three possible reasons for failure: - /// 1. The parser does not have a language assigned. Check for this using the - /// `ts_parser_language` function. - /// 2. Parsing was cancelled due to a timeout that was set by an earlier call to - /// the `ts_parser_set_timeout_micros` function. You can resume parsing from - /// where the parser left out by calling `ts_parser_parse` again with the - /// same arguments. Or you can start parsing from scratch by first calling - /// `ts_parser_reset`. - /// 3. Parsing was cancelled using a cancellation flag that was set by an - /// earlier call to `ts_parser_set_cancellation_flag`. You can resume parsing - /// from where the parser left out by calling `ts_parser_parse` again with - /// the same arguments. - ffi.Pointer ts_parser_parse( - ffi.Pointer self, - ffi.Pointer old_tree, - TSInput input, - ) { - return _ts_parser_parse( - self, - old_tree, - input, - ); - } - - late final _ts_parser_parsePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer, TSInput)>>('ts_parser_parse'); - late final _ts_parser_parse = _ts_parser_parsePtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer, TSInput)>(); - - /// Use the parser to parse some source code stored in one contiguous buffer. - /// The first two parameters are the same as in the `ts_parser_parse` function - /// above. The second two parameters indicate the location of the buffer and its - /// length in bytes. - ffi.Pointer ts_parser_parse_string( - ffi.Pointer self, - ffi.Pointer old_tree, - ffi.Pointer string, - int length, - ) { - return _ts_parser_parse_string( - self, - old_tree, - string, - length, - ); - } - - late final _ts_parser_parse_stringPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32)>>('ts_parser_parse_string'); - late final _ts_parser_parse_string = _ts_parser_parse_stringPtr.asFunction< - ffi.Pointer Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer, int)>(); - - /// Use the parser to parse some source code stored in one contiguous buffer with - /// a given encoding. The first four parameters work the same as in the - /// `ts_parser_parse_string` method above. The final parameter indicates whether - /// the text is encoded as UTF8 or UTF16. - ffi.Pointer ts_parser_parse_string_encoding( - ffi.Pointer self, - ffi.Pointer old_tree, - ffi.Pointer string, - int length, - int encoding, - ) { - return _ts_parser_parse_string_encoding( +import '' as self; + +/// Create a new parser. +@ffi.Native Function()>() +external ffi.Pointer ts_parser_new(); + +/// Delete the parser, freeing all of the memory that it used. +@ffi.Native)>() +external void ts_parser_delete( + ffi.Pointer self, +); + +/// Get the parser's current language. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_parser_language( + ffi.Pointer self, +); + +/// Set the language that the parser should use for parsing. +/// +/// Returns a boolean indicating whether or not the language was successfully +/// assigned. True means assignment succeeded. False means there was a version +/// mismatch: the language was generated with an incompatible version of the +/// Tree-sitter CLI. Check the language's ABI version using [`ts_language_abi_version`] +/// and compare it to this library's [`TREE_SITTER_LANGUAGE_VERSION`] and +/// [`TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION`] constants. +@ffi.Native, ffi.Pointer)>() +external bool ts_parser_set_language( + ffi.Pointer self, + ffi.Pointer language, +); + +/// Set the ranges of text that the parser should include when parsing. +/// +/// By default, the parser will always include entire documents. This function +/// allows you to parse only a *portion* of a document but still return a syntax +/// tree whose ranges match up with the document as a whole. You can also pass +/// multiple disjoint ranges. +/// +/// The second and third parameters specify the location and length of an array +/// of ranges. The parser does *not* take ownership of these ranges; it copies +/// the data, so it doesn't matter how these ranges are allocated. +/// +/// If `count` is zero, then the entire document will be parsed. Otherwise, +/// the given ranges must be ordered from earliest to latest in the document, +/// and they must not overlap. That is, the following must hold for all: +/// +/// `i < count - 1`: `ranges[i].end_byte <= ranges[i + 1].start_byte` +/// +/// If this requirement is not satisfied, the operation will fail, the ranges +/// will not be assigned, and this function will return `false`. On success, +/// this function returns `true` +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, ffi.Pointer, ffi.Uint32)>() +external bool ts_parser_set_included_ranges( + ffi.Pointer self, + ffi.Pointer ranges, + int count, +); + +/// Get the ranges of text that the parser will include when parsing. +/// +/// The returned pointer is owned by the parser. The caller should not free it +/// or write to it. The length of the array will be written to the given +/// `count` pointer. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>() +external ffi.Pointer ts_parser_included_ranges( + ffi.Pointer self, + ffi.Pointer count, +); + +/// Use the parser to parse some source code and create a syntax tree. +/// +/// If you are parsing this document for the first time, pass `NULL` for the +/// `old_tree` parameter. Otherwise, if you have already parsed an earlier +/// version of this document and the document has since been edited, pass the +/// previous syntax tree so that the unchanged parts of it can be reused. +/// This will save time and memory. For this to work correctly, you must have +/// already edited the old syntax tree using the [`ts_tree_edit`] function in a +/// way that exactly matches the source code changes. +/// +/// The [`TSInput`] parameter lets you specify how to read the text. It has the +/// following three fields: +/// 1. [`read`]: A function to retrieve a chunk of text at a given byte offset +/// and (row, column) position. The function should return a pointer to the +/// text and write its length to the [`bytes_read`] pointer. The parser does +/// not take ownership of this buffer; it just borrows it until it has +/// finished reading it. The function should write a zero value to the +/// [`bytes_read`] pointer to indicate the end of the document. +/// 2. [`payload`]: An arbitrary pointer that will be passed to each invocation +/// of the [`read`] function. +/// 3. [`encoding`]: An indication of how the text is encoded. Either +/// `TSInputEncodingUTF8` or `TSInputEncodingUTF16`. +/// +/// This function returns a syntax tree on success, and `NULL` on failure. There +/// are four possible reasons for failure: +/// 1. The parser does not have a language assigned. Check for this using the +/// [`ts_parser_language`] function. +/// 2. Parsing was cancelled due to a timeout that was set by an earlier call to +/// the [`ts_parser_set_timeout_micros`] function. You can resume parsing from +/// where the parser left out by calling [`ts_parser_parse`] again with the +/// same arguments. Or you can start parsing from scratch by first calling +/// [`ts_parser_reset`]. +/// 3. Parsing was cancelled using a cancellation flag that was set by an +/// earlier call to [`ts_parser_set_cancellation_flag`]. You can resume parsing +/// from where the parser left out by calling [`ts_parser_parse`] again with +/// the same arguments. +/// 4. Parsing was cancelled due to the progress callback returning true. This callback +/// is passed in [`ts_parser_parse_with_options`] inside the [`TSParseOptions`] struct. +/// +/// [`read`]: TSInput::read +/// [`payload`]: TSInput::payload +/// [`encoding`]: TSInput::encoding +/// [`bytes_read`]: TSInput::read +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, TSInput)>() +external ffi.Pointer ts_parser_parse( + ffi.Pointer self, + ffi.Pointer old_tree, + TSInput input, +); + +/// Use the parser to parse some source code and create a syntax tree, with some options. +/// +/// See [`ts_parser_parse`] for more details. +/// +/// See [`TSParseOptions`] for more details on the options. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, TSInput, TSParseOptions)>() +external ffi.Pointer ts_parser_parse_with_options( + ffi.Pointer self, + ffi.Pointer old_tree, + TSInput input, + TSParseOptions parse_options, +); + +/// Use the parser to parse some source code stored in one contiguous buffer. +/// The first two parameters are the same as in the [`ts_parser_parse`] function +/// above. The second two parameters indicate the location of the buffer and its +/// length in bytes. +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer, ffi.Uint32)>() +external ffi.Pointer ts_parser_parse_string( + ffi.Pointer self, + ffi.Pointer old_tree, + ffi.Pointer string, + int length, +); + +/// Use the parser to parse some source code stored in one contiguous buffer with +/// a given encoding. The first four parameters work the same as in the +/// [`ts_parser_parse_string`] method above. The final parameter indicates whether +/// the text is encoded as UTF8 or UTF16. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.UnsignedInt)>(symbol: 'ts_parser_parse_string_encoding') +external ffi.Pointer _ts_parser_parse_string_encoding( + ffi.Pointer self, + ffi.Pointer old_tree, + ffi.Pointer string, + int length, + int encoding, +); + +ffi.Pointer ts_parser_parse_string_encoding( + ffi.Pointer self, + ffi.Pointer old_tree, + ffi.Pointer string, + int length, + TSInputEncoding encoding, +) => + _ts_parser_parse_string_encoding( self, old_tree, string, length, - encoding, - ); - } - - late final _ts_parser_parse_string_encodingPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Int32)>>('ts_parser_parse_string_encoding'); - late final _ts_parser_parse_string_encoding = - _ts_parser_parse_string_encodingPtr.asFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer, int, int)>(); - - /// Instruct the parser to start the next parse from the beginning. - /// - /// If the parser previously failed because of a timeout or a cancellation, then - /// by default, it will resume where it left off on the next call to - /// `ts_parser_parse` or other parsing functions. If you don't want to resume, - /// and instead intend to use this parser to parse some other document, you must - /// call `ts_parser_reset` first. - void ts_parser_reset( - ffi.Pointer self, - ) { - return _ts_parser_reset( - self, - ); - } - - late final _ts_parser_resetPtr = - _lookup)>>( - 'ts_parser_reset'); - late final _ts_parser_reset = - _ts_parser_resetPtr.asFunction)>(); - - /// Set the maximum duration in microseconds that parsing should be allowed to - /// take before halting. - /// - /// If parsing takes longer than this, it will halt early, returning NULL. - /// See `ts_parser_parse` for more information. - void ts_parser_set_timeout_micros( - ffi.Pointer self, - int timeout, - ) { - return _ts_parser_set_timeout_micros( - self, - timeout, - ); - } - - late final _ts_parser_set_timeout_microsPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Uint64)>>('ts_parser_set_timeout_micros'); - late final _ts_parser_set_timeout_micros = _ts_parser_set_timeout_microsPtr - .asFunction, int)>(); - - /// Get the duration in microseconds that parsing is allowed to take. - int ts_parser_timeout_micros( - ffi.Pointer self, - ) { - return _ts_parser_timeout_micros( - self, - ); - } - - late final _ts_parser_timeout_microsPtr = - _lookup)>>( - 'ts_parser_timeout_micros'); - late final _ts_parser_timeout_micros = _ts_parser_timeout_microsPtr - .asFunction)>(); - - /// Set the parser's current cancellation flag pointer. - /// - /// If a non-null pointer is assigned, then the parser will periodically read - /// from this pointer during parsing. If it reads a non-zero value, it will - /// halt early, returning NULL. See `ts_parser_parse` for more information. - void ts_parser_set_cancellation_flag( - ffi.Pointer self, - ffi.Pointer flag, - ) { - return _ts_parser_set_cancellation_flag( - self, - flag, - ); - } - - late final _ts_parser_set_cancellation_flagPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Pointer)>>('ts_parser_set_cancellation_flag'); - late final _ts_parser_set_cancellation_flag = - _ts_parser_set_cancellation_flagPtr.asFunction< - void Function(ffi.Pointer, ffi.Pointer)>(); - - /// Get the parser's current cancellation flag pointer. - ffi.Pointer ts_parser_cancellation_flag( - ffi.Pointer self, - ) { - return _ts_parser_cancellation_flag( - self, - ); - } - - late final _ts_parser_cancellation_flagPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('ts_parser_cancellation_flag'); - late final _ts_parser_cancellation_flag = _ts_parser_cancellation_flagPtr - .asFunction Function(ffi.Pointer)>(); - - /// Set the logger that a parser should use during parsing. - /// - /// The parser does not take ownership over the logger payload. If a logger was - /// previously assigned, the caller is responsible for releasing any memory - /// owned by the previous logger. - void ts_parser_set_logger( - ffi.Pointer self, - TSLogger logger, - ) { - return _ts_parser_set_logger( - self, - logger, - ); - } - - late final _ts_parser_set_loggerPtr = _lookup< - ffi - .NativeFunction, TSLogger)>>( - 'ts_parser_set_logger'); - late final _ts_parser_set_logger = _ts_parser_set_loggerPtr - .asFunction, TSLogger)>(); - - /// Get the parser's current logger. - TSLogger ts_parser_logger( - ffi.Pointer self, - ) { - return _ts_parser_logger( - self, - ); - } - - late final _ts_parser_loggerPtr = - _lookup)>>( - 'ts_parser_logger'); - late final _ts_parser_logger = _ts_parser_loggerPtr - .asFunction)>(); - - /// Set the file descriptor to which the parser should write debugging graphs - /// during parsing. The graphs are formatted in the DOT language. You may want - /// to pipe these graphs directly to a `dot(1)` process in order to generate - /// SVG output. You can turn off this logging by passing a negative number. - void ts_parser_print_dot_graphs( - ffi.Pointer self, - int file, - ) { - return _ts_parser_print_dot_graphs( - self, - file, - ); - } - - late final _ts_parser_print_dot_graphsPtr = _lookup< - ffi - .NativeFunction, ffi.Int)>>( - 'ts_parser_print_dot_graphs'); - late final _ts_parser_print_dot_graphs = _ts_parser_print_dot_graphsPtr - .asFunction, int)>(); - - /// Create a shallow copy of the syntax tree. This is very fast. - /// - /// You need to copy a syntax tree in order to use it on more than one thread at - /// a time, as syntax trees are not thread safe. - ffi.Pointer ts_tree_copy( - ffi.Pointer self, - ) { - return _ts_tree_copy( - self, - ); - } - - late final _ts_tree_copyPtr = _lookup< - ffi - .NativeFunction Function(ffi.Pointer)>>( - 'ts_tree_copy'); - late final _ts_tree_copy = _ts_tree_copyPtr - .asFunction Function(ffi.Pointer)>(); - - /// Delete the syntax tree, freeing all of the memory that it used. - void ts_tree_delete( - ffi.Pointer self, - ) { - return _ts_tree_delete( - self, - ); - } - - late final _ts_tree_deletePtr = - _lookup)>>( - 'ts_tree_delete'); - late final _ts_tree_delete = - _ts_tree_deletePtr.asFunction)>(); - - /// Get the root node of the syntax tree. - TSNode ts_tree_root_node( - ffi.Pointer self, - ) { - return _ts_tree_root_node( - self, - ); - } - - late final _ts_tree_root_nodePtr = - _lookup)>>( - 'ts_tree_root_node'); - late final _ts_tree_root_node = - _ts_tree_root_nodePtr.asFunction)>(); - - /// Get the root node of the syntax tree, but with its position - /// shifted forward by the given offset. - TSNode ts_tree_root_node_with_offset( - ffi.Pointer self, - int offset_bytes, - TSPoint offset_point, - ) { - return _ts_tree_root_node_with_offset( - self, - offset_bytes, - offset_point, - ); - } - - late final _ts_tree_root_node_with_offsetPtr = _lookup< - ffi.NativeFunction< - TSNode Function(ffi.Pointer, ffi.Uint32, - TSPoint)>>('ts_tree_root_node_with_offset'); - late final _ts_tree_root_node_with_offset = _ts_tree_root_node_with_offsetPtr - .asFunction, int, TSPoint)>(); - - /// Get the language that was used to parse the syntax tree. - ffi.Pointer ts_tree_language( - ffi.Pointer arg0, - ) { - return _ts_tree_language( - arg0, - ); - } - - late final _ts_tree_languagePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('ts_tree_language'); - late final _ts_tree_language = _ts_tree_languagePtr - .asFunction Function(ffi.Pointer)>(); - - /// Get the array of included ranges that was used to parse the syntax tree. - /// - /// The returned pointer must be freed by the caller. - ffi.Pointer ts_tree_included_ranges( - ffi.Pointer arg0, - ffi.Pointer length, - ) { - return _ts_tree_included_ranges( - arg0, - length, - ); - } - - late final _ts_tree_included_rangesPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer)>>('ts_tree_included_ranges'); - late final _ts_tree_included_ranges = _ts_tree_included_rangesPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Pointer)>(); - - /// Edit the syntax tree to keep it in sync with source code that has been - /// edited. - /// - /// You must describe the edit both in terms of byte offsets and in terms of - /// (row, column) coordinates. - void ts_tree_edit( - ffi.Pointer self, - ffi.Pointer edit, - ) { - return _ts_tree_edit( - self, - edit, - ); - } - - late final _ts_tree_editPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>>('ts_tree_edit'); - late final _ts_tree_edit = _ts_tree_editPtr.asFunction< - void Function(ffi.Pointer, ffi.Pointer)>(); - - /// Compare an old edited syntax tree to a new syntax tree representing the same - /// document, returning an array of ranges whose syntactic structure has changed. - /// - /// For this to work correctly, the old syntax tree must have been edited such - /// that its ranges match up to the new tree. Generally, you'll want to call - /// this function right after calling one of the `ts_parser_parse` functions. - /// You need to pass the old tree that was passed to parse, as well as the new - /// tree that was returned from that function. - /// - /// The returned array is allocated using `malloc` and the caller is responsible - /// for freeing it using `free`. The length of the array will be written to the - /// given `length` pointer. - ffi.Pointer ts_tree_get_changed_ranges( - ffi.Pointer old_tree, - ffi.Pointer new_tree, - ffi.Pointer length, - ) { - return _ts_tree_get_changed_ranges( - old_tree, - new_tree, - length, - ); - } - - late final _ts_tree_get_changed_rangesPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('ts_tree_get_changed_ranges'); - late final _ts_tree_get_changed_ranges = - _ts_tree_get_changed_rangesPtr.asFunction< - ffi.Pointer Function(ffi.Pointer, - ffi.Pointer, ffi.Pointer)>(); - - /// Write a DOT graph describing the syntax tree to the given file. - void ts_tree_print_dot_graph( - ffi.Pointer arg0, - int file_descriptor, - ) { - return _ts_tree_print_dot_graph( - arg0, - file_descriptor, - ); - } - - late final _ts_tree_print_dot_graphPtr = _lookup< - ffi.NativeFunction, ffi.Int)>>( - 'ts_tree_print_dot_graph'); - late final _ts_tree_print_dot_graph = _ts_tree_print_dot_graphPtr - .asFunction, int)>(); - - /// Get the node's type as a null-terminated string. - ffi.Pointer ts_node_type( - TSNode arg0, - ) { - return _ts_node_type( - arg0, - ); - } - - late final _ts_node_typePtr = - _lookup Function(TSNode)>>( - 'ts_node_type'); - late final _ts_node_type = - _ts_node_typePtr.asFunction Function(TSNode)>(); - - /// Get the node's type as a numerical id. - int ts_node_symbol( - TSNode arg0, - ) { - return _ts_node_symbol( - arg0, - ); - } - - late final _ts_node_symbolPtr = - _lookup>('ts_node_symbol'); - late final _ts_node_symbol = - _ts_node_symbolPtr.asFunction(); - - /// Get the node's start byte. - int ts_node_start_byte( - TSNode arg0, - ) { - return _ts_node_start_byte( - arg0, - ); - } - - late final _ts_node_start_bytePtr = - _lookup>( - 'ts_node_start_byte'); - late final _ts_node_start_byte = - _ts_node_start_bytePtr.asFunction(); - - /// Get the node's start position in terms of rows and columns. - TSPoint ts_node_start_point( - TSNode arg0, - ) { - return _ts_node_start_point( - arg0, - ); - } - - late final _ts_node_start_pointPtr = - _lookup>( - 'ts_node_start_point'); - late final _ts_node_start_point = - _ts_node_start_pointPtr.asFunction(); - - /// Get the node's end byte. - int ts_node_end_byte( - TSNode arg0, - ) { - return _ts_node_end_byte( - arg0, - ); - } - - late final _ts_node_end_bytePtr = - _lookup>( - 'ts_node_end_byte'); - late final _ts_node_end_byte = - _ts_node_end_bytePtr.asFunction(); - - /// Get the node's end position in terms of rows and columns. - TSPoint ts_node_end_point( - TSNode arg0, - ) { - return _ts_node_end_point( - arg0, - ); - } - - late final _ts_node_end_pointPtr = - _lookup>( - 'ts_node_end_point'); - late final _ts_node_end_point = - _ts_node_end_pointPtr.asFunction(); - - /// Get an S-expression representing the node as a string. - /// - /// This string is allocated with `malloc` and the caller is responsible for - /// freeing it using `free`. - ffi.Pointer ts_node_string( - TSNode arg0, - ) { - return _ts_node_string( - arg0, - ); - } - - late final _ts_node_stringPtr = - _lookup Function(TSNode)>>( - 'ts_node_string'); - late final _ts_node_string = - _ts_node_stringPtr.asFunction Function(TSNode)>(); - - /// Check if the node is null. Functions like `ts_node_child` and - /// `ts_node_next_sibling` will return a null node to indicate that no such node - /// was found. - bool ts_node_is_null( - TSNode arg0, - ) { - return _ts_node_is_null( - arg0, - ); - } - - late final _ts_node_is_nullPtr = - _lookup>('ts_node_is_null'); - late final _ts_node_is_null = - _ts_node_is_nullPtr.asFunction(); - - /// Check if the node is *named*. Named nodes correspond to named rules in the - /// grammar, whereas *anonymous* nodes correspond to string literals in the - /// grammar. - bool ts_node_is_named( - TSNode arg0, - ) { - return _ts_node_is_named( - arg0, - ); - } - - late final _ts_node_is_namedPtr = - _lookup>( - 'ts_node_is_named'); - late final _ts_node_is_named = - _ts_node_is_namedPtr.asFunction(); - - /// Check if the node is *missing*. Missing nodes are inserted by the parser in - /// order to recover from certain kinds of syntax errors. - bool ts_node_is_missing( - TSNode arg0, - ) { - return _ts_node_is_missing( - arg0, - ); - } - - late final _ts_node_is_missingPtr = - _lookup>( - 'ts_node_is_missing'); - late final _ts_node_is_missing = - _ts_node_is_missingPtr.asFunction(); - - /// Check if the node is *extra*. Extra nodes represent things like comments, - /// which are not required the grammar, but can appear anywhere. - bool ts_node_is_extra( - TSNode arg0, - ) { - return _ts_node_is_extra( - arg0, - ); - } - - late final _ts_node_is_extraPtr = - _lookup>( - 'ts_node_is_extra'); - late final _ts_node_is_extra = - _ts_node_is_extraPtr.asFunction(); - - /// Check if a syntax node has been edited. - bool ts_node_has_changes( - TSNode arg0, - ) { - return _ts_node_has_changes( - arg0, - ); - } - - late final _ts_node_has_changesPtr = - _lookup>( - 'ts_node_has_changes'); - late final _ts_node_has_changes = - _ts_node_has_changesPtr.asFunction(); - - /// Check if the node is a syntax error or contains any syntax errors. - bool ts_node_has_error( - TSNode arg0, - ) { - return _ts_node_has_error( - arg0, - ); - } - - late final _ts_node_has_errorPtr = - _lookup>( - 'ts_node_has_error'); - late final _ts_node_has_error = - _ts_node_has_errorPtr.asFunction(); - - /// Get the node's immediate parent. - TSNode ts_node_parent( - TSNode arg0, - ) { - return _ts_node_parent( - arg0, - ); - } - - late final _ts_node_parentPtr = - _lookup>('ts_node_parent'); - late final _ts_node_parent = - _ts_node_parentPtr.asFunction(); - - /// Get the node's child at the given index, where zero represents the first - /// child. - TSNode ts_node_child( - TSNode arg0, - int arg1, - ) { - return _ts_node_child( - arg0, - arg1, - ); - } - - late final _ts_node_childPtr = - _lookup>( - 'ts_node_child'); - late final _ts_node_child = - _ts_node_childPtr.asFunction(); - - /// Get the field name for node's child at the given index, where zero represents - /// the first child. Returns NULL, if no field is found. - ffi.Pointer ts_node_field_name_for_child( - TSNode arg0, - int arg1, - ) { - return _ts_node_field_name_for_child( - arg0, - arg1, - ); - } - - late final _ts_node_field_name_for_childPtr = _lookup< - ffi - .NativeFunction Function(TSNode, ffi.Uint32)>>( - 'ts_node_field_name_for_child'); - late final _ts_node_field_name_for_child = _ts_node_field_name_for_childPtr - .asFunction Function(TSNode, int)>(); - - /// Get the node's number of children. - int ts_node_child_count( - TSNode arg0, - ) { - return _ts_node_child_count( - arg0, - ); - } - - late final _ts_node_child_countPtr = - _lookup>( - 'ts_node_child_count'); - late final _ts_node_child_count = - _ts_node_child_countPtr.asFunction(); - - /// Get the node's *named* child at the given index. - /// - /// See also `ts_node_is_named`. - TSNode ts_node_named_child( - TSNode arg0, - int arg1, - ) { - return _ts_node_named_child( - arg0, - arg1, - ); - } - - late final _ts_node_named_childPtr = - _lookup>( - 'ts_node_named_child'); - late final _ts_node_named_child = - _ts_node_named_childPtr.asFunction(); - - /// Get the node's number of *named* children. - /// - /// See also `ts_node_is_named`. - int ts_node_named_child_count( - TSNode arg0, - ) { - return _ts_node_named_child_count( - arg0, - ); - } - - late final _ts_node_named_child_countPtr = - _lookup>( - 'ts_node_named_child_count'); - late final _ts_node_named_child_count = - _ts_node_named_child_countPtr.asFunction(); - - /// Get the node's child with the given field name. - TSNode ts_node_child_by_field_name( - TSNode self, - ffi.Pointer field_name, - int field_name_length, - ) { - return _ts_node_child_by_field_name( - self, - field_name, - field_name_length, - ); - } - - late final _ts_node_child_by_field_namePtr = _lookup< - ffi.NativeFunction< - TSNode Function(TSNode, ffi.Pointer, - ffi.Uint32)>>('ts_node_child_by_field_name'); - late final _ts_node_child_by_field_name = _ts_node_child_by_field_namePtr - .asFunction, int)>(); - - /// Get the node's child with the given numerical field id. - /// - /// You can convert a field name to an id using the - /// `ts_language_field_id_for_name` function. - TSNode ts_node_child_by_field_id( - TSNode arg0, - int arg1, - ) { - return _ts_node_child_by_field_id( - arg0, - arg1, - ); - } - - late final _ts_node_child_by_field_idPtr = - _lookup>( - 'ts_node_child_by_field_id'); - late final _ts_node_child_by_field_id = - _ts_node_child_by_field_idPtr.asFunction(); - - /// Get the node's next / previous sibling. - TSNode ts_node_next_sibling( - TSNode arg0, - ) { - return _ts_node_next_sibling( - arg0, - ); - } - - late final _ts_node_next_siblingPtr = - _lookup>( - 'ts_node_next_sibling'); - late final _ts_node_next_sibling = - _ts_node_next_siblingPtr.asFunction(); - - TSNode ts_node_prev_sibling( - TSNode arg0, - ) { - return _ts_node_prev_sibling( - arg0, - ); - } - - late final _ts_node_prev_siblingPtr = - _lookup>( - 'ts_node_prev_sibling'); - late final _ts_node_prev_sibling = - _ts_node_prev_siblingPtr.asFunction(); - - /// Get the node's next / previous *named* sibling. - TSNode ts_node_next_named_sibling( - TSNode arg0, - ) { - return _ts_node_next_named_sibling( - arg0, - ); - } - - late final _ts_node_next_named_siblingPtr = - _lookup>( - 'ts_node_next_named_sibling'); - late final _ts_node_next_named_sibling = - _ts_node_next_named_siblingPtr.asFunction(); - - TSNode ts_node_prev_named_sibling( - TSNode arg0, - ) { - return _ts_node_prev_named_sibling( - arg0, - ); - } - - late final _ts_node_prev_named_siblingPtr = - _lookup>( - 'ts_node_prev_named_sibling'); - late final _ts_node_prev_named_sibling = - _ts_node_prev_named_siblingPtr.asFunction(); - - /// Get the node's first child that extends beyond the given byte offset. - TSNode ts_node_first_child_for_byte( - TSNode arg0, - int arg1, - ) { - return _ts_node_first_child_for_byte( - arg0, - arg1, - ); - } - - late final _ts_node_first_child_for_bytePtr = - _lookup>( - 'ts_node_first_child_for_byte'); - late final _ts_node_first_child_for_byte = _ts_node_first_child_for_bytePtr - .asFunction(); - - /// Get the node's first named child that extends beyond the given byte offset. - TSNode ts_node_first_named_child_for_byte( - TSNode arg0, - int arg1, - ) { - return _ts_node_first_named_child_for_byte( - arg0, - arg1, - ); - } - - late final _ts_node_first_named_child_for_bytePtr = - _lookup>( - 'ts_node_first_named_child_for_byte'); - late final _ts_node_first_named_child_for_byte = - _ts_node_first_named_child_for_bytePtr - .asFunction(); - - /// Get the smallest node within this node that spans the given range of bytes - /// or (row, column) positions. - TSNode ts_node_descendant_for_byte_range( - TSNode arg0, - int arg1, - int arg2, - ) { - return _ts_node_descendant_for_byte_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_node_descendant_for_byte_rangePtr = _lookup< - ffi.NativeFunction>( - 'ts_node_descendant_for_byte_range'); - late final _ts_node_descendant_for_byte_range = - _ts_node_descendant_for_byte_rangePtr - .asFunction(); - - TSNode ts_node_descendant_for_point_range( - TSNode arg0, - TSPoint arg1, - TSPoint arg2, - ) { - return _ts_node_descendant_for_point_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_node_descendant_for_point_rangePtr = - _lookup>( - 'ts_node_descendant_for_point_range'); - late final _ts_node_descendant_for_point_range = - _ts_node_descendant_for_point_rangePtr - .asFunction(); - - /// Get the smallest named node within this node that spans the given range of - /// bytes or (row, column) positions. - TSNode ts_node_named_descendant_for_byte_range( - TSNode arg0, - int arg1, - int arg2, - ) { - return _ts_node_named_descendant_for_byte_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_node_named_descendant_for_byte_rangePtr = _lookup< - ffi.NativeFunction>( - 'ts_node_named_descendant_for_byte_range'); - late final _ts_node_named_descendant_for_byte_range = - _ts_node_named_descendant_for_byte_rangePtr - .asFunction(); - - TSNode ts_node_named_descendant_for_point_range( - TSNode arg0, - TSPoint arg1, - TSPoint arg2, - ) { - return _ts_node_named_descendant_for_point_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_node_named_descendant_for_point_rangePtr = - _lookup>( - 'ts_node_named_descendant_for_point_range'); - late final _ts_node_named_descendant_for_point_range = - _ts_node_named_descendant_for_point_rangePtr - .asFunction(); - - /// Edit the node to keep it in-sync with source code that has been edited. - /// - /// This function is only rarely needed. When you edit a syntax tree with the - /// `ts_tree_edit` function, all of the nodes that you retrieve from the tree - /// afterward will already reflect the edit. You only need to use `ts_node_edit` - /// when you have a `TSNode` instance that you want to keep and continue to use - /// after an edit. - void ts_node_edit( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) { - return _ts_node_edit( - arg0, - arg1, - ); - } - - late final _ts_node_editPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, ffi.Pointer)>>('ts_node_edit'); - late final _ts_node_edit = _ts_node_editPtr.asFunction< - void Function(ffi.Pointer, ffi.Pointer)>(); - - /// Check if two nodes are identical. - bool ts_node_eq( - TSNode arg0, - TSNode arg1, - ) { - return _ts_node_eq( - arg0, - arg1, - ); - } - - late final _ts_node_eqPtr = - _lookup>( - 'ts_node_eq'); - late final _ts_node_eq = - _ts_node_eqPtr.asFunction(); - - /// Create a new tree cursor starting from the given node. - /// - /// A tree cursor allows you to walk a syntax tree more efficiently than is - /// possible using the `TSNode` functions. It is a mutable object that is always - /// on a certain syntax node, and can be moved imperatively to different nodes. - TSTreeCursor ts_tree_cursor_new( - TSNode arg0, - ) { - return _ts_tree_cursor_new( - arg0, - ); - } - - late final _ts_tree_cursor_newPtr = - _lookup>( - 'ts_tree_cursor_new'); - late final _ts_tree_cursor_new = - _ts_tree_cursor_newPtr.asFunction(); - - /// Delete a tree cursor, freeing all of the memory that it used. - void ts_tree_cursor_delete( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_delete( - arg0, - ); - } - - late final _ts_tree_cursor_deletePtr = - _lookup)>>( - 'ts_tree_cursor_delete'); - late final _ts_tree_cursor_delete = _ts_tree_cursor_deletePtr - .asFunction)>(); - - /// Re-initialize a tree cursor to start at a different node. - void ts_tree_cursor_reset( - ffi.Pointer arg0, - TSNode arg1, - ) { - return _ts_tree_cursor_reset( - arg0, - arg1, - ); - } - - late final _ts_tree_cursor_resetPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, TSNode)>>('ts_tree_cursor_reset'); - late final _ts_tree_cursor_reset = _ts_tree_cursor_resetPtr - .asFunction, TSNode)>(); - - /// Get the tree cursor's current node. - TSNode ts_tree_cursor_current_node( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_current_node( - arg0, - ); - } - - late final _ts_tree_cursor_current_nodePtr = - _lookup)>>( - 'ts_tree_cursor_current_node'); - late final _ts_tree_cursor_current_node = _ts_tree_cursor_current_nodePtr - .asFunction)>(); - - /// Get the field name of the tree cursor's current node. - /// - /// This returns `NULL` if the current node doesn't have a field. - /// See also `ts_node_child_by_field_name`. - ffi.Pointer ts_tree_cursor_current_field_name( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_current_field_name( - arg0, - ); - } - - late final _ts_tree_cursor_current_field_namePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer)>>('ts_tree_cursor_current_field_name'); - late final _ts_tree_cursor_current_field_name = - _ts_tree_cursor_current_field_namePtr.asFunction< - ffi.Pointer Function(ffi.Pointer)>(); - - /// Get the field id of the tree cursor's current node. - /// - /// This returns zero if the current node doesn't have a field. - /// See also `ts_node_child_by_field_id`, `ts_language_field_id_for_name`. - int ts_tree_cursor_current_field_id( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_current_field_id( - arg0, - ); - } - - late final _ts_tree_cursor_current_field_idPtr = _lookup< - ffi.NativeFunction)>>( - 'ts_tree_cursor_current_field_id'); - late final _ts_tree_cursor_current_field_id = - _ts_tree_cursor_current_field_idPtr - .asFunction)>(); - - /// Move the cursor to the parent of its current node. - /// - /// This returns `true` if the cursor successfully moved, and returns `false` - /// if there was no parent node (the cursor was already on the root node). - bool ts_tree_cursor_goto_parent( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_goto_parent( - arg0, - ); - } - - late final _ts_tree_cursor_goto_parentPtr = - _lookup)>>( - 'ts_tree_cursor_goto_parent'); - late final _ts_tree_cursor_goto_parent = _ts_tree_cursor_goto_parentPtr - .asFunction)>(); - - /// Move the cursor to the next sibling of its current node. - /// - /// This returns `true` if the cursor successfully moved, and returns `false` - /// if there was no next sibling node. - bool ts_tree_cursor_goto_next_sibling( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_goto_next_sibling( - arg0, - ); - } - - late final _ts_tree_cursor_goto_next_siblingPtr = - _lookup)>>( - 'ts_tree_cursor_goto_next_sibling'); - late final _ts_tree_cursor_goto_next_sibling = - _ts_tree_cursor_goto_next_siblingPtr - .asFunction)>(); - - /// Move the cursor to the first child of its current node. - /// - /// This returns `true` if the cursor successfully moved, and returns `false` - /// if there were no children. - bool ts_tree_cursor_goto_first_child( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_goto_first_child( - arg0, - ); - } - - late final _ts_tree_cursor_goto_first_childPtr = - _lookup)>>( - 'ts_tree_cursor_goto_first_child'); - late final _ts_tree_cursor_goto_first_child = - _ts_tree_cursor_goto_first_childPtr - .asFunction)>(); - - /// Move the cursor to the first child of its current node that extends beyond - /// the given byte offset or point. - /// - /// This returns the index of the child node if one was found, and returns -1 - /// if no such child was found. - int ts_tree_cursor_goto_first_child_for_byte( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_tree_cursor_goto_first_child_for_byte( - arg0, - arg1, - ); - } - - late final _ts_tree_cursor_goto_first_child_for_bytePtr = _lookup< - ffi.NativeFunction< - ffi.Int64 Function(ffi.Pointer, - ffi.Uint32)>>('ts_tree_cursor_goto_first_child_for_byte'); - late final _ts_tree_cursor_goto_first_child_for_byte = - _ts_tree_cursor_goto_first_child_for_bytePtr - .asFunction, int)>(); - - int ts_tree_cursor_goto_first_child_for_point( - ffi.Pointer arg0, - TSPoint arg1, - ) { - return _ts_tree_cursor_goto_first_child_for_point( - arg0, - arg1, - ); - } - - late final _ts_tree_cursor_goto_first_child_for_pointPtr = _lookup< - ffi.NativeFunction< - ffi.Int64 Function(ffi.Pointer, - TSPoint)>>('ts_tree_cursor_goto_first_child_for_point'); - late final _ts_tree_cursor_goto_first_child_for_point = - _ts_tree_cursor_goto_first_child_for_pointPtr - .asFunction, TSPoint)>(); - - TSTreeCursor ts_tree_cursor_copy( - ffi.Pointer arg0, - ) { - return _ts_tree_cursor_copy( - arg0, - ); - } - - late final _ts_tree_cursor_copyPtr = _lookup< - ffi.NativeFunction)>>( - 'ts_tree_cursor_copy'); - late final _ts_tree_cursor_copy = _ts_tree_cursor_copyPtr - .asFunction)>(); - - /// Create a new query from a string containing one or more S-expression - /// patterns. The query is associated with a particular language, and can - /// only be run on syntax nodes parsed with that language. - /// - /// If all of the given patterns are valid, this returns a `TSQuery`. - /// If a pattern is invalid, this returns `NULL`, and provides two pieces - /// of information about the problem: - /// 1. The byte offset of the error is written to the `error_offset` parameter. - /// 2. The type of error is written to the `error_type` parameter. - ffi.Pointer ts_query_new( - ffi.Pointer language, - ffi.Pointer source, - int source_len, - ffi.Pointer error_offset, - ffi.Pointer error_type, - ) { - return _ts_query_new( - language, - source, - source_len, - error_offset, - error_type, - ); - } - - late final _ts_query_newPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ffi.Pointer)>>('ts_query_new'); - late final _ts_query_new = _ts_query_newPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ffi.Pointer)>(); - - /// Delete a query, freeing all of the memory that it used. - void ts_query_delete( - ffi.Pointer arg0, - ) { - return _ts_query_delete( - arg0, - ); - } - - late final _ts_query_deletePtr = - _lookup)>>( - 'ts_query_delete'); - late final _ts_query_delete = - _ts_query_deletePtr.asFunction)>(); - - /// Get the number of patterns, captures, or string literals in the query. - int ts_query_pattern_count( - ffi.Pointer arg0, - ) { - return _ts_query_pattern_count( - arg0, - ); - } - - late final _ts_query_pattern_countPtr = - _lookup)>>( - 'ts_query_pattern_count'); - late final _ts_query_pattern_count = _ts_query_pattern_countPtr - .asFunction)>(); - - int ts_query_capture_count( - ffi.Pointer arg0, - ) { - return _ts_query_capture_count( - arg0, - ); - } - - late final _ts_query_capture_countPtr = - _lookup)>>( - 'ts_query_capture_count'); - late final _ts_query_capture_count = _ts_query_capture_countPtr - .asFunction)>(); - - int ts_query_string_count( - ffi.Pointer arg0, - ) { - return _ts_query_string_count( - arg0, - ); - } - - late final _ts_query_string_countPtr = - _lookup)>>( - 'ts_query_string_count'); - late final _ts_query_string_count = _ts_query_string_countPtr - .asFunction)>(); - - /// Get the byte offset where the given pattern starts in the query's source. - /// - /// This can be useful when combining queries by concatenating their source - /// code strings. - int ts_query_start_byte_for_pattern( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_query_start_byte_for_pattern( - arg0, - arg1, - ); - } - - late final _ts_query_start_byte_for_patternPtr = _lookup< - ffi.NativeFunction< - ffi.Uint32 Function(ffi.Pointer, - ffi.Uint32)>>('ts_query_start_byte_for_pattern'); - late final _ts_query_start_byte_for_pattern = - _ts_query_start_byte_for_patternPtr - .asFunction, int)>(); - - /// Get all of the predicates for the given pattern in the query. - /// - /// The predicates are represented as a single array of steps. There are three - /// types of steps in this array, which correspond to the three legal values for - /// the `type` field: - /// - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names - /// of captures. Their `value_id` can be used with the - /// `ts_query_capture_name_for_id` function to obtain the name of the capture. - /// - `TSQueryPredicateStepTypeString` - Steps with this type represent literal - /// strings. Their `value_id` can be used with the - /// `ts_query_string_value_for_id` function to obtain their string value. - /// - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels* - /// that represent the end of an individual predicate. If a pattern has two - /// predicates, then there will be two steps with this `type` in the array. - ffi.Pointer ts_query_predicates_for_pattern( - ffi.Pointer self, - int pattern_index, - ffi.Pointer length, - ) { - return _ts_query_predicates_for_pattern( - self, - pattern_index, - length, - ); - } - - late final _ts_query_predicates_for_patternPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Uint32, - ffi.Pointer)>>('ts_query_predicates_for_pattern'); - late final _ts_query_predicates_for_pattern = - _ts_query_predicates_for_patternPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, int, ffi.Pointer)>(); - - bool ts_query_is_pattern_rooted( - ffi.Pointer self, - int pattern_index, - ) { - return _ts_query_is_pattern_rooted( + encoding.value, + ); + +/// Instruct the parser to start the next parse from the beginning. +/// +/// If the parser previously failed because of a timeout or a cancellation, then +/// by default, it will resume where it left off on the next call to +/// [`ts_parser_parse`] or other parsing functions. If you don't want to resume, +/// and instead intend to use this parser to parse some other document, you must +/// call [`ts_parser_reset`] first. +@ffi.Native)>() +external void ts_parser_reset( + ffi.Pointer self, +); + +/// @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Set the maximum duration in microseconds that parsing should be allowed to +/// take before halting. +/// +/// If parsing takes longer than this, it will halt early, returning NULL. +/// See [`ts_parser_parse`] for more information. +@ffi.Native, ffi.Uint64)>() +external void ts_parser_set_timeout_micros( + ffi.Pointer self, + int timeout_micros, +); + +/// @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Get the duration in microseconds that parsing is allowed to take. +@ffi.Native)>() +external int ts_parser_timeout_micros( + ffi.Pointer self, +); + +/// @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Set the parser's current cancellation flag pointer. +/// +/// If a non-null pointer is assigned, then the parser will periodically read +/// from this pointer during parsing. If it reads a non-zero value, it will +/// halt early, returning NULL. See [`ts_parser_parse`] for more information. +@ffi.Native, ffi.Pointer)>() +external void ts_parser_set_cancellation_flag( + ffi.Pointer self, + ffi.Pointer flag, +); + +/// @deprecated use [`ts_parser_parse_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Get the parser's current cancellation flag pointer. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_parser_cancellation_flag( + ffi.Pointer self, +); + +/// Set the logger that a parser should use during parsing. +/// +/// The parser does not take ownership over the logger payload. If a logger was +/// previously assigned, the caller is responsible for releasing any memory +/// owned by the previous logger. +@ffi.Native, TSLogger)>() +external void ts_parser_set_logger( + ffi.Pointer self, + TSLogger logger, +); + +/// Get the parser's current logger. +@ffi.Native)>() +external TSLogger ts_parser_logger( + ffi.Pointer self, +); + +/// Set the file descriptor to which the parser should write debugging graphs +/// during parsing. The graphs are formatted in the DOT language. You may want +/// to pipe these graphs directly to a `dot(1)` process in order to generate +/// SVG output. You can turn off this logging by passing a negative number. +@ffi.Native, ffi.Int)>() +external void ts_parser_print_dot_graphs( + ffi.Pointer self, + int fd, +); + +/// Create a shallow copy of the syntax tree. This is very fast. +/// +/// You need to copy a syntax tree in order to use it on more than one thread at +/// a time, as syntax trees are not thread safe. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_tree_copy( + ffi.Pointer self, +); + +/// Delete the syntax tree, freeing all of the memory that it used. +@ffi.Native)>() +external void ts_tree_delete( + ffi.Pointer self, +); + +/// Get the root node of the syntax tree. +@ffi.Native)>() +external TSNode ts_tree_root_node( + ffi.Pointer self, +); + +/// Get the root node of the syntax tree, but with its position +/// shifted forward by the given offset. +@ffi.Native, ffi.Uint32, TSPoint)>() +external TSNode ts_tree_root_node_with_offset( + ffi.Pointer self, + int offset_bytes, + TSPoint offset_extent, +); + +/// Get the language that was used to parse the syntax tree. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_tree_language( + ffi.Pointer self, +); + +/// Get the array of included ranges that was used to parse the syntax tree. +/// +/// The returned pointer must be freed by the caller. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>() +external ffi.Pointer ts_tree_included_ranges( + ffi.Pointer self, + ffi.Pointer length, +); + +/// Edit the syntax tree to keep it in sync with source code that has been +/// edited. +/// +/// You must describe the edit both in terms of byte offsets and in terms of +/// (row, column) coordinates. +@ffi.Native, ffi.Pointer)>() +external void ts_tree_edit( + ffi.Pointer self, + ffi.Pointer edit, +); + +/// Compare an old edited syntax tree to a new syntax tree representing the same +/// document, returning an array of ranges whose syntactic structure has changed. +/// +/// For this to work correctly, the old syntax tree must have been edited such +/// that its ranges match up to the new tree. Generally, you'll want to call +/// this function right after calling one of the [`ts_parser_parse`] functions. +/// You need to pass the old tree that was passed to parse, as well as the new +/// tree that was returned from that function. +/// +/// The returned ranges indicate areas where the hierarchical structure of syntax +/// nodes (from root to leaf) has changed between the old and new trees. Characters +/// outside these ranges have identical ancestor nodes in both trees. +/// +/// Note that the returned ranges may be slightly larger than the exact changed areas, +/// but Tree-sitter attempts to make them as small as possible. +/// +/// The returned array is allocated using `malloc` and the caller is responsible +/// for freeing it using `free`. The length of the array will be written to the +/// given `length` pointer. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer, ffi.Pointer)>() +external ffi.Pointer ts_tree_get_changed_ranges( + ffi.Pointer old_tree, + ffi.Pointer new_tree, + ffi.Pointer length, +); + +/// Write a DOT graph describing the syntax tree to the given file. +@ffi.Native, ffi.Int)>() +external void ts_tree_print_dot_graph( + ffi.Pointer self, + int file_descriptor, +); + +/// Get the node's type as a null-terminated string. +@ffi.Native Function(TSNode)>() +external ffi.Pointer ts_node_type( + TSNode self, +); + +/// Get the node's type as a numerical id. +@ffi.Native() +external int ts_node_symbol( + TSNode self, +); + +/// Get the node's language. +@ffi.Native Function(TSNode)>() +external ffi.Pointer ts_node_language( + TSNode self, +); + +/// Get the node's type as it appears in the grammar ignoring aliases as a +/// null-terminated string. +@ffi.Native Function(TSNode)>() +external ffi.Pointer ts_node_grammar_type( + TSNode self, +); + +/// Get the node's type as a numerical id as it appears in the grammar ignoring +/// aliases. This should be used in [`ts_language_next_state`] instead of +/// [`ts_node_symbol`]. +@ffi.Native() +external int ts_node_grammar_symbol( + TSNode self, +); + +/// Get the node's start byte. +@ffi.Native() +external int ts_node_start_byte( + TSNode self, +); + +/// Get the node's start position in terms of rows and columns. +@ffi.Native() +external TSPoint ts_node_start_point( + TSNode self, +); + +/// Get the node's end byte. +@ffi.Native() +external int ts_node_end_byte( + TSNode self, +); + +/// Get the node's end position in terms of rows and columns. +@ffi.Native() +external TSPoint ts_node_end_point( + TSNode self, +); + +/// Get an S-expression representing the node as a string. +/// +/// This string is allocated with `malloc` and the caller is responsible for +/// freeing it using `free`. +@ffi.Native Function(TSNode)>() +external ffi.Pointer ts_node_string( + TSNode self, +); + +/// Check if the node is null. Functions like [`ts_node_child`] and +/// [`ts_node_next_sibling`] will return a null node to indicate that no such node +/// was found. +@ffi.Native() +external bool ts_node_is_null( + TSNode self, +); + +/// Check if the node is *named*. Named nodes correspond to named rules in the +/// grammar, whereas *anonymous* nodes correspond to string literals in the +/// grammar. +@ffi.Native() +external bool ts_node_is_named( + TSNode self, +); + +/// Check if the node is *missing*. Missing nodes are inserted by the parser in +/// order to recover from certain kinds of syntax errors. +@ffi.Native() +external bool ts_node_is_missing( + TSNode self, +); + +/// Check if the node is *extra*. Extra nodes represent things like comments, +/// which are not required the grammar, but can appear anywhere. +@ffi.Native() +external bool ts_node_is_extra( + TSNode self, +); + +/// Check if a syntax node has been edited. +@ffi.Native() +external bool ts_node_has_changes( + TSNode self, +); + +/// Check if the node is a syntax error or contains any syntax errors. +@ffi.Native() +external bool ts_node_has_error( + TSNode self, +); + +/// Check if the node is a syntax error. +@ffi.Native() +external bool ts_node_is_error( + TSNode self, +); + +/// Get this node's parse state. +@ffi.Native() +external int ts_node_parse_state( + TSNode self, +); + +/// Get the parse state after this node. +@ffi.Native() +external int ts_node_next_parse_state( + TSNode self, +); + +/// Get the node's immediate parent. +/// Prefer [`ts_node_child_with_descendant`] for +/// iterating over the node's ancestors. +@ffi.Native() +external TSNode ts_node_parent( + TSNode self, +); + +/// Get the node that contains `descendant`. +/// +/// Note that this can return `descendant` itself. +@ffi.Native() +external TSNode ts_node_child_with_descendant( + TSNode self, + TSNode descendant, +); + +/// Get the node's child at the given index, where zero represents the first +/// child. +@ffi.Native() +external TSNode ts_node_child( + TSNode self, + int child_index, +); + +/// Get the field name for node's child at the given index, where zero represents +/// the first child. Returns NULL, if no field is found. +@ffi.Native Function(TSNode, ffi.Uint32)>() +external ffi.Pointer ts_node_field_name_for_child( + TSNode self, + int child_index, +); + +/// Get the field name for node's named child at the given index, where zero +/// represents the first named child. Returns NULL, if no field is found. +@ffi.Native Function(TSNode, ffi.Uint32)>() +external ffi.Pointer ts_node_field_name_for_named_child( + TSNode self, + int named_child_index, +); + +/// Get the node's number of children. +@ffi.Native() +external int ts_node_child_count( + TSNode self, +); + +/// Get the node's *named* child at the given index. +/// +/// See also [`ts_node_is_named`]. +@ffi.Native() +external TSNode ts_node_named_child( + TSNode self, + int child_index, +); + +/// Get the node's number of *named* children. +/// +/// See also [`ts_node_is_named`]. +@ffi.Native() +external int ts_node_named_child_count( + TSNode self, +); + +/// Get the node's child with the given field name. +@ffi.Native, ffi.Uint32)>() +external TSNode ts_node_child_by_field_name( + TSNode self, + ffi.Pointer name, + int name_length, +); + +/// Get the node's child with the given numerical field id. +/// +/// You can convert a field name to an id using the +/// [`ts_language_field_id_for_name`] function. +@ffi.Native() +external TSNode ts_node_child_by_field_id( + TSNode self, + int field_id, +); + +/// Get the node's next / previous sibling. +@ffi.Native() +external TSNode ts_node_next_sibling( + TSNode self, +); + +@ffi.Native() +external TSNode ts_node_prev_sibling( + TSNode self, +); + +/// Get the node's next / previous *named* sibling. +@ffi.Native() +external TSNode ts_node_next_named_sibling( + TSNode self, +); + +@ffi.Native() +external TSNode ts_node_prev_named_sibling( + TSNode self, +); + +/// Get the node's first child that contains or starts after the given byte offset. +@ffi.Native() +external TSNode ts_node_first_child_for_byte( + TSNode self, + int byte, +); + +/// Get the node's first named child that contains or starts after the given byte offset. +@ffi.Native() +external TSNode ts_node_first_named_child_for_byte( + TSNode self, + int byte, +); + +/// Get the node's number of descendants, including one for the node itself. +@ffi.Native() +external int ts_node_descendant_count( + TSNode self, +); + +/// Get the smallest node within this node that spans the given range of bytes +/// or (row, column) positions. +@ffi.Native() +external TSNode ts_node_descendant_for_byte_range( + TSNode self, + int start, + int end, +); + +@ffi.Native() +external TSNode ts_node_descendant_for_point_range( + TSNode self, + TSPoint start, + TSPoint end, +); + +/// Get the smallest named node within this node that spans the given range of +/// bytes or (row, column) positions. +@ffi.Native() +external TSNode ts_node_named_descendant_for_byte_range( + TSNode self, + int start, + int end, +); + +@ffi.Native() +external TSNode ts_node_named_descendant_for_point_range( + TSNode self, + TSPoint start, + TSPoint end, +); + +/// Edit the node to keep it in-sync with source code that has been edited. +/// +/// This function is only rarely needed. When you edit a syntax tree with the +/// [`ts_tree_edit`] function, all of the nodes that you retrieve from the tree +/// afterward will already reflect the edit. You only need to use [`ts_node_edit`] +/// when you have a [`TSNode`] instance that you want to keep and continue to use +/// after an edit. +@ffi.Native, ffi.Pointer)>() +external void ts_node_edit( + ffi.Pointer self, + ffi.Pointer edit, +); + +/// Check if two nodes are identical. +@ffi.Native() +external bool ts_node_eq( + TSNode self, + TSNode other, +); + +/// Create a new tree cursor starting from the given node. +/// +/// A tree cursor allows you to walk a syntax tree more efficiently than is +/// possible using the [`TSNode`] functions. It is a mutable object that is always +/// on a certain syntax node, and can be moved imperatively to different nodes. +/// +/// Note that the given node is considered the root of the cursor, +/// and the cursor cannot walk outside this node. +@ffi.Native() +external TSTreeCursor ts_tree_cursor_new( + TSNode node, +); + +/// Delete a tree cursor, freeing all of the memory that it used. +@ffi.Native)>() +external void ts_tree_cursor_delete( + ffi.Pointer self, +); + +/// Re-initialize a tree cursor to start at the original node that the cursor was +/// constructed with. +@ffi.Native, TSNode)>() +external void ts_tree_cursor_reset( + ffi.Pointer self, + TSNode node, +); + +/// Re-initialize a tree cursor to the same position as another cursor. +/// +/// Unlike [`ts_tree_cursor_reset`], this will not lose parent information and +/// allows reusing already created cursors. +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer)>() +external void ts_tree_cursor_reset_to( + ffi.Pointer dst, + ffi.Pointer src, +); + +/// Get the tree cursor's current node. +@ffi.Native)>() +external TSNode ts_tree_cursor_current_node( + ffi.Pointer self, +); + +/// Get the field name of the tree cursor's current node. +/// +/// This returns `NULL` if the current node doesn't have a field. +/// See also [`ts_node_child_by_field_name`]. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_tree_cursor_current_field_name( + ffi.Pointer self, +); + +/// Get the field id of the tree cursor's current node. +/// +/// This returns zero if the current node doesn't have a field. +/// See also [`ts_node_child_by_field_id`], [`ts_language_field_id_for_name`]. +@ffi.Native)>() +external int ts_tree_cursor_current_field_id( + ffi.Pointer self, +); + +/// Move the cursor to the parent of its current node. +/// +/// This returns `true` if the cursor successfully moved, and returns `false` +/// if there was no parent node (the cursor was already on the root node). +/// +/// Note that the node the cursor was constructed with is considered the root +/// of the cursor, and the cursor cannot walk outside this node. +@ffi.Native)>() +external bool ts_tree_cursor_goto_parent( + ffi.Pointer self, +); + +/// Move the cursor to the next sibling of its current node. +/// +/// This returns `true` if the cursor successfully moved, and returns `false` +/// if there was no next sibling node. +/// +/// Note that the node the cursor was constructed with is considered the root +/// of the cursor, and the cursor cannot walk outside this node. +@ffi.Native)>() +external bool ts_tree_cursor_goto_next_sibling( + ffi.Pointer self, +); + +/// Move the cursor to the previous sibling of its current node. +/// +/// This returns `true` if the cursor successfully moved, and returns `false` if +/// there was no previous sibling node. +/// +/// Note, that this function may be slower than +/// [`ts_tree_cursor_goto_next_sibling`] due to how node positions are stored. In +/// the worst case, this will need to iterate through all the children up to the +/// previous sibling node to recalculate its position. Also note that the node the cursor +/// was constructed with is considered the root of the cursor, and the cursor cannot +/// walk outside this node. +@ffi.Native)>() +external bool ts_tree_cursor_goto_previous_sibling( + ffi.Pointer self, +); + +/// Move the cursor to the first child of its current node. +/// +/// This returns `true` if the cursor successfully moved, and returns `false` +/// if there were no children. +@ffi.Native)>() +external bool ts_tree_cursor_goto_first_child( + ffi.Pointer self, +); + +/// Move the cursor to the last child of its current node. +/// +/// This returns `true` if the cursor successfully moved, and returns `false` if +/// there were no children. +/// +/// Note that this function may be slower than [`ts_tree_cursor_goto_first_child`] +/// because it needs to iterate through all the children to compute the child's +/// position. +@ffi.Native)>() +external bool ts_tree_cursor_goto_last_child( + ffi.Pointer self, +); + +/// Move the cursor to the node that is the nth descendant of +/// the original node that the cursor was constructed with, where +/// zero represents the original node itself. +@ffi.Native, ffi.Uint32)>() +external void ts_tree_cursor_goto_descendant( + ffi.Pointer self, + int goal_descendant_index, +); + +/// Get the index of the cursor's current node out of all of the +/// descendants of the original node that the cursor was constructed with. +@ffi.Native)>() +external int ts_tree_cursor_current_descendant_index( + ffi.Pointer self, +); + +/// Get the depth of the cursor's current node relative to the original +/// node that the cursor was constructed with. +@ffi.Native)>() +external int ts_tree_cursor_current_depth( + ffi.Pointer self, +); + +/// Move the cursor to the first child of its current node that contains or starts after +/// the given byte offset or point. +/// +/// This returns the index of the child node if one was found, and returns -1 +/// if no such child was found. +@ffi.Native, ffi.Uint32)>() +external int ts_tree_cursor_goto_first_child_for_byte( + ffi.Pointer self, + int goal_byte, +); + +@ffi.Native, TSPoint)>() +external int ts_tree_cursor_goto_first_child_for_point( + ffi.Pointer self, + TSPoint goal_point, +); + +@ffi.Native)>() +external TSTreeCursor ts_tree_cursor_copy( + ffi.Pointer cursor, +); + +/// Create a new query from a string containing one or more S-expression +/// patterns. The query is associated with a particular language, and can +/// only be run on syntax nodes parsed with that language. +/// +/// If all of the given patterns are valid, this returns a [`TSQuery`]. +/// If a pattern is invalid, this returns `NULL`, and provides two pieces +/// of information about the problem: +/// 1. The byte offset of the error is written to the `error_offset` parameter. +/// 2. The type of error is written to the `error_type` parameter. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ffi.Pointer)>() +external ffi.Pointer ts_query_new( + ffi.Pointer language, + ffi.Pointer source, + int source_len, + ffi.Pointer error_offset, + ffi.Pointer error_type, +); + +/// Delete a query, freeing all of the memory that it used. +@ffi.Native)>() +external void ts_query_delete( + ffi.Pointer self, +); + +/// Get the number of patterns, captures, or string literals in the query. +@ffi.Native)>() +external int ts_query_pattern_count( + ffi.Pointer self, +); + +@ffi.Native)>() +external int ts_query_capture_count( + ffi.Pointer self, +); + +@ffi.Native)>() +external int ts_query_string_count( + ffi.Pointer self, +); + +/// Get the byte offset where the given pattern starts in the query's source. +/// +/// This can be useful when combining queries by concatenating their source +/// code strings. +@ffi.Native, ffi.Uint32)>() +external int ts_query_start_byte_for_pattern( + ffi.Pointer self, + int pattern_index, +); + +/// Get the byte offset where the given pattern ends in the query's source. +/// +/// This can be useful when combining queries by concatenating their source +/// code strings. +@ffi.Native, ffi.Uint32)>() +external int ts_query_end_byte_for_pattern( + ffi.Pointer self, + int pattern_index, +); + +/// Get all of the predicates for the given pattern in the query. +/// +/// The predicates are represented as a single array of steps. There are three +/// types of steps in this array, which correspond to the three legal values for +/// the `type` field: +/// - `TSQueryPredicateStepTypeCapture` - Steps with this type represent names +/// of captures. Their `value_id` can be used with the +/// [`ts_query_capture_name_for_id`] function to obtain the name of the capture. +/// - `TSQueryPredicateStepTypeString` - Steps with this type represent literal +/// strings. Their `value_id` can be used with the +/// [`ts_query_string_value_for_id`] function to obtain their string value. +/// - `TSQueryPredicateStepTypeDone` - Steps with this type are *sentinels* +/// that represent the end of an individual predicate. If a pattern has two +/// predicates, then there will be two steps with this `type` in the array. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Uint32, ffi.Pointer)>() +external ffi.Pointer ts_query_predicates_for_pattern( + ffi.Pointer self, + int pattern_index, + ffi.Pointer step_count, +); + +@ffi.Native, ffi.Uint32)>() +external bool ts_query_is_pattern_rooted( + ffi.Pointer self, + int pattern_index, +); + +@ffi.Native, ffi.Uint32)>() +external bool ts_query_is_pattern_non_local( + ffi.Pointer self, + int pattern_index, +); + +@ffi.Native, ffi.Uint32)>() +external bool ts_query_is_pattern_guaranteed_at_step( + ffi.Pointer self, + int byte_offset, +); + +/// Get the name and length of one of the query's captures, or one of the +/// query's string literals. Each capture and string is associated with a +/// numeric id based on the order that it appeared in the query's source. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Uint32, ffi.Pointer)>() +external ffi.Pointer ts_query_capture_name_for_id( + ffi.Pointer self, + int index, + ffi.Pointer length, +); + +/// Get the quantifier of the query's captures. Each capture is * associated +/// with a numeric id based on the order that it appeared in the query's source. +@ffi.Native< + ffi.UnsignedInt Function(ffi.Pointer, ffi.Uint32, ffi.Uint32)>( + symbol: 'ts_query_capture_quantifier_for_id') +external int _ts_query_capture_quantifier_for_id( + ffi.Pointer self, + int pattern_index, + int capture_index, +); + +TSQuantifier ts_query_capture_quantifier_for_id( + ffi.Pointer self, + int pattern_index, + int capture_index, +) => + TSQuantifier.fromValue(_ts_query_capture_quantifier_for_id( self, pattern_index, - ); - } - - late final _ts_query_is_pattern_rootedPtr = _lookup< - ffi - .NativeFunction, ffi.Uint32)>>( - 'ts_query_is_pattern_rooted'); - late final _ts_query_is_pattern_rooted = _ts_query_is_pattern_rootedPtr - .asFunction, int)>(); - - bool ts_query_is_pattern_non_local( - ffi.Pointer self, - int pattern_index, - ) { - return _ts_query_is_pattern_non_local( - self, - pattern_index, - ); - } - - late final _ts_query_is_pattern_non_localPtr = _lookup< - ffi - .NativeFunction, ffi.Uint32)>>( - 'ts_query_is_pattern_non_local'); - late final _ts_query_is_pattern_non_local = _ts_query_is_pattern_non_localPtr - .asFunction, int)>(); - - bool ts_query_is_pattern_guaranteed_at_step( - ffi.Pointer self, - int byte_offset, - ) { - return _ts_query_is_pattern_guaranteed_at_step( - self, - byte_offset, - ); - } - - late final _ts_query_is_pattern_guaranteed_at_stepPtr = _lookup< - ffi - .NativeFunction, ffi.Uint32)>>( - 'ts_query_is_pattern_guaranteed_at_step'); - late final _ts_query_is_pattern_guaranteed_at_step = - _ts_query_is_pattern_guaranteed_at_stepPtr - .asFunction, int)>(); - - /// Get the name and length of one of the query's captures, or one of the - /// query's string literals. Each capture and string is associated with a - /// numeric id based on the order that it appeared in the query's source. - ffi.Pointer ts_query_capture_name_for_id( - ffi.Pointer arg0, - int id, - ffi.Pointer length, - ) { - return _ts_query_capture_name_for_id( - arg0, - id, - length, - ); - } - - late final _ts_query_capture_name_for_idPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, ffi.Uint32, - ffi.Pointer)>>('ts_query_capture_name_for_id'); - late final _ts_query_capture_name_for_id = - _ts_query_capture_name_for_idPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, int, ffi.Pointer)>(); - - /// Get the quantifier of the query's captures. Each capture is * associated - /// with a numeric id based on the order that it appeared in the query's source. - int ts_query_capture_quantifier_for_id( - ffi.Pointer arg0, - int pattern_id, - int capture_id, - ) { - return _ts_query_capture_quantifier_for_id( - arg0, - pattern_id, - capture_id, - ); - } - - late final _ts_query_capture_quantifier_for_idPtr = _lookup< - ffi.NativeFunction< - ffi.Int32 Function(ffi.Pointer, ffi.Uint32, - ffi.Uint32)>>('ts_query_capture_quantifier_for_id'); - late final _ts_query_capture_quantifier_for_id = - _ts_query_capture_quantifier_for_idPtr - .asFunction, int, int)>(); - - ffi.Pointer ts_query_string_value_for_id( - ffi.Pointer arg0, - int id, - ffi.Pointer length, - ) { - return _ts_query_string_value_for_id( - arg0, - id, - length, - ); - } - - late final _ts_query_string_value_for_idPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, ffi.Uint32, - ffi.Pointer)>>('ts_query_string_value_for_id'); - late final _ts_query_string_value_for_id = - _ts_query_string_value_for_idPtr.asFunction< - ffi.Pointer Function( - ffi.Pointer, int, ffi.Pointer)>(); - - /// Disable a certain capture within a query. - /// - /// This prevents the capture from being returned in matches, and also avoids - /// any resource usage associated with recording the capture. Currently, there - /// is no way to undo this. - void ts_query_disable_capture( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ) { - return _ts_query_disable_capture( - arg0, - arg1, - arg2, - ); - } - - late final _ts_query_disable_capturePtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - ffi.Uint32)>>('ts_query_disable_capture'); - late final _ts_query_disable_capture = - _ts_query_disable_capturePtr.asFunction< - void Function(ffi.Pointer, ffi.Pointer, int)>(); - - /// Disable a certain pattern within a query. - /// - /// This prevents the pattern from matching and removes most of the overhead - /// associated with the pattern. Currently, there is no way to undo this. - void ts_query_disable_pattern( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_query_disable_pattern( - arg0, - arg1, - ); - } - - late final _ts_query_disable_patternPtr = _lookup< - ffi - .NativeFunction, ffi.Uint32)>>( - 'ts_query_disable_pattern'); - late final _ts_query_disable_pattern = _ts_query_disable_patternPtr - .asFunction, int)>(); - - /// Create a new cursor for executing a given query. - /// - /// The cursor stores the state that is needed to iteratively search - /// for matches. To use the query cursor, first call `ts_query_cursor_exec` - /// to start running a given query on a given syntax node. Then, there are - /// two options for consuming the results of the query: - /// 1. Repeatedly call `ts_query_cursor_next_match` to iterate over all of the - /// *matches* in the order that they were found. Each match contains the - /// index of the pattern that matched, and an array of captures. Because - /// multiple patterns can match the same set of nodes, one match may contain - /// captures that appear *before* some of the captures from a previous match. - /// 2. Repeatedly call `ts_query_cursor_next_capture` to iterate over all of the - /// individual *captures* in the order that they appear. This is useful if - /// don't care about which pattern matched, and just want a single ordered - /// sequence of captures. - /// - /// If you don't care about consuming all of the results, you can stop calling - /// `ts_query_cursor_next_match` or `ts_query_cursor_next_capture` at any point. - /// You can then start executing another query on another node by calling - /// `ts_query_cursor_exec` again. - ffi.Pointer ts_query_cursor_new() { - return _ts_query_cursor_new(); - } - - late final _ts_query_cursor_newPtr = - _lookup Function()>>( - 'ts_query_cursor_new'); - late final _ts_query_cursor_new = _ts_query_cursor_newPtr - .asFunction Function()>(); - - /// Delete a query cursor, freeing all of the memory that it used. - void ts_query_cursor_delete( - ffi.Pointer arg0, - ) { - return _ts_query_cursor_delete( - arg0, - ); - } - - late final _ts_query_cursor_deletePtr = _lookup< - ffi.NativeFunction)>>( - 'ts_query_cursor_delete'); - late final _ts_query_cursor_delete = _ts_query_cursor_deletePtr - .asFunction)>(); - - /// Start running a given query on a given node. - void ts_query_cursor_exec( - ffi.Pointer arg0, - ffi.Pointer arg1, - TSNode arg2, - ) { - return _ts_query_cursor_exec( - arg0, - arg1, - arg2, - ); - } - - late final _ts_query_cursor_execPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer, - TSNode)>>('ts_query_cursor_exec'); - late final _ts_query_cursor_exec = _ts_query_cursor_execPtr.asFunction< - void Function( - ffi.Pointer, ffi.Pointer, TSNode)>(); - - /// Manage the maximum number of in-progress matches allowed by this query - /// cursor. - /// - /// Query cursors have an optional maximum capacity for storing lists of - /// in-progress captures. If this capacity is exceeded, then the - /// earliest-starting match will silently be dropped to make room for further - /// matches. This maximum capacity is optional — by default, query cursors allow - /// any number of pending matches, dynamically allocating new space for them as - /// needed as the query is executed. - bool ts_query_cursor_did_exceed_match_limit( - ffi.Pointer arg0, - ) { - return _ts_query_cursor_did_exceed_match_limit( - arg0, - ); - } - - late final _ts_query_cursor_did_exceed_match_limitPtr = _lookup< - ffi.NativeFunction)>>( - 'ts_query_cursor_did_exceed_match_limit'); - late final _ts_query_cursor_did_exceed_match_limit = - _ts_query_cursor_did_exceed_match_limitPtr - .asFunction)>(); - - int ts_query_cursor_match_limit( - ffi.Pointer arg0, - ) { - return _ts_query_cursor_match_limit( - arg0, - ); - } - - late final _ts_query_cursor_match_limitPtr = _lookup< - ffi.NativeFunction)>>( - 'ts_query_cursor_match_limit'); - late final _ts_query_cursor_match_limit = _ts_query_cursor_match_limitPtr - .asFunction)>(); - - void ts_query_cursor_set_match_limit( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_query_cursor_set_match_limit( - arg0, - arg1, - ); - } - - late final _ts_query_cursor_set_match_limitPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Uint32)>>('ts_query_cursor_set_match_limit'); - late final _ts_query_cursor_set_match_limit = - _ts_query_cursor_set_match_limitPtr - .asFunction, int)>(); - - /// Set the range of bytes or (row, column) positions in which the query - /// will be executed. - void ts_query_cursor_set_byte_range( - ffi.Pointer arg0, - int arg1, - int arg2, - ) { - return _ts_query_cursor_set_byte_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_query_cursor_set_byte_rangePtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, ffi.Uint32, - ffi.Uint32)>>('ts_query_cursor_set_byte_range'); - late final _ts_query_cursor_set_byte_range = - _ts_query_cursor_set_byte_rangePtr - .asFunction, int, int)>(); - - void ts_query_cursor_set_point_range( - ffi.Pointer arg0, - TSPoint arg1, - TSPoint arg2, - ) { - return _ts_query_cursor_set_point_range( - arg0, - arg1, - arg2, - ); - } - - late final _ts_query_cursor_set_point_rangePtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, TSPoint, - TSPoint)>>('ts_query_cursor_set_point_range'); - late final _ts_query_cursor_set_point_range = - _ts_query_cursor_set_point_rangePtr.asFunction< - void Function(ffi.Pointer, TSPoint, TSPoint)>(); - - /// Advance to the next match of the currently running query. - /// - /// If there is a match, write it to `*match` and return `true`. - /// Otherwise, return `false`. - bool ts_query_cursor_next_match( - ffi.Pointer arg0, - ffi.Pointer match, - ) { - return _ts_query_cursor_next_match( - arg0, - match, - ); - } - - late final _ts_query_cursor_next_matchPtr = _lookup< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, - ffi.Pointer)>>('ts_query_cursor_next_match'); - late final _ts_query_cursor_next_match = - _ts_query_cursor_next_matchPtr.asFunction< - bool Function( - ffi.Pointer, ffi.Pointer)>(); - - void ts_query_cursor_remove_match( - ffi.Pointer arg0, - int id, - ) { - return _ts_query_cursor_remove_match( - arg0, - id, - ); - } - - late final _ts_query_cursor_remove_matchPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Uint32)>>('ts_query_cursor_remove_match'); - late final _ts_query_cursor_remove_match = _ts_query_cursor_remove_matchPtr - .asFunction, int)>(); - - /// Advance to the next capture of the currently running query. - /// - /// If there is a capture, write its match to `*match` and its index within - /// the matche's capture list to `*capture_index`. Otherwise, return `false`. - bool ts_query_cursor_next_capture( - ffi.Pointer arg0, - ffi.Pointer match, - ffi.Pointer capture_index, - ) { - return _ts_query_cursor_next_capture( - arg0, - match, capture_index, - ); - } - - late final _ts_query_cursor_next_capturePtr = _lookup< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer)>>('ts_query_cursor_next_capture'); - late final _ts_query_cursor_next_capture = - _ts_query_cursor_next_capturePtr.asFunction< - bool Function(ffi.Pointer, ffi.Pointer, - ffi.Pointer)>(); - - /// Set the maximum start depth for a cursor. - /// - /// This prevents cursors from exploring children nodes at a certain depth. - /// Note if a pattern includes many children, then they will still be checked. - /// - /// Set to `0` to remove the maximum start depth. - void ts_query_cursor_set_max_start_depth( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_query_cursor_set_max_start_depth( - arg0, - arg1, - ); - } - - late final _ts_query_cursor_set_max_start_depthPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer, - ffi.Uint32)>>('ts_query_cursor_set_max_start_depth'); - late final _ts_query_cursor_set_max_start_depth = - _ts_query_cursor_set_max_start_depthPtr - .asFunction, int)>(); - - /// Get the number of distinct node types in the language. - int ts_language_symbol_count( - ffi.Pointer arg0, - ) { - return _ts_language_symbol_count( - arg0, - ); - } - - late final _ts_language_symbol_countPtr = - _lookup)>>( - 'ts_language_symbol_count'); - late final _ts_language_symbol_count = _ts_language_symbol_countPtr - .asFunction)>(); - - /// Get a node type string for the given numerical id. - ffi.Pointer ts_language_symbol_name( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_language_symbol_name( - arg0, - arg1, - ); - } - - late final _ts_language_symbol_namePtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, TSSymbol)>>('ts_language_symbol_name'); - late final _ts_language_symbol_name = _ts_language_symbol_namePtr.asFunction< - ffi.Pointer Function(ffi.Pointer, int)>(); - - /// Get the numerical id for the given node type string. - int ts_language_symbol_for_name( - ffi.Pointer self, - ffi.Pointer string, - int length, - bool is_named, - ) { - return _ts_language_symbol_for_name( + )); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Uint32, ffi.Pointer)>() +external ffi.Pointer ts_query_string_value_for_id( + ffi.Pointer self, + int index, + ffi.Pointer length, +); + +/// Disable a certain capture within a query. +/// +/// This prevents the capture from being returned in matches, and also avoids +/// any resource usage associated with recording the capture. Currently, there +/// is no way to undo this. +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, ffi.Uint32)>() +external void ts_query_disable_capture( + ffi.Pointer self, + ffi.Pointer name, + int length, +); + +/// Disable a certain pattern within a query. +/// +/// This prevents the pattern from matching and removes most of the overhead +/// associated with the pattern. Currently, there is no way to undo this. +@ffi.Native, ffi.Uint32)>() +external void ts_query_disable_pattern( + ffi.Pointer self, + int pattern_index, +); + +/// Create a new cursor for executing a given query. +/// +/// The cursor stores the state that is needed to iteratively search +/// for matches. To use the query cursor, first call [`ts_query_cursor_exec`] +/// to start running a given query on a given syntax node. Then, there are +/// two options for consuming the results of the query: +/// 1. Repeatedly call [`ts_query_cursor_next_match`] to iterate over all of the +/// *matches* in the order that they were found. Each match contains the +/// index of the pattern that matched, and an array of captures. Because +/// multiple patterns can match the same set of nodes, one match may contain +/// captures that appear *before* some of the captures from a previous match. +/// 2. Repeatedly call [`ts_query_cursor_next_capture`] to iterate over all of the +/// individual *captures* in the order that they appear. This is useful if +/// don't care about which pattern matched, and just want a single ordered +/// sequence of captures. +/// +/// If you don't care about consuming all of the results, you can stop calling +/// [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] at any point. +/// You can then start executing another query on another node by calling +/// [`ts_query_cursor_exec`] again. +@ffi.Native Function()>() +external ffi.Pointer ts_query_cursor_new(); + +/// Delete a query cursor, freeing all of the memory that it used. +@ffi.Native)>() +external void ts_query_cursor_delete( + ffi.Pointer self, +); + +/// Start running a given query on a given node. +@ffi.Native< + ffi.Void Function( + ffi.Pointer, ffi.Pointer, TSNode)>() +external void ts_query_cursor_exec( + ffi.Pointer self, + ffi.Pointer query, + TSNode node, +); + +/// Start running a given query on a given node, with some options. +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer, TSNode, + ffi.Pointer)>() +external void ts_query_cursor_exec_with_options( + ffi.Pointer self, + ffi.Pointer query, + TSNode node, + ffi.Pointer query_options, +); + +/// Manage the maximum number of in-progress matches allowed by this query +/// cursor. +/// +/// Query cursors have an optional maximum capacity for storing lists of +/// in-progress captures. If this capacity is exceeded, then the +/// earliest-starting match will silently be dropped to make room for further +/// matches. This maximum capacity is optional — by default, query cursors allow +/// any number of pending matches, dynamically allocating new space for them as +/// needed as the query is executed. +@ffi.Native)>() +external bool ts_query_cursor_did_exceed_match_limit( + ffi.Pointer self, +); + +@ffi.Native)>() +external int ts_query_cursor_match_limit( + ffi.Pointer self, +); + +@ffi.Native, ffi.Uint32)>() +external void ts_query_cursor_set_match_limit( + ffi.Pointer self, + int limit, +); + +/// @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Set the maximum duration in microseconds that query execution should be allowed to +/// take before halting. +/// +/// If query execution takes longer than this, it will halt early, returning NULL. +/// See [`ts_query_cursor_next_match`] or [`ts_query_cursor_next_capture`] for more information. +@ffi.Native, ffi.Uint64)>() +external void ts_query_cursor_set_timeout_micros( + ffi.Pointer self, + int timeout_micros, +); + +/// @deprecated use [`ts_query_cursor_exec_with_options`] and pass in a callback instead, this will be removed in 0.26. +/// +/// Get the duration in microseconds that query execution is allowed to take. +/// +/// This is set via [`ts_query_cursor_set_timeout_micros`]. +@ffi.Native)>() +external int ts_query_cursor_timeout_micros( + ffi.Pointer self, +); + +/// Set the range of bytes in which the query will be executed. +/// +/// The query cursor will return matches that intersect with the given point range. +/// This means that a match may be returned even if some of its captures fall +/// outside the specified range, as long as at least part of the match +/// overlaps with the range. +/// +/// For example, if a query pattern matches a node that spans a larger area +/// than the specified range, but part of that node intersects with the range, +/// the entire match will be returned. +/// +/// This will return `false` if the start byte is greater than the end byte, otherwise +/// it will return `true`. +@ffi.Native< + ffi.Bool Function(ffi.Pointer, ffi.Uint32, ffi.Uint32)>() +external bool ts_query_cursor_set_byte_range( + ffi.Pointer self, + int start_byte, + int end_byte, +); + +/// Set the range of (row, column) positions in which the query will be executed. +/// +/// The query cursor will return matches that intersect with the given point range. +/// This means that a match may be returned even if some of its captures fall +/// outside the specified range, as long as at least part of the match +/// overlaps with the range. +/// +/// For example, if a query pattern matches a node that spans a larger area +/// than the specified range, but part of that node intersects with the range, +/// the entire match will be returned. +/// +/// This will return `false` if the start point is greater than the end point, otherwise +/// it will return `true`. +@ffi.Native, TSPoint, TSPoint)>() +external bool ts_query_cursor_set_point_range( + ffi.Pointer self, + TSPoint start_point, + TSPoint end_point, +); + +/// Advance to the next match of the currently running query. +/// +/// If there is a match, write it to `*match` and return `true`. +/// Otherwise, return `false`. +@ffi.Native< + ffi.Bool Function(ffi.Pointer, ffi.Pointer)>() +external bool ts_query_cursor_next_match( + ffi.Pointer self, + ffi.Pointer match, +); + +@ffi.Native, ffi.Uint32)>() +external void ts_query_cursor_remove_match( + ffi.Pointer self, + int match_id, +); + +/// Advance to the next capture of the currently running query. +/// +/// If there is a capture, write its match to `*match` and its index within +/// the match's capture list to `*capture_index`. Otherwise, return `false`. +@ffi.Native< + ffi.Bool Function(ffi.Pointer, ffi.Pointer, + ffi.Pointer)>() +external bool ts_query_cursor_next_capture( + ffi.Pointer self, + ffi.Pointer match, + ffi.Pointer capture_index, +); + +/// Set the maximum start depth for a query cursor. +/// +/// This prevents cursors from exploring children nodes at a certain depth. +/// Note if a pattern includes many children, then they will still be checked. +/// +/// The zero max start depth value can be used as a special behavior and +/// it helps to destructure a subtree by staying on a node and using captures +/// for interested parts. Note that the zero max start depth only limit a search +/// depth for a pattern's root node but other nodes that are parts of the pattern +/// may be searched at any depth what defined by the pattern structure. +/// +/// Set to `UINT32_MAX` to remove the maximum start depth. +@ffi.Native, ffi.Uint32)>() +external void ts_query_cursor_set_max_start_depth( + ffi.Pointer self, + int max_start_depth, +); + +/// Get another reference to the given language. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_language_copy( + ffi.Pointer self, +); + +/// Free any dynamically-allocated resources for this language, if +/// this is the last reference. +@ffi.Native)>() +external void ts_language_delete( + ffi.Pointer self, +); + +/// Get the number of distinct node types in the language. +@ffi.Native)>() +external int ts_language_symbol_count( + ffi.Pointer self, +); + +/// Get the number of valid states in this language. +@ffi.Native)>() +external int ts_language_state_count( + ffi.Pointer self, +); + +/// Get the numerical id for the given node type string. +@ffi.Native< + TSSymbol Function( + ffi.Pointer, ffi.Pointer, ffi.Uint32, ffi.Bool)>() +external int ts_language_symbol_for_name( + ffi.Pointer self, + ffi.Pointer string, + int length, + bool is_named, +); + +/// Get the number of distinct field names in the language. +@ffi.Native)>() +external int ts_language_field_count( + ffi.Pointer self, +); + +/// Get the field name string for the given numerical id. +@ffi.Native< + ffi.Pointer Function(ffi.Pointer, TSFieldId)>() +external ffi.Pointer ts_language_field_name_for_id( + ffi.Pointer self, + int id, +); + +/// Get the numerical id for the given field name string. +@ffi.Native< + TSFieldId Function( + ffi.Pointer, ffi.Pointer, ffi.Uint32)>() +external int ts_language_field_id_for_name( + ffi.Pointer self, + ffi.Pointer name, + int name_length, +); + +/// Get a list of all supertype symbols for the language. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>() +external ffi.Pointer ts_language_supertypes( + ffi.Pointer self, + ffi.Pointer length, +); + +/// Get a list of all subtype symbol ids for a given supertype symbol. +/// +/// See [`ts_language_supertypes`] for fetching all supertype symbols. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, TSSymbol, ffi.Pointer)>() +external ffi.Pointer ts_language_subtypes( + ffi.Pointer self, + int supertype, + ffi.Pointer length, +); + +/// Get a node type string for the given numerical id. +@ffi.Native Function(ffi.Pointer, TSSymbol)>() +external ffi.Pointer ts_language_symbol_name( + ffi.Pointer self, + int symbol, +); + +/// Check whether the given node type id belongs to named nodes, anonymous nodes, +/// or a hidden nodes. +/// +/// See also [`ts_node_is_named`]. Hidden nodes are never returned from the API. +@ffi.Native, TSSymbol)>( + symbol: 'ts_language_symbol_type') +external int _ts_language_symbol_type( + ffi.Pointer self, + int symbol, +); + +TSSymbolType ts_language_symbol_type( + ffi.Pointer self, + DartTSSymbol symbol, +) => + TSSymbolType.fromValue(_ts_language_symbol_type( self, - string, - length, - is_named, - ); - } - - late final _ts_language_symbol_for_namePtr = _lookup< - ffi.NativeFunction< - TSSymbol Function(ffi.Pointer, ffi.Pointer, - ffi.Uint32, ffi.Bool)>>('ts_language_symbol_for_name'); - late final _ts_language_symbol_for_name = - _ts_language_symbol_for_namePtr.asFunction< - int Function( - ffi.Pointer, ffi.Pointer, int, bool)>(); - - /// Get the number of distinct field names in the language. - int ts_language_field_count( - ffi.Pointer arg0, - ) { - return _ts_language_field_count( - arg0, - ); - } - - late final _ts_language_field_countPtr = - _lookup)>>( - 'ts_language_field_count'); - late final _ts_language_field_count = _ts_language_field_countPtr - .asFunction)>(); - - /// Get the field name string for the given numerical id. - ffi.Pointer ts_language_field_name_for_id( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_language_field_name_for_id( - arg0, - arg1, - ); - } - - late final _ts_language_field_name_for_idPtr = _lookup< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Pointer, - TSFieldId)>>('ts_language_field_name_for_id'); - late final _ts_language_field_name_for_id = - _ts_language_field_name_for_idPtr.asFunction< - ffi.Pointer Function(ffi.Pointer, int)>(); - - /// Get the numerical id for the given field name string. - int ts_language_field_id_for_name( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ) { - return _ts_language_field_id_for_name( - arg0, - arg1, - arg2, - ); - } - - late final _ts_language_field_id_for_namePtr = _lookup< - ffi.NativeFunction< - TSFieldId Function(ffi.Pointer, ffi.Pointer, - ffi.Uint32)>>('ts_language_field_id_for_name'); - late final _ts_language_field_id_for_name = - _ts_language_field_id_for_namePtr.asFunction< - int Function(ffi.Pointer, ffi.Pointer, int)>(); - - /// Check whether the given node type id belongs to named nodes, anonymous nodes, - /// or a hidden nodes. - /// - /// See also `ts_node_is_named`. Hidden nodes are never returned from the API. - int ts_language_symbol_type( - ffi.Pointer arg0, - int arg1, - ) { - return _ts_language_symbol_type( - arg0, - arg1, - ); - } - - late final _ts_language_symbol_typePtr = _lookup< - ffi.NativeFunction< - ffi.Int32 Function( - ffi.Pointer, TSSymbol)>>('ts_language_symbol_type'); - late final _ts_language_symbol_type = _ts_language_symbol_typePtr - .asFunction, int)>(); - - /// Get the ABI version number for this language. This version number is used - /// to ensure that languages were generated by a compatible version of - /// Tree-sitter. - /// - /// See also `ts_parser_set_language`. - int ts_language_version( - ffi.Pointer arg0, - ) { - return _ts_language_version( - arg0, - ); - } - - late final _ts_language_versionPtr = - _lookup)>>( - 'ts_language_version'); - late final _ts_language_version = _ts_language_versionPtr - .asFunction)>(); - - /// Set the allocation functions used by the library. - /// - /// By default, Tree-sitter uses the standard libc allocation functions, - /// but aborts the process when an allocation fails. This function lets - /// you supply alternative allocation functions at runtime. - /// - /// If you pass `NULL` for any parameter, Tree-sitter will switch back to - /// its default implementation of that function. - /// - /// If you call this function after the library has already been used, then - /// you must ensure that either: - /// 1. All the existing objects have been freed. - /// 2. The new allocator shares its state with the old one, so it is capable - /// of freeing memory that was allocated by the old allocator. - void ts_set_allocator( - ffi.Pointer Function(ffi.Size)>> - new_malloc, - ffi.Pointer< - ffi - .NativeFunction Function(ffi.Size, ffi.Size)>> - new_calloc, - ffi.Pointer< + symbol, + )); + +/// @deprecated use [`ts_language_abi_version`] instead, this will be removed in 0.26. +/// +/// Get the ABI version number for this language. This version number is used +/// to ensure that languages were generated by a compatible version of +/// Tree-sitter. +/// +/// See also [`ts_parser_set_language`]. +@ffi.Native)>() +external int ts_language_version( + ffi.Pointer self, +); + +/// Get the ABI version number for this language. This version number is used +/// to ensure that languages were generated by a compatible version of +/// Tree-sitter. +/// +/// See also [`ts_parser_set_language`]. +@ffi.Native)>() +external int ts_language_abi_version( + ffi.Pointer self, +); + +/// Get the metadata for this language. This information is generated by the +/// CLI, and relies on the language author providing the correct metadata in +/// the language's `tree-sitter.json` file. +/// +/// See also [`TSMetadata`]. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_language_metadata( + ffi.Pointer self, +); + +/// Get the next parse state. Combine this with lookahead iterators to generate +/// completion suggestions or valid symbols in error nodes. Use +/// [`ts_node_grammar_symbol`] for valid symbols. +@ffi.Native, TSStateId, TSSymbol)>() +external int ts_language_next_state( + ffi.Pointer self, + int state, + int symbol, +); + +/// Get the name of this language. This returns `NULL` in older parsers. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_language_name( + ffi.Pointer self, +); + +/// Create a new lookahead iterator for the given language and parse state. +/// +/// This returns `NULL` if state is invalid for the language. +/// +/// Repeatedly using [`ts_lookahead_iterator_next`] and +/// [`ts_lookahead_iterator_current_symbol`] will generate valid symbols in the +/// given parse state. Newly created lookahead iterators will contain the `ERROR` +/// symbol. +/// +/// Lookahead iterators can be useful to generate suggestions and improve syntax +/// error diagnostics. To get symbols valid in an ERROR node, use the lookahead +/// iterator on its first leaf node state. For `MISSING` nodes, a lookahead +/// iterator created on the previous non-extra leaf node may be appropriate. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, TSStateId)>() +external ffi.Pointer ts_lookahead_iterator_new( + ffi.Pointer self, + int state, +); + +/// Delete a lookahead iterator freeing all the memory used. +@ffi.Native)>() +external void ts_lookahead_iterator_delete( + ffi.Pointer self, +); + +/// Reset the lookahead iterator to another state. +/// +/// This returns `true` if the iterator was reset to the given state and `false` +/// otherwise. +@ffi.Native, TSStateId)>() +external bool ts_lookahead_iterator_reset_state( + ffi.Pointer self, + int state, +); + +/// Reset the lookahead iterator. +/// +/// This returns `true` if the language was set successfully and `false` +/// otherwise. +@ffi.Native< + ffi.Bool Function( + ffi.Pointer, ffi.Pointer, TSStateId)>() +external bool ts_lookahead_iterator_reset( + ffi.Pointer self, + ffi.Pointer language, + int state, +); + +/// Get the current language of the lookahead iterator. +@ffi.Native< + ffi.Pointer Function(ffi.Pointer)>() +external ffi.Pointer ts_lookahead_iterator_language( + ffi.Pointer self, +); + +/// Advance the lookahead iterator to the next symbol. +/// +/// This returns `true` if there is a new symbol and `false` otherwise. +@ffi.Native)>() +external bool ts_lookahead_iterator_next( + ffi.Pointer self, +); + +/// Get the current symbol of the lookahead iterator; +@ffi.Native)>() +external int ts_lookahead_iterator_current_symbol( + ffi.Pointer self, +); + +/// Get the current symbol type of the lookahead iterator as a null terminated +/// string. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_lookahead_iterator_current_symbol_name( + ffi.Pointer self, +); + +/// Create a Wasm store. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, ffi.Pointer)>() +external ffi.Pointer ts_wasm_store_new( + ffi.Pointer engine, + ffi.Pointer error, +); + +/// Free the memory associated with the given Wasm store. +@ffi.Native)>() +external void ts_wasm_store_delete( + ffi.Pointer arg0, +); + +/// Create a language from a buffer of Wasm. The resulting language behaves +/// like any other Tree-sitter language, except that in order to use it with +/// a parser, that parser must have a Wasm store. Note that the language +/// can be used with any Wasm store, it doesn't need to be the same store that +/// was used to originally load it. +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer)>() +external ffi.Pointer ts_wasm_store_load_language( + ffi.Pointer arg0, + ffi.Pointer name, + ffi.Pointer wasm, + int wasm_len, + ffi.Pointer error, +); + +/// Get the number of languages instantiated in the given wasm store. +@ffi.Native)>() +external int ts_wasm_store_language_count( + ffi.Pointer arg0, +); + +/// Check if the language came from a Wasm module. If so, then in order to use +/// this language with a Parser, that parser must have a Wasm store assigned. +@ffi.Native)>() +external bool ts_language_is_wasm( + ffi.Pointer arg0, +); + +/// Assign the given Wasm store to the parser. A parser must have a Wasm store +/// in order to use Wasm languages. +@ffi.Native< + ffi.Void Function(ffi.Pointer, ffi.Pointer)>() +external void ts_parser_set_wasm_store( + ffi.Pointer arg0, + ffi.Pointer arg1, +); + +/// Remove the parser's current Wasm store and return it. This returns NULL if +/// the parser doesn't have a Wasm store. +@ffi.Native Function(ffi.Pointer)>() +external ffi.Pointer ts_parser_take_wasm_store( + ffi.Pointer arg0, +); + +/// Set the allocation functions used by the library. +/// +/// By default, Tree-sitter uses the standard libc allocation functions, +/// but aborts the process when an allocation fails. This function lets +/// you supply alternative allocation functions at runtime. +/// +/// If you pass `NULL` for any parameter, Tree-sitter will switch back to +/// its default implementation of that function. +/// +/// If you call this function after the library has already been used, then +/// you must ensure that either: +/// 1. All the existing objects have been freed. +/// 2. The new allocator shares its state with the old one, so it is capable +/// of freeing memory that was allocated by the old allocator. +@ffi.Native< + ffi.Void Function( + ffi.Pointer< + ffi.NativeFunction Function(ffi.Size)>>, + ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function(ffi.Size, ffi.Size)>>, + ffi.Pointer< ffi.NativeFunction< ffi.Pointer Function( - ffi.Pointer, ffi.Size)>> - new_realloc, - ffi.Pointer)>> - new_free, - ) { - return _ts_set_allocator( + ffi.Pointer, ffi.Size)>>, + ffi.Pointer< + ffi.NativeFunction)>>)>() +external void ts_set_allocator( + ffi.Pointer Function(ffi.Size)>> new_malloc, + ffi.Pointer< + ffi + .NativeFunction Function(ffi.Size, ffi.Size)>> new_calloc, + ffi.Pointer< + ffi.NativeFunction< + ffi.Pointer Function(ffi.Pointer, ffi.Size)>> new_realloc, + ffi.Pointer)>> new_free, - ); - } +); - late final _ts_set_allocatorPtr = _lookup< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer< - ffi.NativeFunction Function(ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Size, ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer)>>)>>('ts_set_allocator'); - late final _ts_set_allocator = _ts_set_allocatorPtr.asFunction< - void Function( - ffi.Pointer< - ffi.NativeFunction Function(ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction< - ffi.Pointer Function(ffi.Size, ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, ffi.Size)>>, - ffi.Pointer< - ffi.NativeFunction)>>)>(); - - late final addresses = _SymbolAddresses(this); -} +const addresses = _SymbolAddresses(); class _SymbolAddresses { - final TreeSitter _library; - _SymbolAddresses(this._library); + const _SymbolAddresses(); ffi.Pointer)>> - get ts_parser_delete => _library._ts_parser_deletePtr; + get ts_parser_delete => ffi.Native.addressOf(self.ts_parser_delete); ffi.Pointer)>> - get ts_tree_delete => _library._ts_tree_deletePtr; + get ts_tree_delete => ffi.Native.addressOf(self.ts_tree_delete); ffi.Pointer)>> - get ts_tree_cursor_delete => _library._ts_tree_cursor_deletePtr; + get ts_tree_cursor_delete => + ffi.Native.addressOf(self.ts_tree_cursor_delete); ffi.Pointer)>> - get ts_query_delete => _library._ts_query_deletePtr; + get ts_query_delete => ffi.Native.addressOf(self.ts_query_delete); ffi.Pointer)>> - get ts_query_cursor_delete => _library._ts_query_cursor_deletePtr; + get ts_query_cursor_delete => + ffi.Native.addressOf(self.ts_query_cursor_delete); } +/// / +typedef TSStateId = ffi.Uint16; +typedef DartTSStateId = int; +typedef TSSymbol = ffi.Uint16; +typedef DartTSSymbol = int; +typedef TSFieldId = ffi.Uint16; +typedef DartTSFieldId = int; + final class TSLanguage extends ffi.Opaque {} final class TSParser extends ffi.Opaque {} @@ -2204,15 +1574,51 @@ final class TSQuery extends ffi.Opaque {} final class TSQueryCursor extends ffi.Opaque {} -abstract class TSInputEncoding { - static const int TSInputEncodingUTF8 = 0; - static const int TSInputEncodingUTF16 = 1; +final class TSLookaheadIterator extends ffi.Opaque {} + +typedef DecodeFunctionFunction = ffi.Uint32 Function( + ffi.Pointer string, + ffi.Uint32 length, + ffi.Pointer code_point); +typedef DartDecodeFunctionFunction = int Function(ffi.Pointer string, + int length, ffi.Pointer code_point); +typedef DecodeFunction + = ffi.Pointer>; + +enum TSInputEncoding { + TSInputEncodingUTF8(0), + TSInputEncodingUTF16LE(1), + TSInputEncodingUTF16BE(2), + TSInputEncodingCustom(3); + + final int value; + const TSInputEncoding(this.value); + + static TSInputEncoding fromValue(int value) => switch (value) { + 0 => TSInputEncodingUTF8, + 1 => TSInputEncodingUTF16LE, + 2 => TSInputEncodingUTF16BE, + 3 => TSInputEncodingCustom, + _ => throw ArgumentError('Unknown value for TSInputEncoding: $value'), + }; } -abstract class TSSymbolType { - static const int TSSymbolTypeRegular = 0; - static const int TSSymbolTypeAnonymous = 1; - static const int TSSymbolTypeAuxiliary = 2; +enum TSSymbolType { + TSSymbolTypeRegular(0), + TSSymbolTypeAnonymous(1), + TSSymbolTypeSupertype(2), + TSSymbolTypeAuxiliary(3); + + final int value; + const TSSymbolType(this.value); + + static TSSymbolType fromValue(int value) => switch (value) { + 0 => TSSymbolTypeRegular, + 1 => TSSymbolTypeAnonymous, + 2 => TSSymbolTypeSupertype, + 3 => TSSymbolTypeAuxiliary, + _ => throw ArgumentError('Unknown value for TSSymbolType: $value'), + }; } final class TSPoint extends ffi.Struct { @@ -2246,13 +1652,45 @@ final class TSInput extends ffi.Struct { TSPoint position, ffi.Pointer bytes_read)>> read; - @ffi.Int32() - external int encoding; + @ffi.UnsignedInt() + external int encodingAsInt; + + TSInputEncoding get encoding => TSInputEncoding.fromValue(encodingAsInt); + + external DecodeFunction decode; +} + +final class TSParseState extends ffi.Struct { + external ffi.Pointer payload; + + @ffi.Uint32() + external int current_byte_offset; + + @ffi.Bool() + external bool has_error; +} + +final class TSParseOptions extends ffi.Struct { + external ffi.Pointer payload; + + external ffi.Pointer< + ffi + .NativeFunction state)>> + progress_callback; } -abstract class TSLogType { - static const int TSLogTypeParse = 0; - static const int TSLogTypeLex = 1; +enum TSLogType { + TSLogTypeParse(0), + TSLogTypeLex(1); + + final int value; + const TSLogType(this.value); + + static TSLogType fromValue(int value) => switch (value) { + 0 => TSLogTypeParse, + 1 => TSLogTypeLex, + _ => throw ArgumentError('Unknown value for TSLogType: $value'), + }; } final class TSLogger extends ffi.Struct { @@ -2260,8 +1698,8 @@ final class TSLogger extends ffi.Struct { external ffi.Pointer< ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, ffi.Int32, ffi.Pointer)>> log; + ffi.Void Function(ffi.Pointer payload, + ffi.UnsignedInt log_type, ffi.Pointer buffer)>> log; } final class TSInputEdit extends ffi.Struct { @@ -2295,7 +1733,7 @@ final class TSTreeCursor extends ffi.Struct { external ffi.Pointer id; - @ffi.Array.multi([2]) + @ffi.Array.multi([3]) external ffi.Array context; } @@ -2306,12 +1744,24 @@ final class TSQueryCapture extends ffi.Struct { external int index; } -abstract class TSQuantifier { - static const int TSQuantifierZero = 0; - static const int TSQuantifierZeroOrOne = 1; - static const int TSQuantifierZeroOrMore = 2; - static const int TSQuantifierOne = 3; - static const int TSQuantifierOneOrMore = 4; +enum TSQuantifier { + TSQuantifierZero(0), + TSQuantifierZeroOrOne(1), + TSQuantifierZeroOrMore(2), + TSQuantifierOne(3), + TSQuantifierOneOrMore(4); + + final int value; + const TSQuantifier(this.value); + + static TSQuantifier fromValue(int value) => switch (value) { + 0 => TSQuantifierZero, + 1 => TSQuantifierZeroOrOne, + 2 => TSQuantifierZeroOrMore, + 3 => TSQuantifierOne, + 4 => TSQuantifierOneOrMore, + _ => throw ArgumentError('Unknown value for TSQuantifier: $value'), + }; } final class TSQueryMatch extends ffi.Struct { @@ -2327,34 +1777,127 @@ final class TSQueryMatch extends ffi.Struct { external ffi.Pointer captures; } -abstract class TSQueryPredicateStepType { - static const int TSQueryPredicateStepTypeDone = 0; - static const int TSQueryPredicateStepTypeCapture = 1; - static const int TSQueryPredicateStepTypeString = 2; +enum TSQueryPredicateStepType { + TSQueryPredicateStepTypeDone(0), + TSQueryPredicateStepTypeCapture(1), + TSQueryPredicateStepTypeString(2); + + final int value; + const TSQueryPredicateStepType(this.value); + + static TSQueryPredicateStepType fromValue(int value) => switch (value) { + 0 => TSQueryPredicateStepTypeDone, + 1 => TSQueryPredicateStepTypeCapture, + 2 => TSQueryPredicateStepTypeString, + _ => throw ArgumentError( + 'Unknown value for TSQueryPredicateStepType: $value'), + }; } final class TSQueryPredicateStep extends ffi.Struct { - @ffi.Int32() - external int type; + @ffi.UnsignedInt() + external int typeAsInt; + + TSQueryPredicateStepType get type => + TSQueryPredicateStepType.fromValue(typeAsInt); @ffi.Uint32() external int value_id; } -abstract class TSQueryError { - static const int TSQueryErrorNone = 0; - static const int TSQueryErrorSyntax = 1; - static const int TSQueryErrorNodeType = 2; - static const int TSQueryErrorField = 3; - static const int TSQueryErrorCapture = 4; - static const int TSQueryErrorStructure = 5; - static const int TSQueryErrorLanguage = 6; +enum TSQueryError { + TSQueryErrorNone(0), + TSQueryErrorSyntax(1), + TSQueryErrorNodeType(2), + TSQueryErrorField(3), + TSQueryErrorCapture(4), + TSQueryErrorStructure(5), + TSQueryErrorLanguage(6); + + final int value; + const TSQueryError(this.value); + + static TSQueryError fromValue(int value) => switch (value) { + 0 => TSQueryErrorNone, + 1 => TSQueryErrorSyntax, + 2 => TSQueryErrorNodeType, + 3 => TSQueryErrorField, + 4 => TSQueryErrorCapture, + 5 => TSQueryErrorStructure, + 6 => TSQueryErrorLanguage, + _ => throw ArgumentError('Unknown value for TSQueryError: $value'), + }; +} + +final class TSQueryCursorState extends ffi.Struct { + external ffi.Pointer payload; + + @ffi.Uint32() + external int current_byte_offset; +} + +final class TSQueryCursorOptions extends ffi.Struct { + external ffi.Pointer payload; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer state)>> + progress_callback; +} + +/// The metadata associated with a language. +/// +/// Currently, this metadata can be used to check the [Semantic Version](https://semver.org/) +/// of the language. This version information should be used to signal if a given parser might +/// be incompatible with existing queries when upgrading between major versions, or minor versions +/// if it's in zerover. +final class TSLanguageMetadata extends ffi.Struct { + @ffi.Uint8() + external int major_version; + + @ffi.Uint8() + external int minor_version; + + @ffi.Uint8() + external int patch_version; } +final class wasm_engine_t extends ffi.Opaque {} + /// / -typedef TSSymbol = ffi.Uint16; -typedef TSFieldId = ffi.Uint16; +typedef TSWasmEngine = wasm_engine_t; + +final class TSWasmStore extends ffi.Opaque {} + +enum TSWasmErrorKind { + TSWasmErrorKindNone(0), + TSWasmErrorKindParse(1), + TSWasmErrorKindCompile(2), + TSWasmErrorKindInstantiate(3), + TSWasmErrorKindAllocate(4); + + final int value; + const TSWasmErrorKind(this.value); + + static TSWasmErrorKind fromValue(int value) => switch (value) { + 0 => TSWasmErrorKindNone, + 1 => TSWasmErrorKindParse, + 2 => TSWasmErrorKindCompile, + 3 => TSWasmErrorKindInstantiate, + 4 => TSWasmErrorKindAllocate, + _ => throw ArgumentError('Unknown value for TSWasmErrorKind: $value'), + }; +} + +final class TSWasmError extends ffi.Struct { + @ffi.UnsignedInt() + external int kindAsInt; + + TSWasmErrorKind get kind => TSWasmErrorKind.fromValue(kindAsInt); + + external ffi.Pointer message; +} -const int TREE_SITTER_LANGUAGE_VERSION = 14; +const int TREE_SITTER_LANGUAGE_VERSION = 15; const int TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION = 13; diff --git a/tree_sitter/lib/src/parser_generated_bindings.dart b/tree_sitter/lib/src/parser_generated_bindings.dart index 618195a..27fa041 100644 --- a/tree_sitter/lib/src/parser_generated_bindings.dart +++ b/tree_sitter/lib/src/parser_generated_bindings.dart @@ -4,93 +4,12 @@ // ignore_for_file: type=lint import 'dart:ffi' as ffi; -final class TSLanguage extends ffi.Struct { - @ffi.Uint32() - external int version; - - @ffi.Uint32() - external int symbol_count; - - @ffi.Uint32() - external int alias_count; - - @ffi.Uint32() - external int token_count; - - @ffi.Uint32() - external int external_token_count; - - @ffi.Uint32() - external int state_count; - - @ffi.Uint32() - external int large_state_count; - - @ffi.Uint32() - external int production_id_count; - - @ffi.Uint32() - external int field_count; - - @ffi.Uint16() - external int max_alias_sequence_length; - - external ffi.Pointer parse_table; - - external ffi.Pointer small_parse_table; - - external ffi.Pointer small_parse_table_map; - - external ffi.Pointer parse_actions; - - external ffi.Pointer> symbol_names; - - external ffi.Pointer> field_names; - - external ffi.Pointer field_map_slices; - - external ffi.Pointer field_map_entries; - - external ffi.Pointer symbol_metadata; - - external ffi.Pointer public_symbol_map; - - external ffi.Pointer alias_map; - - external ffi.Pointer alias_sequences; - - external ffi.Pointer lex_modes; - - external ffi.Pointer< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, TSStateId)>> lex_fn; - - external ffi.Pointer< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, TSStateId)>> keyword_lex_fn; - - @TSSymbol() - external int keyword_capture_token; - - external UnnamedStruct4 external_scanner; - - external ffi.Pointer primary_state_ids; -} - -final class TSParseActionEntry extends ffi.Union { - external TSParseAction action; - - external UnnamedStruct3 entry; -} - -final class TSParseAction extends ffi.Union { - external UnnamedStruct1 shift; - - external UnnamedStruct2 reduce; - - @ffi.Uint8() - external int type; -} +typedef TSStateId = ffi.Uint16; +typedef DartTSStateId = int; +typedef TSSymbol = ffi.Uint16; +typedef DartTSSymbol = int; +typedef TSFieldId = ffi.Uint16; +typedef DartTSFieldId = int; final class UnnamedStruct1 extends ffi.Struct { @ffi.Uint8() @@ -106,8 +25,6 @@ final class UnnamedStruct1 extends ffi.Struct { external bool repetition; } -typedef TSStateId = ffi.Uint16; - final class UnnamedStruct2 extends ffi.Struct { @ffi.Uint8() external int type; @@ -125,7 +42,14 @@ final class UnnamedStruct2 extends ffi.Struct { external int production_id; } -typedef TSSymbol = ffi.Uint16; +final class TSParseAction extends ffi.Union { + external UnnamedStruct1 shift; + + external UnnamedStruct2 reduce; + + @ffi.Uint8() + external int type; +} final class UnnamedStruct3 extends ffi.Struct { @ffi.Uint8() @@ -135,7 +59,13 @@ final class UnnamedStruct3 extends ffi.Struct { external bool reusable; } -final class TSFieldMapSlice extends ffi.Struct { +final class TSParseActionEntry extends ffi.Union { + external TSParseAction action; + + external UnnamedStruct3 entry; +} + +final class TSMapSlice extends ffi.Struct { @ffi.Uint16() external int index; @@ -154,8 +84,6 @@ final class TSFieldMapEntry extends ffi.Struct { external bool inherited; } -typedef TSFieldId = ffi.Uint16; - final class TSSymbolMetadata extends ffi.Struct { @ffi.Bool() external bool visible; @@ -167,12 +95,15 @@ final class TSSymbolMetadata extends ffi.Struct { external bool supertype; } -final class TSLexMode extends ffi.Struct { +final class TSLexerMode extends ffi.Struct { @ffi.Uint16() external int lex_state; @ffi.Uint16() external int external_lex_state; + + @ffi.Uint16() + external int reserved_word_set_id; } final class TSLexer extends ffi.Struct { @@ -187,18 +118,23 @@ final class TSLexer extends ffi.Struct { advance; external ffi - .Pointer)>> + .Pointer)>> mark_end; - external ffi.Pointer< - ffi.NativeFunction)>> get_column; + external ffi + .Pointer)>> + get_column; external ffi - .Pointer)>> + .Pointer)>> is_at_included_range_start; external ffi .Pointer)>> eof; + + external ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer)>> log; } final class UnnamedStruct4 extends ffi.Struct { @@ -210,7 +146,7 @@ final class UnnamedStruct4 extends ffi.Struct { create; external ffi - .Pointer)>> + .Pointer)>> destroy; external ffi.Pointer< @@ -229,11 +165,142 @@ final class UnnamedStruct4 extends ffi.Struct { ffi.UnsignedInt)>> deserialize; } -abstract class TSParseActionType { - static const int TSParseActionTypeShift = 0; - static const int TSParseActionTypeReduce = 1; - static const int TSParseActionTypeAccept = 2; - static const int TSParseActionTypeRecover = 3; +final class TSLanguageMetadata extends ffi.Struct { + @ffi.Uint8() + external int major_version; + + @ffi.Uint8() + external int minor_version; + + @ffi.Uint8() + external int patch_version; +} + +final class TSLanguage extends ffi.Struct { + @ffi.Uint32() + external int abi_version; + + @ffi.Uint32() + external int symbol_count; + + @ffi.Uint32() + external int alias_count; + + @ffi.Uint32() + external int token_count; + + @ffi.Uint32() + external int external_token_count; + + @ffi.Uint32() + external int state_count; + + @ffi.Uint32() + external int large_state_count; + + @ffi.Uint32() + external int production_id_count; + + @ffi.Uint32() + external int field_count; + + @ffi.Uint16() + external int max_alias_sequence_length; + + external ffi.Pointer parse_table; + + external ffi.Pointer small_parse_table; + + external ffi.Pointer small_parse_table_map; + + external ffi.Pointer parse_actions; + + external ffi.Pointer> symbol_names; + + external ffi.Pointer> field_names; + + external ffi.Pointer field_map_slices; + + external ffi.Pointer field_map_entries; + + external ffi.Pointer symbol_metadata; + + external ffi.Pointer public_symbol_map; + + external ffi.Pointer alias_map; + + external ffi.Pointer alias_sequences; + + external ffi.Pointer lex_modes; + + external ffi.Pointer< + ffi + .NativeFunction, TSStateId)>> + lex_fn; + + external ffi.Pointer< + ffi + .NativeFunction, TSStateId)>> + keyword_lex_fn; + + @TSSymbol() + external int keyword_capture_token; + + external UnnamedStruct4 external_scanner; + + external ffi.Pointer primary_state_ids; + + external ffi.Pointer name; + + external ffi.Pointer reserved_words; + + @ffi.Uint16() + external int max_reserved_word_set_size; + + @ffi.Uint32() + external int supertype_count; + + external ffi.Pointer supertype_symbols; + + external ffi.Pointer supertype_map_slices; + + external ffi.Pointer supertype_map_entries; + + external TSLanguageMetadata metadata; +} + +enum TSParseActionType { + TSParseActionTypeShift(0), + TSParseActionTypeReduce(1), + TSParseActionTypeAccept(2), + TSParseActionTypeRecover(3); + + final int value; + const TSParseActionType(this.value); + + static TSParseActionType fromValue(int value) => switch (value) { + 0 => TSParseActionTypeShift, + 1 => TSParseActionTypeReduce, + 2 => TSParseActionTypeAccept, + 3 => TSParseActionTypeRecover, + _ => throw ArgumentError('Unknown value for TSParseActionType: $value'), + }; +} + +final class TSLexMode extends ffi.Struct { + @ffi.Uint16() + external int lex_state; + + @ffi.Uint16() + external int external_lex_state; +} + +final class TSCharacterRange extends ffi.Struct { + @ffi.Int32() + external int start; + + @ffi.Int32() + external int end; } const int ts_builtin_sym_error = 65535; diff --git a/tree_sitter/lib/tree_sitter.dart b/tree_sitter/lib/tree_sitter.dart index 76ded68..016cf30 100644 --- a/tree_sitter/lib/tree_sitter.dart +++ b/tree_sitter/lib/tree_sitter.dart @@ -4,74 +4,76 @@ library; import 'dart:convert'; -import 'dart:ffi'; import 'dart:ffi' as ffi; -import 'dart:io'; +import 'dart:ffi'; import 'dart:typed_data'; -import 'package:dylib/dylib.dart'; import 'package:ffi/ffi.dart'; import 'package:tree_sitter/tree_sitter.dart'; +// Import @Native functions - they are now at the top level +import 'src/generated_bindings.dart' as ts; import 'src/parser_generated_bindings.dart' as details; import 'src/utils.dart'; +export 'src/dart_language.dart' show treeSitterDart; export 'src/generated_bindings.dart'; -/// Exposes the tree sitter C API as a minimal dart ffi wrapper -final treeSitterApi = TreeSitterConfig.instance.ffiApi; - -/// Configuration of the package to find the correct shared libraries -final class TreeSitterConfig { - static String _dylibLocation = - resolveDylibPath('tree-sitter', path: Directory.current.path); - late final ffiApi = TreeSitter(DynamicLibrary.open(_dylibLocation)); - - /// Sets the path to find the tree sitter shared libraries - static void setLibraryPath(String path) { - _dylibLocation = path; - } - - TreeSitterConfig._(); - static final instance = TreeSitterConfig._(); -} - /// A dart interface to the tree sitter API /// /// - Handles basic parser / language setup base class Parser implements Finalizable { /// The shared library for the language used by this parser - final String sharedLibrary; + final String? sharedLibrary; /// The entry point for the language used by this parser - final String entryPoint; + final String? entryPoint; /// The c ffi parser instance /// /// Automatically disposed by [Parser] using dart's Finalizable support - late final parser = treeSitterApi.ts_parser_new(); + late final parser = ts.ts_parser_new(); - late final _langDylib = DynamicLibrary.open(sharedLibrary); - late final _languagePtr = - _langDylib.lookup Function()>>( - entryPoint); - late final _language = - _languagePtr.asFunction Function()>()(); + late final ffi.Pointer _language; - final _finalizer = - NativeFinalizer(treeSitterApi.addresses.ts_parser_delete.cast()); + final _finalizer = NativeFinalizer(ts.addresses.ts_parser_delete.cast()); /// Creates a new parser with the given shared library and entry point /// /// Sets up a language for the parser to use based on those parameters Parser({required this.sharedLibrary, required this.entryPoint}) { + final langDylib = DynamicLibrary.open(sharedLibrary!); + final languagePtr = langDylib.lookup< + ffi.NativeFunction Function()>>(entryPoint!); + _language = languagePtr.asFunction Function()>()(); + _finalizer.attach(this, parser.cast(), detach: this); - if (!treeSitterApi.ts_parser_set_language(parser, _language)) { + if (!ts.ts_parser_set_language(parser, _language)) { throw Exception( 'Failed to set language using the provided shared library and entry point'); } } + /// Creates a new parser with a native language binding + /// + /// Uses a language pointer obtained via @Native annotation for efficient + /// static linking. This is the preferred method when using Dart 3.0+. + /// + /// Example: + /// ```dart + /// final parser = Parser.fromLanguage(treeSitterDart()); + /// final tree = parser.parse('class A {}'); + /// ``` + Parser.fromLanguage(ffi.Pointer language) + : sharedLibrary = null, + entryPoint = null, + _language = language { + _finalizer.attach(this, parser.cast(), detach: this); + if (!ts.ts_parser_set_language(parser, _language)) { + throw Exception('Failed to set language'); + } + } + details.TSLanguage get language => _language.cast().ref; /// Parses out a tree from the given string @@ -79,28 +81,28 @@ base class Parser implements Finalizable { _contents = program; final (pProgram, len) = program.toNativeUtf8Len(); if (encoding == null) { - return Tree(treeSitterApi.ts_parser_parse_string( - parser, nullptr, pProgram.cast(), len)); + return Tree( + ts.ts_parser_parse_string(parser, nullptr, pProgram.cast(), len)); } else { - return Tree(treeSitterApi.ts_parser_parse_string_encoding( - parser, nullptr, pProgram.cast(), len, encoding)); + return Tree(ts.ts_parser_parse_string_encoding(parser, nullptr, + pProgram.cast(), len, TSInputEncoding.values[encoding])); } } String? _contents; List get contents => utf8.encode(_contents ?? ''); - void reset() => treeSitterApi.ts_parser_reset(parser); + void reset() => ts.ts_parser_reset(parser); set timeoutMicros(int timeout) => - treeSitterApi.ts_parser_set_timeout_micros(parser, timeout); + ts.ts_parser_set_timeout_micros(parser, timeout); - int get timeoutMicros => treeSitterApi.ts_parser_timeout_micros(parser); + int get timeoutMicros => ts.ts_parser_timeout_micros(parser); set cancellationFlag(CancelToken flag) => - treeSitterApi.ts_parser_set_cancellation_flag(parser, flag._token); + ts.ts_parser_set_cancellation_flag(parser, flag._token); CancelToken get cancellationFlag => - CancelToken.fromToken(treeSitterApi.ts_parser_cancellation_flag(parser)); + CancelToken.fromToken(ts.ts_parser_cancellation_flag(parser)); String getText(TSNode namedChild) { final text = contents.sublist(namedChild.startByte, namedChild.endByte); @@ -122,8 +124,7 @@ final class CancelToken implements Finalizable { base class Tree implements Finalizable { final Pointer tree; - final _finalizer = - NativeFinalizer(treeSitterApi.addresses.ts_tree_delete.cast()); + final _finalizer = NativeFinalizer(ts.addresses.ts_tree_delete.cast()); Tree(this.tree) { if (tree == nullptr) { @@ -132,29 +133,27 @@ base class Tree implements Finalizable { _finalizer.attach(this, tree.cast(), detach: this); } - TSNode get root => treeSitterApi.ts_tree_root_node(tree); + TSNode get root => ts.ts_tree_root_node(tree); - Tree get copy => Tree(treeSitterApi.ts_tree_copy(tree)); + Tree get copy => Tree(ts.ts_tree_copy(tree)); details.TSLanguage get language => - treeSitterApi.ts_tree_language(tree).cast().ref; + ts.ts_tree_language(tree).cast().ref; } base class TreeCursor implements Finalizable { late final Pointer cursor = malloc(1); - final _finalizer = - NativeFinalizer(treeSitterApi.addresses.ts_tree_cursor_delete.cast()); + final _finalizer = NativeFinalizer(ts.addresses.ts_tree_cursor_delete.cast()); final TSNode node; TreeCursor(this.node) { - cursor.ref = treeSitterApi.ts_tree_cursor_new(node); + cursor.ref = ts.ts_tree_cursor_new(node); _finalizer.attach(this, cursor.cast(), detach: this); } } base class Query implements Finalizable { late final Pointer query; - final _finalizer = - NativeFinalizer(treeSitterApi.addresses.ts_query_delete.cast()); + final _finalizer = NativeFinalizer(ts.addresses.ts_query_delete.cast()); Query(this.query) { _finalizer.attach(this, query.cast(), detach: this); } @@ -164,8 +163,8 @@ base class Query implements Finalizable { final (pSource, len) = source.toNativeUtf8Len(); using((alloc) { final errorOffset = alloc(1); - final errorType = alloc(1); - query = treeSitterApi.ts_query_new( + final errorType = alloc(1); + query = ts.ts_query_new( language, pSource.cast(), len, errorOffset, errorType); if (query == nullptr) { final errOff = errorOffset.value; @@ -178,7 +177,9 @@ base class Query implements Finalizable { } extension TSApiIntX on int { - String get queryError => switch (this) { + String get queryError => switch (this < TSQueryError.values.length + ? TSQueryError.values[this] + : null) { TSQueryError.TSQueryErrorNone => 'TSQueryErrorNone', TSQueryError.TSQueryErrorSyntax => 'TSQueryErrorSyntax', TSQueryError.TSQueryErrorNodeType => 'TSQueryErrorNodeType', @@ -189,7 +190,10 @@ extension TSApiIntX on int { _ => 'Unknown error code $this' }; - String get queryPredicateStepType => switch (this) { + String get queryPredicateStepType => + switch (this < TSQueryPredicateStepType.values.length + ? TSQueryPredicateStepType.values[this] + : null) { TSQueryPredicateStepType.TSQueryPredicateStepTypeCapture => 'TSQueryPredicateStepTypeCapture', TSQueryPredicateStepType.TSQueryPredicateStepTypeString => @@ -199,7 +203,9 @@ extension TSApiIntX on int { _ => 'Unknown predicate step type $this' }; - String get quantifier => switch (this) { + String get quantifier => switch (this < TSQuantifier.values.length + ? TSQuantifier.values[this] + : null) { TSQuantifier.TSQuantifierZero => 'TSQuantifierZero', TSQuantifier.TSQuantifierZeroOrOne => 'TSQuantifierZeroOrOne', TSQuantifier.TSQuantifierZeroOrMore => 'TSQuantifierZeroOrMore', @@ -208,20 +214,28 @@ extension TSApiIntX on int { _ => 'Unknown predicate step type $this' }; - String get symbolType => switch (this) { + String get symbolType => switch (this < TSSymbolType.values.length + ? TSSymbolType.values[this] + : null) { TSSymbolType.TSSymbolTypeRegular => 'TSSymbolTypeRegular', TSSymbolType.TSSymbolTypeAnonymous => 'TSSymbolTypeAnonymous', TSSymbolType.TSSymbolTypeAuxiliary => 'TSSymbolTypeAuxiliary', _ => 'Unknown symbol type $this' }; - String get inputEncoding => switch (this) { + String get inputEncoding => switch (this < TSInputEncoding.values.length + ? TSInputEncoding.values[this] + : null) { TSInputEncoding.TSInputEncodingUTF8 => 'TSInputEncodingUTF8', - TSInputEncoding.TSInputEncodingUTF16 => 'TSInputEncodingUTF16', + TSInputEncoding.TSInputEncodingUTF16LE => 'TSInputEncodingUTF16LE', + TSInputEncoding.TSInputEncodingUTF16BE => 'TSInputEncodingUTF16BE', + TSInputEncoding.TSInputEncodingCustom => 'TSInputEncodingCustom', _ => 'Unknown input encoding $this' }; - String get logType => switch (this) { + String get logType => switch (this < TSInputEncoding.values.length + ? TSLogType.values[this] + : null) { TSLogType.TSLogTypeParse => 'TSLogTypeParse', TSLogType.TSLogTypeLex => 'TSLogTypeLex', _ => 'Unknown log type $this' @@ -229,9 +243,8 @@ extension TSApiIntX on int { } base class QueryCursor implements Finalizable { - final Pointer cursor = treeSitterApi.ts_query_cursor_new(); - final _finalizer = - NativeFinalizer(treeSitterApi.addresses.ts_query_delete.cast()); + final Pointer cursor = ts.ts_query_cursor_new(); + final _finalizer = NativeFinalizer(ts.addresses.ts_query_delete.cast()); QueryCursor() { _finalizer.attach(this, cursor.cast(), detach: this); } @@ -239,69 +252,67 @@ base class QueryCursor implements Finalizable { extension TSNodeX on TSNode { String get string { - final root = treeSitterApi.ts_node_string(this); + final root = ts.ts_node_string(this); final result = root.cast().toDartString(); malloc.free(root); return result; } - String get nodeType => - treeSitterApi.ts_node_type(this).cast().toDartString(); + String get nodeType => ts.ts_node_type(this).cast().toDartString(); - int get symbol => treeSitterApi.ts_node_symbol(this); + int get symbol => ts.ts_node_symbol(this); - int get startByte => treeSitterApi.ts_node_start_byte(this); + int get startByte => ts.ts_node_start_byte(this); - int get endByte => treeSitterApi.ts_node_end_byte(this); + int get endByte => ts.ts_node_end_byte(this); - TSPoint get startPoint => treeSitterApi.ts_node_start_point(this); + TSPoint get startPoint => ts.ts_node_start_point(this); - TSPoint get endPoint => treeSitterApi.ts_node_end_point(this); + TSPoint get endPoint => ts.ts_node_end_point(this); - bool get isNull => treeSitterApi.ts_node_is_null(this); + bool get isNull => ts.ts_node_is_null(this); - bool get isNamed => treeSitterApi.ts_node_is_named(this); + bool get isNamed => ts.ts_node_is_named(this); - bool get isMissing => treeSitterApi.ts_node_is_missing(this); + bool get isMissing => ts.ts_node_is_missing(this); - bool get isExtra => treeSitterApi.ts_node_is_extra(this); + bool get isExtra => ts.ts_node_is_extra(this); - bool get hasChanges => treeSitterApi.ts_node_has_changes(this); + bool get hasChanges => ts.ts_node_has_changes(this); - bool get hasError => treeSitterApi.ts_node_has_error(this); + bool get hasError => ts.ts_node_has_error(this); - TSNode get parent => treeSitterApi.ts_node_parent(this); + TSNode get parent => ts.ts_node_parent(this); - TSNode child(int childIndex) => treeSitterApi.ts_node_child(this, childIndex); + TSNode child(int childIndex) => ts.ts_node_child(this, childIndex); - String fieldNameForChild(int childIndex) => treeSitterApi + String fieldNameForChild(int childIndex) => ts .ts_node_field_name_for_child(this, childIndex) .cast() .toDartString(); - int get childCount => treeSitterApi.ts_node_child_count(this); + int get childCount => ts.ts_node_child_count(this); - TSNode namedChild(int childIndex) => - treeSitterApi.ts_node_named_child(this, childIndex); + TSNode namedChild(int childIndex) => ts.ts_node_named_child(this, childIndex); - int get namedChildCount => treeSitterApi.ts_node_named_child_count(this); + int get namedChildCount => ts.ts_node_named_child_count(this); TSNode childByFieldName(String fieldName) { final (pFieldName, nameLength) = fieldName.toNativeUtf8Len(); - final result = treeSitterApi.ts_node_child_by_field_name( - this, pFieldName.cast(), nameLength); + final result = + ts.ts_node_child_by_field_name(this, pFieldName.cast(), nameLength); malloc.free(pFieldName); return result; } TSNode childByFieldId(int fieldId) => - treeSitterApi.ts_node_child_by_field_id(this, fieldId); + ts.ts_node_child_by_field_id(this, fieldId); - TSNode get nextSibling => treeSitterApi.ts_node_next_sibling(this); - TSNode get prevSibling => treeSitterApi.ts_node_prev_sibling(this); + TSNode get nextSibling => ts.ts_node_next_sibling(this); + TSNode get prevSibling => ts.ts_node_prev_sibling(this); - TSNode get nextNamedSibling => treeSitterApi.ts_node_next_named_sibling(this); - TSNode get prevNamedSibling => treeSitterApi.ts_node_prev_named_sibling(this); + TSNode get nextNamedSibling => ts.ts_node_next_named_sibling(this); + TSNode get prevNamedSibling => ts.ts_node_prev_named_sibling(this); } extension on String { diff --git a/tree_sitter/parser_config.yaml b/tree_sitter/parser_config.yaml index 34ec477..2665963 100644 --- a/tree_sitter/parser_config.yaml +++ b/tree_sitter/parser_config.yaml @@ -3,6 +3,17 @@ description: "C Bindings to the TreeSitter Parser library" output: 'lib/src/parser_generated_bindings.dart' headers: entry-points: - - 'tree-sitter/lib/include/tree_sitter/parser.h' + - 'tree-sitter/lib/src/parser.h' include-directives: - - 'tree-sitter/lib/include/tree_sitter/parser.h' \ No newline at end of file + - 'tree-sitter/lib/src/parser.h' +# Configure ffigen to generate @Native annotations (Dart 3.0+) +# This enables efficient static linking instead of dynamic library loading +# Note: assetId is omitted to allow fallback to process lookup +ffi-native: +llvm-path: + - '/usr/lib/llvm-18' + - '/usr/lib/llvm-17' + - '/usr/lib/llvm-16' + - '/usr/lib/llvm-14' + - '/usr/lib/llvm-11' + - '/usr/local/opt/llvm' \ No newline at end of file diff --git a/tree_sitter/pubspec.yaml b/tree_sitter/pubspec.yaml index 2a2a552..c20d24a 100644 --- a/tree_sitter/pubspec.yaml +++ b/tree_sitter/pubspec.yaml @@ -1,26 +1,26 @@ name: tree_sitter description: A tree sitter parsing library -version: 0.1.2 +version: 0.2.0 repository: https://github.com/UserNobody14/tree-sitter-dart environment: - sdk: ">=3.0.0 <3.4.0" + sdk: ">=3.3.0 <4.0.0" dependencies: dylib: ^0.3.3 - args: ^2.4.1 - ffi: ^2.0.1 - freezed_annotation: ^2.2.0 - path: ^1.8.3 - json_annotation: ^4.8.1 + args: ^2.7.0 + ffi: ^2.1.4 + freezed_annotation: ^3.1.0 + path: ^1.9.1 + json_annotation: ^4.9.0 dev_dependencies: - lints: ^2.1.0 - test: ^1.24.2 - ffigen: ^8.0.2 - freezed: ^2.3.4 - json_serializable: ^6.7.0 - build_runner: ^2.4.4 + lints: ^6.0.0 + test: ^1.26.3 + ffigen: ^19.1.0 + freezed: ^3.2.3 + json_serializable: ^6.11.1 + build_runner: ^2.9.0 executables: tsdart: gen_grammar \ No newline at end of file diff --git a/tree_sitter/test/tree_sitter_test.dart b/tree_sitter/test/tree_sitter_test.dart index cb930cb..a081730 100644 --- a/tree_sitter/test/tree_sitter_test.dart +++ b/tree_sitter/test/tree_sitter_test.dart @@ -5,12 +5,26 @@ import 'package:test/test.dart'; import 'package:tree_sitter/tree_sitter.dart'; void main() { - test('calculate', () { - final parser = Parser( - sharedLibrary: resolveDylibPath('dart', path: Directory.current.path), - entryPoint: 'tree_sitter_dart'); - final program = "class A {}"; - final tree = parser.parse(program); - print(tree.root.string); + group('Parser with dynamic loading', () { + test('parse with dynamic library loading', () { + final parser = Parser( + sharedLibrary: resolveDylibPath('dart', path: Directory.current.path), + entryPoint: 'tree_sitter_dart'); + final program = "class A {}"; + final tree = parser.parse(program); + print(tree.root.string); + expect(tree.root.string, isNotEmpty); + }); + }); + + group('Parser with @Native annotation', () { + test('parse with native language binding', () { + // Use the @Native binding for efficient static linking + final parser = Parser.fromLanguage(treeSitterDart()); + final program = "class A {}"; + final tree = parser.parse(program); + print(tree.root.string); + expect(tree.root.string, isNotEmpty); + }); }); }