This commit is contained in:
mahaat 2026-04-20 01:10:00 +08:00 committed by GitHub
commit 0e81b0038c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 405 additions and 6 deletions

10
pnpm-lock.yaml generated
View file

@ -1002,8 +1002,8 @@ importers:
specifier: ^0.2.3
version: 0.2.4
tree-sitter-wasms:
specifier: ^0.1.12
version: 0.1.12
specifier: ^0.1.13
version: 0.1.13
turndown:
specifier: ^7.2.0
version: 7.2.0
@ -10242,8 +10242,8 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
tree-sitter-wasms@0.1.12:
resolution: {integrity: sha512-N9Jp+dkB23Ul5Gw0utm+3pvG4km4Fxsi2jmtMFg7ivzwqWPlSyrYQIrOmcX+79taVfcHEA+NzP0hl7vXL8DNUQ==}
tree-sitter-wasms@0.1.13:
resolution: {integrity: sha512-wT+cR6DwaIz80/vho3AvSF0N4txuNx/5bcRKoXouOfClpxh/qqrF4URNLQXbbt8MaAxeksZcZd1j8gcGjc+QxQ==}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
@ -21375,7 +21375,7 @@ snapshots:
tree-kill@1.2.2: {}
tree-sitter-wasms@0.1.12: {}
tree-sitter-wasms@0.1.13: {}
trim-lines@3.0.1: {}

View file

@ -529,7 +529,7 @@
"strip-bom": "^5.0.0",
"tiktoken": "^1.0.21",
"tmp": "^0.2.3",
"tree-sitter-wasms": "^0.1.12",
"tree-sitter-wasms": "^0.1.13",
"turndown": "^7.2.0",
"undici": "^6.21.3",
"uuid": "^11.1.0",

View file

@ -0,0 +1,274 @@
import { testParseSourceCodeDefinitions, debugLog } from "./helpers"
import { dartQuery } from "../queries"
// Dart test options
const dartOptions = {
language: "dart",
wasmFile: "tree-sitter-dart.wasm",
queryString: dartQuery,
extKey: "dart",
}
describe("parseSourceCodeDefinitionsForFile with Dart", () => {
let parseResult: string | undefined
beforeAll(async () => {
const dartCode = `
// Class definition with constructor
class MyClass {
String name;
int age;
MyClass(this.name, this.age);
void greet() {
print('Hello, \$name!');
}
String get description => 'Name: \$name, Age: \$age';
set description(String value) {
// setter implementation
}
}
// Factory constructor
class LoggerFactory {
LoggerFactory._();
factory LoggerFactory.create() {
return LoggerFactory._();
}
}
// Mixin declaration
mixin MyMixin {
void mixinMethod() {
print('Mixin method called');
}
}
// Extension declaration
extension StringExtension on String {
int get length => this.length;
String capitalize() {
return '\${this[0].toUpperCase()}\${substring(1)}';
}
}
// Enum declaration
enum Status {
active,
inactive,
pending;
String get displayName {
switch (this) {
case Status.active:
return 'Active';
case Status.inactive:
return 'Inactive';
case Status.pending:
return 'Pending';
}
}
}
// Type alias
typedef MyType = Map<String, int>;
typedef Callback = void Function(String);
// Standalone function
void mainFunction() {
var instance = MyClass('test', 25);
instance.greet();
var logger = LoggerFactory.create();
var status = Status.active;
print(status.displayName);
}
// Function with parameters
String formatUser(String name, int age) {
return '\$name is \$age years old';
}
// Operator overloading
class Vector {
final double x, y;
Vector(this.x, this.y);
Vector operator +(Vector other) {
return Vector(x + other.x, y + other.y);
}
bool operator ==(Object other) {
return other is Vector && x == other.x && y == other.y;
}
}
// Class with mixin
class EnhancedClass with MyMixin {
void doSomething() {
mixinMethod();
}
}
// Generic class
class Container<T> {
T value;
Container(this.value);
T get() => value;
void set(T newValue) {
value = newValue;
}
}
// Abstract class
abstract class Shape {
double get area;
void draw();
}
// Interface-like class
class Drawable {
void render() {}
}
// Static methods and properties
class MathUtils {
static const double pi = 3.14159;
static double circleArea(double radius) {
return pi * radius * radius;
}
}
// Cascade notation usage
void cascadeExample() {
var builder = StringBuilder()
..write('Hello')
..write(' ')
..write('World')
..toString();
}
class StringBuilder {
String _buffer = '';
void write(String text) {
_buffer += text;
}
String toString() => _buffer;
}
`
parseResult = await testParseSourceCodeDefinitions("test.dart", dartCode, dartOptions)
debugLog("Dart Parse Result:", parseResult)
})
it("should parse class definitions", () => {
expect(parseResult).toMatch(/class MyClass \{/)
expect(parseResult).toMatch(/class LoggerFactory \{/)
expect(parseResult).toMatch(/class Vector \{/)
expect(parseResult).toMatch(/class EnhancedClass with/)
expect(parseResult).toMatch(/class Container</)
expect(parseResult).toMatch(/abstract class Shape \{/)
expect(parseResult).toMatch(/class Drawable \{/)
expect(parseResult).toMatch(/class MathUtils \{/)
expect(parseResult).toMatch(/class StringBuilder \{/)
})
it("should parse method definitions", () => {
expect(parseResult).toMatch(/greet/)
expect(parseResult).toMatch(/description/) // getter
expect(parseResult).toMatch(/create/) // factory constructor
expect(parseResult).toMatch(/operator \+/) // operator
expect(parseResult).toMatch(/operator ==/) // operator
expect(parseResult).toMatch(/doSomething/)
expect(parseResult).toMatch(/get/)
expect(parseResult).toMatch(/set/)
expect(parseResult).toMatch(/render/)
expect(parseResult).toMatch(/circleArea/)
expect(parseResult).toMatch(/write/)
expect(parseResult).toMatch(/toString/)
})
it("should parse mixin declarations", () => {
expect(parseResult).toMatch(/mixin MyMixin/)
})
it("should parse extension declarations", () => {
expect(parseResult).toMatch(/extension StringExtension/)
})
it("should parse enum declarations", () => {
expect(parseResult).toMatch(/enum Status/)
})
it("should parse type aliases", () => {
expect(parseResult).toMatch(/typedef MyType/)
expect(parseResult).toMatch(/typedef Callback/)
})
it("should parse function definitions", () => {
expect(parseResult).toMatch(/mainFunction/)
expect(parseResult).toMatch(/formatUser/)
expect(parseResult).toMatch(/cascadeExample/)
})
it("should handle constructor definitions", () => {
expect(parseResult).toMatch(/MyClass\(/) // constructor
expect(parseResult).toMatch(/Vector\(/) // constructor
expect(parseResult).toMatch(/Container\(/) // constructor
})
it("should handle getter and setter definitions", () => {
expect(parseResult).toMatch(/get description/)
expect(parseResult).toMatch(/set description/)
expect(parseResult).toMatch(/get area/)
expect(parseResult).toMatch(/get length/) // extension getter
})
it("should handle operator definitions", () => {
expect(parseResult).toMatch(/operator \+/)
expect(parseResult).toMatch(/operator ==/)
})
it("should handle factory constructors", () => {
expect(parseResult).toMatch(/factory LoggerFactory\.create\(/)
})
it("should handle generic classes", () => {
expect(parseResult).toMatch(/class Container/)
})
it("should handle abstract classes", () => {
expect(parseResult).toMatch(/abstract class Shape/)
})
it("should handle static methods and properties", () => {
expect(parseResult).toMatch(/static double circleArea/)
})
it("should parse variable initialization with identifier reference", () => {
expect(parseResult).toMatch(/var instance = MyClass/)
expect(parseResult).toMatch(/var status = Status/)
})
it("should parse variable initialization with method calls", () => {
expect(parseResult).toMatch(/var logger = LoggerFactory\.create\(\)/)
})
it("should parse reference patterns", () => {
expect(parseResult).toMatch(/instance\.greet/)
expect(parseResult).toMatch(/status\.displayName/)
})
})

View file

@ -90,6 +90,8 @@ const extensions = [
"erb",
// Visual Basic .NET
"vb",
// Dart
"dart",
].map((e) => `.${e}`)
export { extensions }

View file

@ -28,6 +28,7 @@ import {
embeddedTemplateQuery,
elispQuery,
elixirQuery,
dartQuery,
} from "./queries"
export interface LanguageParser {
@ -137,6 +138,10 @@ export async function loadRequiredLanguageParsers(filesToParse: string[], source
language = await loadLanguage("c_sharp", sourceDirectory)
query = new Query(language, csharpQuery)
break
case "dart":
language = await loadLanguage("dart", sourceDirectory)
query = new Query(language, dartQuery)
break
case "rb":
language = await loadLanguage("ruby", sourceDirectory)
query = new Query(language, rubyQuery)

View file

@ -0,0 +1,117 @@
/*
Dart Tree-sitter Query Patterns
This file contains query patterns for Dart language constructs:
- class definitions - Captures standard class definitions
- method signatures - Captures all method types (getters, setters, constructors, factory, operators)
- function signatures - Captures standalone function definitions
- mixin declarations - Captures Dart mixin definitions
- extension declarations - Captures extension methods on existing types
- enum declarations - Captures enum definitions
- type aliases - Captures typedef declarations
- references - Captures class instantiation, method calls, property access
*/
export default `
; Class definitions
(class_definition
name: (identifier) @name) @definition.class
; Method signatures (various types)
(method_signature
(function_signature)) @definition.method
(method_signature
(getter_signature
name: (identifier) @name)) @definition.method
(method_signature
(setter_signature
name: (identifier) @name)) @definition.method
(method_signature
(function_signature
name: (identifier) @name)) @definition.method
(method_signature
(factory_constructor_signature
(identifier) @name)) @definition.method
(method_signature
(constructor_signature
name: (identifier) @name)) @definition.method
(method_signature
(operator_signature)) @definition.method
(method_signature) @definition.method
; Type aliases
(type_alias
(type_identifier) @name) @definition.type
; Mixin declarations
(mixin_declaration
(mixin)
(identifier) @name) @definition.mixin
; Extension declarations
(extension_declaration
name: (identifier) @name) @definition.extension
; Enum declarations
(enum_declaration
name: (identifier) @name) @definition.enum
; Function signatures
(function_signature
name: (identifier) @name) @definition.function
; References
(new_expression
(type_identifier) @name) @reference.class
; Variables initialized with identifier reference
(initialized_variable_definition
name: (identifier)
value: (identifier) @name) @reference.class
; Variables initialized with selector/method call
(initialized_variable_definition
name: (identifier)
value: (selector
"!"?
(argument_part
(arguments
(argument)*))?)?) @reference.class
(assignment_expression
left: (assignable_expression
(identifier)
(unconditional_assignable_selector
"."
(identifier) @name))) @reference.call
(assignment_expression
left: (assignable_expression
(identifier)
(conditional_assignable_selector
"?."
(identifier) @name))) @reference.call
((identifier) @name
(selector
"!"?
(conditional_assignable_selector
"?." (identifier) @name)?
(unconditional_assignable_selector
"."? (identifier) @name)?
(argument_part
(arguments
(argument)*))?)*
(cascade_section
(cascade_selector
(identifier)) @name
(argument_part
(arguments
(argument)*))?)?) @reference.call
`

View file

@ -1,4 +1,5 @@
export { solidityQuery } from "./solidity"
export { default as dartQuery } from "./dart"
export { default as phpQuery } from "./php"
export { vueQuery } from "./vue"
export { default as typescriptQuery } from "./typescript"