diff --git a/examples/java/websocket/src/main/resources/static/echo.html b/examples/java/websocket/src/main/resources/static/echo.html index 42081d4e..3a37f451 100644 --- a/examples/java/websocket/src/main/resources/static/echo.html +++ b/examples/java/websocket/src/main/resources/static/echo.html @@ -16,118 +16,133 @@ --> - + Apache Tomcat WebSocket Examples: Echo - - - -
-
+ + + +
+
- +
- - + +
- +
- +
-
-
+
+
+
-
- - \ No newline at end of file + + diff --git a/examples/java/websocket/src/main/resources/static/index.html b/examples/java/websocket/src/main/resources/static/index.html index 39069b15..1eca09cf 100644 --- a/examples/java/websocket/src/main/resources/static/index.html +++ b/examples/java/websocket/src/main/resources/static/index.html @@ -16,16 +16,18 @@ --> - + Apache Tomcat WebSocket Examples: Index - - - -

Please select the sample you would like to try.

- - - \ No newline at end of file + + + +

Please select the sample you would like to try.

+ + + diff --git a/examples/java/websocket/src/main/resources/static/snake.html b/examples/java/websocket/src/main/resources/static/snake.html index be3b6b38..b82dc03c 100644 --- a/examples/java/websocket/src/main/resources/static/snake.html +++ b/examples/java/websocket/src/main/resources/static/snake.html @@ -17,233 +17,249 @@ - - + + Apache Tomcat WebSocket Examples: Multiplayer Snake - - - - + + + +
- +
-
+
- + diff --git a/src/languagePlugins/php/exportResolver/index.test.ts b/src/languagePlugins/php/exportResolver/index.test.ts index f559d7dc..3c02fa43 100644 --- a/src/languagePlugins/php/exportResolver/index.test.ts +++ b/src/languagePlugins/php/exportResolver/index.test.ts @@ -15,7 +15,7 @@ describe("PHP Export resolver", () => { const mynamespace = namespaces.get("My\\Namespace")!; expect(mynamespace.name).toBe("My\\Namespace"); const symbols = mynamespace.symbols; - expect(symbols.length).toBe(66); + expect((new Set(symbols.map((s) => s.name))).size).toBe(66); }); test("resolves nested.php", () => { diff --git a/src/languagePlugins/php/exportResolver/index.ts b/src/languagePlugins/php/exportResolver/index.ts index 387d2ba5..7b537cc7 100644 --- a/src/languagePlugins/php/exportResolver/index.ts +++ b/src/languagePlugins/php/exportResolver/index.ts @@ -1,9 +1,5 @@ import type Parser from "tree-sitter"; -import { - type ExportedNamespace, - type ExportedSymbol, - PHP_VARIABLE, -} from "./types.ts"; +import type { ExportedNamespace, ExportedSymbol } from "./types.ts"; import { INTERESTING_NODES, PHP_IDNODE_QUERY } from "./queries.ts"; export class PHPExportResolver { @@ -41,12 +37,6 @@ export class PHPExportResolver { continue; // Root out false positives for variables and constants } const symType = INTERESTING_NODES.get(child.type)!; - if ( - symType === PHP_VARIABLE && - exports.find((e) => e.name === idNode.node.text) - ) { - continue; // No duplicate variables - } exports.push({ name: idNode.node.text, type: symType, diff --git a/src/languagePlugins/php/registree/index.test.ts b/src/languagePlugins/php/registree/index.test.ts new file mode 100644 index 00000000..958ea8f7 --- /dev/null +++ b/src/languagePlugins/php/registree/index.test.ts @@ -0,0 +1,44 @@ +import { describe, test } from "@std/testing/bdd"; +import { expect } from "@std/expect"; +import { getPHPFilesMap } from "../testFiles/index.ts"; +import { PHPRegistree } from "./index.ts"; +import { SymbolNode } from "./types.ts"; +import { LEARN_PHP, NESTED } from "../testFiles/constants.ts"; + +describe("PHP Registree", () => { + const files = getPHPFilesMap(); + const registree = new PHPRegistree(files); + + test("builds a correct tree", () => { + const tree = registree.tree; + expect(tree.name).toBe(""); + expect(tree.children.get("All")).toBeDefined(); + const all = tree.children.get("All")!; + expect(all.name).toBe("All"); + expect(all.children.size).toBe(2); + expect(all.children.get("a")).toBeDefined(); + expect(all.children.get("a")! instanceof SymbolNode).toBe(true); + expect((all.children.get("a")! as SymbolNode).symbols.length).toBe(1); + expect(all.children.get("My")).toBeDefined(); + expect(all.children.get("My")!.children.get("Fellas")).toBeDefined(); + expect(tree.children.get("My")).toBeDefined(); + const my = tree.children.get("My")!; + expect(my.name).toBe("My"); + expect(my.children.get("Namespace")).toBeDefined(); + const mynamespace = my.children.get("Namespace")!; + expect(mynamespace.children.size).toBe(66); + }); + + test("builds a correct registry", () => { + const registry = registree.registry; + expect(registry.files.get(NESTED)).toBeDefined(); + expect(registry.files.get(LEARN_PHP)).toBeDefined(); + const nested = registry.files.get(NESTED)!; + expect(nested.symbols.size).toBe(3); + expect(Array.from(nested.symbols.keys())).toStrictEqual([ + "a", + "m", + "f", + ]); + }); +}); diff --git a/src/languagePlugins/php/registree/index.ts b/src/languagePlugins/php/registree/index.ts new file mode 100644 index 00000000..0c90c239 --- /dev/null +++ b/src/languagePlugins/php/registree/index.ts @@ -0,0 +1,14 @@ +import type Parser from "tree-sitter"; +import { PHPRegistry, PHPTree } from "./types.ts"; + +export class PHPRegistree { + registry: PHPRegistry; + tree: PHPTree; + + constructor( + files: Map, + ) { + this.registry = new PHPRegistry(files); + this.tree = new PHPTree(files); + } +} diff --git a/src/languagePlugins/php/registree/types.ts b/src/languagePlugins/php/registree/types.ts new file mode 100644 index 00000000..851e9e0e --- /dev/null +++ b/src/languagePlugins/php/registree/types.ts @@ -0,0 +1,109 @@ +import type Parser from "tree-sitter"; +import type { + ExportedNamespace, + ExportedSymbol, +} from "../exportResolver/types.ts"; +import { PHPExportResolver } from "../exportResolver/index.ts"; + +export interface PHPNode { + name: string; + children: Map; +} + +export class NamespaceNode implements PHPNode { + name: string; + children: Map; + + constructor(name: string) { + this.name = name; + this.children = new Map(); + } +} + +export class SymbolNode implements PHPNode { + name: string; + children: Map; + symbols: ExportedSymbol[]; + constructor(symbol: ExportedSymbol) { + this.name = symbol.name; + this.children = new Map(); + this.symbols = [symbol]; + } +} + +export class PHPTree extends NamespaceNode { + constructor( + files: Map, + ) { + super(""); + const resolver = new PHPExportResolver(); + for (const [, file] of files) { + this.addNamespaces(Array.from(resolver.resolveFile(file).values())); + } + } + + addNamespaces(namespaces: ExportedNamespace[]) { + for (const ns of namespaces) { + const nsparts = ns.name.split("\\"); + let current = this.children; + for (const p of nsparts) { + if (!current.has(p)) { + current.set(p, new NamespaceNode(p)); + } + current = current.get(p)!.children; + } + for (const s of ns.symbols) { + if (!current.has(s.name)) { + current.set(s.name, new SymbolNode(s)); + } else { + const snode = current.get(s.name)!; + if (!(snode instanceof SymbolNode)) { + throw Error( + `${s.name} is used both for a namespace and a symbol in ${ns.name}`, + ); + } else { + snode.symbols.push(s); + } + } + } + } + } +} + +export interface PHPFile { + path: string; + rootNode: Parser.SyntaxNode; + symbols: Map; +} + +export class PHPRegistry { + files: Map; + resolver: PHPExportResolver; + constructor( + files: Map, + ) { + this.resolver = new PHPExportResolver(); + this.files = new Map(); + for (const [, file] of files) { + this.addFile(file); + } + } + + addFile(file: { path: string; rootNode: Parser.SyntaxNode }) { + const exported = this.resolver.resolveFile(file); + const symbols: Map = new Map(); + for (const [, ns] of exported) { + for (const s of ns.symbols) { + if (!symbols.has(s.name)) { + symbols.set(s.name, []); + } + symbols.get(s.name)!.push(s); + } + } + this.files.set(file.path, { + path: file.path, + rootNode: file.rootNode, + symbols, + }); + } +}