Skip to content

Commit 28cd6b3

Browse files
committed
Incluse resolver completed
1 parent f3ae962 commit 28cd6b3

File tree

8 files changed

+78
-41
lines changed

8 files changed

+78
-41
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, test } from "@std/testing/bdd";
2+
import { expect } from "@std/expect";
3+
import { getPHPFilesMap } from "../testFiles/index.ts";
4+
import { PHPRegistree } from "../registree/index.ts";
5+
import { PHPIncluseResolver } from "./index.ts";
6+
import { INCLUDE, USE } from "../testFiles/constants.ts";
7+
8+
describe("PHP Incluse resolver", () => {
9+
const files = getPHPFilesMap();
10+
const registree = new PHPRegistree(files);
11+
const resolver = new PHPIncluseResolver(registree);
12+
13+
test("resolves use directives", () => {
14+
const imports = resolver.resolveImports(registree.registry.files.get(USE)!);
15+
expect(imports.unresolved.namespaces.length).toBe(1);
16+
expect(imports.unresolved.namespaces).toContainEqual("I\\Do\\Not\\Exist");
17+
expect(imports.resolved.get("f")).toBeDefined(); // nested.php
18+
expect(imports.resolved.get("my_function")).toBeDefined(); // learnphp function
19+
expect(imports.resolved.get("MyClass")).toBeDefined(); // learnphp class
20+
expect(imports.resolved.get("wheels")).toBeDefined(); // leanrphp variable
21+
});
22+
23+
test("resolves include directives", () => {
24+
const imports = resolver.resolveImports(
25+
registree.registry.files.get(INCLUDE)!,
26+
);
27+
expect(imports.unresolved.paths.length).toBe(1);
28+
expect(imports.unresolved.paths).toContainEqual("unresolved.php");
29+
expect(imports.resolved.get("f")).toBeDefined(); // nested.php
30+
expect(imports.resolved.get("defined_in_used_file")).toBeDefined(); // use.php
31+
expect(imports.resolved.get("my_function")).toBeDefined(); // learnphp function
32+
expect(imports.resolved.get("MyClass")).toBeDefined(); // learnphp class
33+
expect(imports.resolved.get("wheels")).toBeDefined(); // leanrphp variable
34+
});
35+
});

src/languagePlugins/php/incluseResolver/index.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
import type { PHPRegistree } from "../registree/index.ts";
22
import { type PHPFile, type PHPNode, SymbolNode } from "../registree/types.ts";
33
import type { PHPImports } from "./types.ts";
4-
import {
5-
PHP_INCLUDE_QUERY,
6-
PHP_USE_DETECTION_QUERY,
7-
PHP_USE_QUERY,
8-
} from "./queries.ts";
4+
import { PHP_INCLUDE_QUERY, PHP_USE_DETECTION_QUERY } from "./queries.ts";
95
import type Parser from "tree-sitter";
10-
import { dirname } from "@std/path";
6+
import { dirname, join } from "@std/path";
117

128
export class PHPIncluseResolver {
139
registree: PHPRegistree;
@@ -57,19 +53,17 @@ export class PHPIncluseResolver {
5753
},
5854
};
5955
for (const use of useDirectives) {
60-
const useClause = PHP_USE_QUERY.captures(use.node);
61-
if (!useClause) continue;
6256
let name: string | undefined = undefined;
6357
let node: PHPNode | undefined = undefined;
64-
for (const clause of useClause) {
65-
if (clause.name === "alias") {
66-
name = clause.node.text;
58+
for (const clause of use.node.namedChildren) {
59+
if (clause.type === "namespace_aliasing_clause") {
60+
name = clause.text;
6761
} else {
68-
node = this.registree.tree.findNode(clause.node.text);
62+
node = this.registree.tree.findNode(clause.text);
6963
if (node && !name) {
7064
name = node.name;
7165
} else if (!node && !name) {
72-
name = clause.node.text;
66+
name = clause.text;
7367
}
7468
}
7569
}
@@ -136,11 +130,11 @@ export class PHPIncluseResolver {
136130
imports.unresolved.paths.push(path);
137131
}
138132
} else if (include.name === "includebin") {
139-
const filepath = this.#splitBinary(include.node)
133+
const fileparts = this.#splitBinary(include.node)
140134
.map((n) => n.text === "__DIR__" ? dirname(file.path) : n.text)
141135
.filter((n) => n !== "")
142-
.map((n) => n.replace(/['"]/g, ""))
143-
.join("/");
136+
.map((n) => n.replace(/['"]/g, ""));
137+
const filepath = join(fileparts[0], ...fileparts.slice(1));
144138
const importedfile = this.registree.registry.getFile(
145139
filepath,
146140
file.path,

src/languagePlugins/php/incluseResolver/queries.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,11 @@ import Parser from "tree-sitter";
22
import { phpParser } from "../../../helpers/treeSitter/parsers.ts";
33

44
export const PHP_USE_DETECTION_QUERY = new Parser.Query(
5-
phpParser.getLanguage(),
6-
`
7-
(namespace_use_declaration)
8-
`,
9-
);
10-
11-
export const PHP_USE_QUERY = new Parser.Query(
125
phpParser.getLanguage(),
136
`
147
(namespace_use_declaration
15-
(namespace_use_clause
16-
. (_) @ns (namespace_aliasing_clause (_) @alias)?
17-
))
8+
(namespace_use_clause) @use
9+
)
1810
`,
1911
);
2012

src/languagePlugins/php/registree/types.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,26 @@ export class PHPTree extends NamespaceNode {
4444
}
4545

4646
findNode(name: string): PHPNode | undefined {
47-
const parts = name.split("\\");
48-
let current: Map<string, PHPNode> = this.children;
49-
for (const part of parts) {
47+
if (name === "") {
48+
return this;
49+
} else {
50+
const packageparts = name.split("\\").reverse();
51+
let part = packageparts.pop()!;
5052
if (part === "") {
51-
continue;
53+
part = packageparts.pop()!;
5254
}
53-
if (!current.has(part)) {
55+
let current = this.children.get(part);
56+
if (!current) {
5457
return undefined;
5558
}
56-
current = current.get(part)!.children;
59+
while (packageparts.length > 0) {
60+
if (!current) {
61+
return undefined;
62+
}
63+
current = current.children.get(packageparts.pop()!);
64+
}
65+
return current;
5766
}
58-
return current.get(parts[parts.length - 1]);
5967
}
6068

6169
addNamespaces(namespaces: ExportedNamespace[]) {

src/languagePlugins/php/testFiles/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ import { join } from "@std/path";
33

44
export const LEARN_PHP = join(phpFilesFolder, "learnphp.php");
55
export const NESTED = join(phpFilesFolder, "nested.php");
6+
export const INCLUDE = join(phpFilesFolder, "include.php");
7+
export const USE = join(phpFilesFolder, "use.php");

src/languagePlugins/php/testFiles/phpFiles/imports.php

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
include 'learnphp.php';
4+
include __DIR__ . '/nested.php';
5+
include __DIR__ . '/../phpFiles/use.php';
6+
include 'unresolved.php';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace All\My;
3+
4+
$defined_in_used_file = 0;
5+
6+
use All\My\Fellas;
7+
use My\Namespace;
8+
use I\Do\Not\Exist;

0 commit comments

Comments
 (0)