Skip to content

Commit 024d365

Browse files
committed
fix(parser): prevent trait use statements from being parsed as namespace imports
Fixes issue #133: when a class uses traits without any namespace use imports, the parser would treat 'use Trait;' inside the class body as namespace imports, causing new imports to be inserted in the wrong location. - Add classDeclaration null check before matching use statements - Add regression tests for trait use with and without namespace imports
1 parent 36af9db commit 024d365

2 files changed

Lines changed: 19 additions & 1 deletion

File tree

src/core/DeclarationParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class DeclarationParser {
3939
declarationLines.declare = line + 1;
4040
} else if (/^\s*(namespace\s|<\?php\s+namespace\s)/.test(text)) {
4141
declarationLines.namespace = line + 1;
42-
} else if (/^\s*use\s+/.test(text) && !/^\s*use\s*\(/.test(text)) {
42+
} else if (declarationLines.classDeclaration === null && /^\s*use\s+/.test(text) && !/^\s*use\s*\(/.test(text)) {
4343
// Match 'use Foo\Bar;', 'use function ...', 'use const ...' but not 'use ($var)' (closure use)
4444
const kindMatch = text.match(/^\s*use\s+(function|const)\s/);
4545
const kind: 'class' | 'function' | 'const' = kindMatch ? kindMatch[1] as 'function' | 'const' : 'class';

src/test/suite/declarationParser.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,24 @@ suite('DeclarationParser (VS Code Integration)', () => {
370370
assert.deepStrictEqual(names, ['User']);
371371
});
372372

373+
test('should not parse trait use statements as namespace imports (#133)', async () => {
374+
const doc = await createDocument(
375+
'<?php\n\nnamespace App\\Models;\n\nclass Project extends Model {\n use \\App\\Traits\\Validation;\n}'
376+
);
377+
const { useStatements, declarationLines } = parser.parse(doc);
378+
assert.strictEqual(useStatements.length, 0);
379+
assert.strictEqual(declarationLines.lastUseStatement, null);
380+
});
381+
382+
test('should not parse trait use when namespace imports exist (#133)', async () => {
383+
const doc = await createDocument(
384+
'<?php\n\nnamespace App\\Models;\n\nuse Illuminate\\Support\\Carbon;\n\nclass Project extends Model {\n use \\App\\Traits\\Validation;\n}'
385+
);
386+
const { useStatements } = parser.parse(doc);
387+
assert.strictEqual(useStatements.length, 1);
388+
assert.strictEqual(useStatements[0].className, 'Carbon');
389+
});
390+
373391
test('should throw when class in grouped import is already imported', async () => {
374392
const doc = await createDocument(
375393
'<?php\n\nuse App\\Models\\{User, Post};\n\nclass Foo {}'

0 commit comments

Comments
 (0)