mirror of
https://github.com/yamadashy/repomix.git
synced 2026-05-30 11:18:53 +02:00
d10814163d
Three constructor variants were silently dropped during --compress: - `const Foo(...);` and `const Foo.named(...) : ...;` parse as `(declaration (constant_constructor_signature ...))` — a node type the existing constructor query did not list. - `const factory Foo() = Bar;` parses as `(redirecting_factory_constructor_signature (const_builtin) (identifier) ...)` whose first named child is `const_builtin`, so the leading-anchor `. (identifier)` pattern failed to match. - `external factory Foo.make();` parses as `(declaration (factory_constructor_signature ...))` — bare under `declaration`, not wrapped in `method_signature`, so the existing factory query missed it. Switch the constructor / factory / redirecting-factory queries to capture the whole signature node as `@name.definition.method`. This emits the same source line(s) DefaultParseStrategy already produces and is robust across all body / external / const / redirecting variants.
288 lines
7.8 KiB
TypeScript
288 lines
7.8 KiB
TypeScript
import { describe, expect, test } from 'vitest';
|
|
import { parseFile } from '../../../src/core/treeSitter/parseFile.js';
|
|
import { createMockConfig } from '../../../tests/testing/testUtils.js';
|
|
|
|
describe('parseFile for Dart', () => {
|
|
test('should parse Dart correctly', async () => {
|
|
const fileContent = `
|
|
/// A simple greeting class
|
|
class Greeter {
|
|
/// The name to greet
|
|
final String name;
|
|
|
|
/// Constructor
|
|
Greeter(this.name);
|
|
|
|
/// Prints a greeting message
|
|
void greet() {
|
|
print('Hello, $name!');
|
|
}
|
|
|
|
/// Returns a greeting message
|
|
String getMessage() {
|
|
return 'Hello, $name!';
|
|
}
|
|
}
|
|
|
|
/// Main entry point
|
|
void main() {
|
|
final greeter = Greeter('World');
|
|
greeter.greet();
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
'/// A simple greeting class',
|
|
'class Greeter {',
|
|
'/// The name to greet',
|
|
'/// Constructor',
|
|
'/// Prints a greeting message',
|
|
'void greet() {',
|
|
'/// Returns a greeting message',
|
|
'String getMessage() {',
|
|
'/// Main entry point',
|
|
'void main() {',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
|
|
test('should parse Dart with imports correctly', async () => {
|
|
const fileContent = `
|
|
import 'dart:async';
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// A simple widget
|
|
class MyWidget extends StatelessWidget {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Container();
|
|
}
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
"import 'dart:async';",
|
|
"import 'package:flutter/material.dart';",
|
|
'/// A simple widget',
|
|
'class MyWidget extends StatelessWidget {',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
|
|
test('should parse Dart with enum, extension, and constructor', async () => {
|
|
const fileContent = `
|
|
/// Status enum
|
|
enum Status {
|
|
pending,
|
|
active,
|
|
completed
|
|
}
|
|
|
|
/// String extension
|
|
extension StringExtension on String {
|
|
/// Capitalizes first letter
|
|
String capitalize() {
|
|
return this[0].toUpperCase() + substring(1);
|
|
}
|
|
}
|
|
|
|
/// User class
|
|
class User {
|
|
final String name;
|
|
final Status status;
|
|
|
|
/// User constructor
|
|
User(this.name, this.status);
|
|
|
|
/// Named constructor
|
|
User.guest() : name = 'Guest', status = Status.pending;
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
'/// Status enum',
|
|
'enum Status {',
|
|
'/// String extension',
|
|
'extension StringExtension on String {',
|
|
'/// Capitalizes first letter',
|
|
'String capitalize() {',
|
|
'/// User class',
|
|
'class User {',
|
|
'/// User constructor',
|
|
'/// Named constructor',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
|
|
test('should parse Dart mixin, typedef, getter, setter, and factory', async () => {
|
|
const fileContent = `
|
|
/// JSON map alias
|
|
typedef Json = Map<String, dynamic>;
|
|
|
|
/// Walker mixin
|
|
mixin Walker on Animal {
|
|
/// Walk action
|
|
void walk() {
|
|
print('walking');
|
|
}
|
|
}
|
|
|
|
/// Animal base class
|
|
class Animal {
|
|
final String _name;
|
|
|
|
Animal(this._name);
|
|
|
|
/// Animal name getter
|
|
String get name => _name;
|
|
|
|
/// Animal name setter
|
|
set nickname(String value) {
|
|
print('nickname is $value');
|
|
}
|
|
|
|
/// Factory constructor
|
|
factory Animal.guest() {
|
|
return Animal('Guest');
|
|
}
|
|
|
|
/// Redirecting factory
|
|
factory Animal.copy(Animal other) = Animal;
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
'/// JSON map alias',
|
|
'typedef Json = Map<String, dynamic>;',
|
|
'/// Walker mixin',
|
|
'mixin Walker on Animal {',
|
|
'/// Walk action',
|
|
'void walk() {',
|
|
'/// Animal name getter',
|
|
'String get name => _name;',
|
|
'/// Animal name setter',
|
|
'set nickname(String value) {',
|
|
'/// Factory constructor',
|
|
'factory Animal.guest() {',
|
|
'/// Redirecting factory',
|
|
'factory Animal.copy(Animal other) = Animal;',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
|
|
test('should parse Dart plain constructor and operator overloads', async () => {
|
|
const fileContent = `
|
|
/// Vector class with operators
|
|
class Vector {
|
|
final double x;
|
|
final double y;
|
|
|
|
/// Plain constructor
|
|
Vector(this.x, this.y);
|
|
|
|
/// Plus operator
|
|
Vector operator +(Vector other) => Vector(x + other.x, y + other.y);
|
|
|
|
/// Index operator
|
|
double operator [](int i) => i == 0 ? x : y;
|
|
|
|
/// Index assignment operator
|
|
void operator []=(int i, double v) {}
|
|
|
|
/// Equality operator
|
|
bool operator ==(Object other) => other is Vector && x == other.x && y == other.y;
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
'/// Plain constructor',
|
|
'Vector(this.x, this.y);',
|
|
'/// Plus operator',
|
|
'Vector operator +(Vector other) => Vector(x + other.x, y + other.y);',
|
|
'/// Index operator',
|
|
'double operator [](int i) => i == 0 ? x : y;',
|
|
'/// Index assignment operator',
|
|
'void operator []=(int i, double v) {}',
|
|
'/// Equality operator',
|
|
'bool operator ==(Object other) => other is Vector && x == other.x && y == other.y;',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
|
|
test('should parse Dart const and external constructors', async () => {
|
|
const fileContent = `
|
|
/// Point with const constructors
|
|
class Point {
|
|
final int x;
|
|
final int y;
|
|
|
|
/// Const plain constructor
|
|
const Point(this.x, this.y);
|
|
|
|
/// Const named constructor
|
|
const Point.zero() : x = 0, y = 0;
|
|
|
|
/// Const redirecting factory
|
|
const factory Point.alias() = Point.zero;
|
|
|
|
/// External factory
|
|
external factory Point.native();
|
|
}
|
|
`;
|
|
const filePath = 'dummy.dart';
|
|
const config = {};
|
|
const result = await parseFile(fileContent, filePath, createMockConfig(config));
|
|
expect(typeof result).toBe('string');
|
|
|
|
const expectContents = [
|
|
'/// Const plain constructor',
|
|
'const Point(this.x, this.y);',
|
|
'/// Const named constructor',
|
|
'const Point.zero() : x = 0, y = 0;',
|
|
'/// Const redirecting factory',
|
|
'const factory Point.alias() = Point.zero;',
|
|
'/// External factory',
|
|
'external factory Point.native();',
|
|
];
|
|
|
|
for (const expectContent of expectContents) {
|
|
expect(result).toContain(expectContent);
|
|
}
|
|
});
|
|
});
|