@untangle-code/parser-registry 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/NOTICE +90 -0
- package/README.md +352 -2
- package/THIRD_PARTY_LICENSES.md +91 -0
- package/dist/boundaries/expression.d.ts +10 -0
- package/dist/boundaries/expression.d.ts.map +1 -0
- package/dist/boundaries/expression.js +95 -0
- package/dist/boundaries/expression.js.map +1 -0
- package/dist/boundaries/extract.d.ts +12 -0
- package/dist/boundaries/extract.d.ts.map +1 -0
- package/dist/boundaries/extract.js +259 -0
- package/dist/boundaries/extract.js.map +1 -0
- package/dist/boundaries/python.d.ts +6 -0
- package/dist/boundaries/python.d.ts.map +1 -0
- package/dist/boundaries/python.js +154 -0
- package/dist/boundaries/python.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/astgrep-backend/adapter.d.ts +101 -0
- package/dist/languages/astgrep-backend/adapter.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/adapter.js +130 -0
- package/dist/languages/astgrep-backend/adapter.js.map +1 -0
- package/dist/languages/astgrep-backend/index.d.ts +29 -0
- package/dist/languages/astgrep-backend/index.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/index.js +28 -0
- package/dist/languages/astgrep-backend/index.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/bash.d.ts +38 -0
- package/dist/languages/astgrep-backend/lang/bash.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/bash.js +42 -0
- package/dist/languages/astgrep-backend/lang/bash.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/c.d.ts +33 -0
- package/dist/languages/astgrep-backend/lang/c.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/c.js +85 -0
- package/dist/languages/astgrep-backend/lang/c.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/cpp.d.ts +27 -0
- package/dist/languages/astgrep-backend/lang/cpp.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/cpp.js +38 -0
- package/dist/languages/astgrep-backend/lang/cpp.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/csharp.d.ts +24 -0
- package/dist/languages/astgrep-backend/lang/csharp.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/csharp.js +102 -0
- package/dist/languages/astgrep-backend/lang/csharp.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/index.d.ts +29 -0
- package/dist/languages/astgrep-backend/lang/index.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/index.js +22 -0
- package/dist/languages/astgrep-backend/lang/index.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/java.d.ts +26 -0
- package/dist/languages/astgrep-backend/lang/java.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/java.js +89 -0
- package/dist/languages/astgrep-backend/lang/java.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/kotlin.d.ts +44 -0
- package/dist/languages/astgrep-backend/lang/kotlin.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/kotlin.js +94 -0
- package/dist/languages/astgrep-backend/lang/kotlin.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/php.d.ts +23 -0
- package/dist/languages/astgrep-backend/lang/php.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/php.js +80 -0
- package/dist/languages/astgrep-backend/lang/php.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/ruby.d.ts +37 -0
- package/dist/languages/astgrep-backend/lang/ruby.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/ruby.js +70 -0
- package/dist/languages/astgrep-backend/lang/ruby.js.map +1 -0
- package/dist/languages/astgrep-backend/lang/swift.d.ts +34 -0
- package/dist/languages/astgrep-backend/lang/swift.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/lang/swift.js +86 -0
- package/dist/languages/astgrep-backend/lang/swift.js.map +1 -0
- package/dist/languages/astgrep-backend/languages.d.ts +55 -0
- package/dist/languages/astgrep-backend/languages.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/languages.js +214 -0
- package/dist/languages/astgrep-backend/languages.js.map +1 -0
- package/dist/languages/astgrep-backend/napi.d.ts +71 -0
- package/dist/languages/astgrep-backend/napi.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/napi.js +176 -0
- package/dist/languages/astgrep-backend/napi.js.map +1 -0
- package/dist/languages/astgrep-backend/syntax.d.ts +88 -0
- package/dist/languages/astgrep-backend/syntax.d.ts.map +1 -0
- package/dist/languages/astgrep-backend/syntax.js +180 -0
- package/dist/languages/astgrep-backend/syntax.js.map +1 -0
- package/dist/languages/index.d.ts +14 -0
- package/dist/languages/index.d.ts.map +1 -0
- package/dist/languages/index.js +37 -0
- package/dist/languages/index.js.map +1 -0
- package/dist/languages/javascript/index.d.ts +4 -0
- package/dist/languages/javascript/index.d.ts.map +1 -0
- package/dist/languages/javascript/index.js +7 -0
- package/dist/languages/javascript/index.js.map +1 -0
- package/dist/languages/jsx/index.d.ts +4 -0
- package/dist/languages/jsx/index.d.ts.map +1 -0
- package/dist/languages/jsx/index.js +7 -0
- package/dist/languages/jsx/index.js.map +1 -0
- package/dist/languages/prose/index.d.ts +53 -0
- package/dist/languages/prose/index.d.ts.map +1 -0
- package/dist/languages/prose/index.js +172 -0
- package/dist/languages/prose/index.js.map +1 -0
- package/dist/languages/prose/line-bytes.d.ts +31 -0
- package/dist/languages/prose/line-bytes.d.ts.map +1 -0
- package/dist/languages/prose/line-bytes.js +39 -0
- package/dist/languages/prose/line-bytes.js.map +1 -0
- package/dist/languages/python/create-adapter.d.ts +20 -0
- package/dist/languages/python/create-adapter.d.ts.map +1 -0
- package/dist/languages/python/create-adapter.js +9 -0
- package/dist/languages/python/create-adapter.js.map +1 -0
- package/dist/languages/python/index.d.ts +4 -0
- package/dist/languages/python/index.d.ts.map +1 -0
- package/dist/languages/python/index.js +6 -0
- package/dist/languages/python/index.js.map +1 -0
- package/dist/languages/python/profile.d.ts +36 -0
- package/dist/languages/python/profile.d.ts.map +1 -0
- package/dist/languages/python/profile.js +282 -0
- package/dist/languages/python/profile.js.map +1 -0
- package/dist/languages/python/signature.d.ts +53 -0
- package/dist/languages/python/signature.d.ts.map +1 -0
- package/dist/languages/python/signature.js +188 -0
- package/dist/languages/python/signature.js.map +1 -0
- package/dist/languages/python/table.d.ts +46 -0
- package/dist/languages/python/table.d.ts.map +1 -0
- package/dist/languages/python/table.js +88 -0
- package/dist/languages/python/table.js.map +1 -0
- package/dist/languages/shared/call-detection.d.ts +17 -0
- package/dist/languages/shared/call-detection.d.ts.map +1 -0
- package/dist/languages/shared/call-detection.js +86 -0
- package/dist/languages/shared/call-detection.js.map +1 -0
- package/dist/languages/shared/chunks.d.ts +28 -0
- package/dist/languages/shared/chunks.d.ts.map +1 -0
- package/dist/languages/shared/chunks.js +181 -0
- package/dist/languages/shared/chunks.js.map +1 -0
- package/dist/languages/shared/create-adapter.d.ts +11 -0
- package/dist/languages/shared/create-adapter.d.ts.map +1 -0
- package/dist/languages/shared/create-adapter.js +90 -0
- package/dist/languages/shared/create-adapter.js.map +1 -0
- package/dist/languages/shared/decisions.d.ts +45 -0
- package/dist/languages/shared/decisions.d.ts.map +1 -0
- package/dist/languages/shared/decisions.js +141 -0
- package/dist/languages/shared/decisions.js.map +1 -0
- package/dist/languages/shared/dialect.d.ts +18 -0
- package/dist/languages/shared/dialect.d.ts.map +1 -0
- package/dist/languages/shared/dialect.js +37 -0
- package/dist/languages/shared/dialect.js.map +1 -0
- package/dist/languages/shared/doc-binding.d.ts +26 -0
- package/dist/languages/shared/doc-binding.d.ts.map +1 -0
- package/dist/languages/shared/doc-binding.js +50 -0
- package/dist/languages/shared/doc-binding.js.map +1 -0
- package/dist/languages/shared/engine.d.ts +49 -0
- package/dist/languages/shared/engine.d.ts.map +1 -0
- package/dist/languages/shared/engine.js +317 -0
- package/dist/languages/shared/engine.js.map +1 -0
- package/dist/languages/shared/extract-symbols.d.ts +5 -0
- package/dist/languages/shared/extract-symbols.d.ts.map +1 -0
- package/dist/languages/shared/extract-symbols.js +31 -0
- package/dist/languages/shared/extract-symbols.js.map +1 -0
- package/dist/languages/shared/fingerprint.d.ts +7 -0
- package/dist/languages/shared/fingerprint.d.ts.map +1 -0
- package/dist/languages/shared/fingerprint.js +95 -0
- package/dist/languages/shared/fingerprint.js.map +1 -0
- package/dist/languages/shared/grammar-loader.d.ts +15 -0
- package/dist/languages/shared/grammar-loader.d.ts.map +1 -0
- package/dist/languages/shared/grammar-loader.js +48 -0
- package/dist/languages/shared/grammar-loader.js.map +1 -0
- package/dist/languages/shared/import-detection.d.ts +24 -0
- package/dist/languages/shared/import-detection.d.ts.map +1 -0
- package/dist/languages/shared/import-detection.js +138 -0
- package/dist/languages/shared/import-detection.js.map +1 -0
- package/dist/languages/shared/js-family-profile.d.ts +5 -0
- package/dist/languages/shared/js-family-profile.d.ts.map +1 -0
- package/dist/languages/shared/js-family-profile.js +179 -0
- package/dist/languages/shared/js-family-profile.js.map +1 -0
- package/dist/languages/shared/node-kinds.d.ts +78 -0
- package/dist/languages/shared/node-kinds.d.ts.map +1 -0
- package/dist/languages/shared/node-kinds.js +141 -0
- package/dist/languages/shared/node-kinds.js.map +1 -0
- package/dist/languages/shared/node-utils.d.ts +31 -0
- package/dist/languages/shared/node-utils.d.ts.map +1 -0
- package/dist/languages/shared/node-utils.js +89 -0
- package/dist/languages/shared/node-utils.js.map +1 -0
- package/dist/languages/shared/parse-diagnostics.d.ts +44 -0
- package/dist/languages/shared/parse-diagnostics.d.ts.map +1 -0
- package/dist/languages/shared/parse-diagnostics.js +64 -0
- package/dist/languages/shared/parse-diagnostics.js.map +1 -0
- package/dist/languages/shared/parse-limits.d.ts +24 -0
- package/dist/languages/shared/parse-limits.d.ts.map +1 -0
- package/dist/languages/shared/parse-limits.js +134 -0
- package/dist/languages/shared/parse-limits.js.map +1 -0
- package/dist/languages/shared/profile.d.ts +149 -0
- package/dist/languages/shared/profile.d.ts.map +1 -0
- package/dist/languages/shared/profile.js +9 -0
- package/dist/languages/shared/profile.js.map +1 -0
- package/dist/languages/shared/scope-model.d.ts +32 -0
- package/dist/languages/shared/scope-model.d.ts.map +1 -0
- package/dist/languages/shared/scope-model.js +2 -0
- package/dist/languages/shared/scope-model.js.map +1 -0
- package/dist/languages/shared/scope-naming.d.ts +20 -0
- package/dist/languages/shared/scope-naming.d.ts.map +1 -0
- package/dist/languages/shared/scope-naming.js +118 -0
- package/dist/languages/shared/scope-naming.js.map +1 -0
- package/dist/languages/shared/scope-signature.d.ts +14 -0
- package/dist/languages/shared/scope-signature.d.ts.map +1 -0
- package/dist/languages/shared/scope-signature.js +82 -0
- package/dist/languages/shared/scope-signature.js.map +1 -0
- package/dist/languages/shared/signature.d.ts +55 -0
- package/dist/languages/shared/signature.d.ts.map +1 -0
- package/dist/languages/shared/signature.js +147 -0
- package/dist/languages/shared/signature.js.map +1 -0
- package/dist/languages/shared/syntax.d.ts +115 -0
- package/dist/languages/shared/syntax.d.ts.map +1 -0
- package/dist/languages/shared/syntax.js +2 -0
- package/dist/languages/shared/syntax.js.map +1 -0
- package/dist/languages/shared/table-profile-decisions.d.ts +54 -0
- package/dist/languages/shared/table-profile-decisions.d.ts.map +1 -0
- package/dist/languages/shared/table-profile-decisions.js +245 -0
- package/dist/languages/shared/table-profile-decisions.js.map +1 -0
- package/dist/languages/shared/table-profile-module-facts.d.ts +29 -0
- package/dist/languages/shared/table-profile-module-facts.d.ts.map +1 -0
- package/dist/languages/shared/table-profile-module-facts.js +139 -0
- package/dist/languages/shared/table-profile-module-facts.js.map +1 -0
- package/dist/languages/shared/table-profile-queries.d.ts +27 -0
- package/dist/languages/shared/table-profile-queries.d.ts.map +1 -0
- package/dist/languages/shared/table-profile-queries.js +70 -0
- package/dist/languages/shared/table-profile-queries.js.map +1 -0
- package/dist/languages/shared/table-profile-scopes.d.ts +46 -0
- package/dist/languages/shared/table-profile-scopes.d.ts.map +1 -0
- package/dist/languages/shared/table-profile-scopes.js +180 -0
- package/dist/languages/shared/table-profile-scopes.js.map +1 -0
- package/dist/languages/shared/table-profile.d.ts +302 -0
- package/dist/languages/shared/table-profile.d.ts.map +1 -0
- package/dist/languages/shared/table-profile.js +125 -0
- package/dist/languages/shared/table-profile.js.map +1 -0
- package/dist/languages/shared/tree-sitter-types.d.ts +44 -0
- package/dist/languages/shared/tree-sitter-types.d.ts.map +1 -0
- package/dist/languages/shared/tree-sitter-types.js +2 -0
- package/dist/languages/shared/tree-sitter-types.js.map +1 -0
- package/dist/languages/structured-text/index.d.ts +48 -0
- package/dist/languages/structured-text/index.d.ts.map +1 -0
- package/dist/languages/structured-text/index.js +120 -0
- package/dist/languages/structured-text/index.js.map +1 -0
- package/dist/languages/tsx/index.d.ts +4 -0
- package/dist/languages/tsx/index.d.ts.map +1 -0
- package/dist/languages/tsx/index.js +7 -0
- package/dist/languages/tsx/index.js.map +1 -0
- package/dist/languages/typescript/index.d.ts +4 -0
- package/dist/languages/typescript/index.d.ts.map +1 -0
- package/dist/languages/typescript/index.js +7 -0
- package/dist/languages/typescript/index.js.map +1 -0
- package/dist/languages/vue/index.d.ts +21 -0
- package/dist/languages/vue/index.d.ts.map +1 -0
- package/dist/languages/vue/index.js +234 -0
- package/dist/languages/vue/index.js.map +1 -0
- package/dist/languages/vue/mapping.d.ts +11 -0
- package/dist/languages/vue/mapping.d.ts.map +1 -0
- package/dist/languages/vue/mapping.js +77 -0
- package/dist/languages/vue/mapping.js.map +1 -0
- package/dist/registry.d.ts +24 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +42 -0
- package/dist/registry.js.map +1 -0
- package/dist/text/byte-offset-table.d.ts +27 -0
- package/dist/text/byte-offset-table.d.ts.map +1 -0
- package/dist/text/byte-offset-table.js +39 -0
- package/dist/text/byte-offset-table.js.map +1 -0
- package/package.json +125 -3
- package/src/boundaries/expression.ts +95 -0
- package/src/boundaries/extract.ts +307 -0
- package/src/boundaries/python.ts +181 -0
- package/src/index.ts +51 -0
- package/src/languages/__golden__/javascript-basic.json +32 -0
- package/src/languages/__golden__/tsx-basic.json +19 -0
- package/src/languages/__golden__/typescript-basic.json +37 -0
- package/src/languages/astgrep-backend/GRAMMARS.md +86 -0
- package/src/languages/astgrep-backend/README.md +112 -0
- package/src/languages/astgrep-backend/__golden__/bash-basic.sh +53 -0
- package/src/languages/astgrep-backend/__golden__/c-basic.c +64 -0
- package/src/languages/astgrep-backend/__golden__/cpp-basic.cpp +65 -0
- package/src/languages/astgrep-backend/__golden__/csharp-basic.cs +73 -0
- package/src/languages/astgrep-backend/__golden__/go-basic.go +93 -0
- package/src/languages/astgrep-backend/__golden__/java-basic.java +62 -0
- package/src/languages/astgrep-backend/__golden__/kotlin-basic.kt +58 -0
- package/src/languages/astgrep-backend/__golden__/php-basic.php +72 -0
- package/src/languages/astgrep-backend/__golden__/ruby-basic.rb +62 -0
- package/src/languages/astgrep-backend/__golden__/rust-basic.rs +82 -0
- package/src/languages/astgrep-backend/__golden__/swift-basic.swift +73 -0
- package/src/languages/astgrep-backend/adapter.ts +240 -0
- package/src/languages/astgrep-backend/index.ts +44 -0
- package/src/languages/astgrep-backend/lang/README.md +115 -0
- package/src/languages/astgrep-backend/lang/bash.ts +78 -0
- package/src/languages/astgrep-backend/lang/c.ts +119 -0
- package/src/languages/astgrep-backend/lang/cpp.ts +65 -0
- package/src/languages/astgrep-backend/lang/csharp.ts +125 -0
- package/src/languages/astgrep-backend/lang/index.ts +61 -0
- package/src/languages/astgrep-backend/lang/java.ts +115 -0
- package/src/languages/astgrep-backend/lang/kotlin.ts +136 -0
- package/src/languages/astgrep-backend/lang/php.ts +105 -0
- package/src/languages/astgrep-backend/lang/ruby.ts +105 -0
- package/src/languages/astgrep-backend/lang/swift.ts +118 -0
- package/src/languages/astgrep-backend/languages.ts +238 -0
- package/src/languages/astgrep-backend/napi.ts +261 -0
- package/src/languages/astgrep-backend/syntax.ts +242 -0
- package/src/languages/index.ts +53 -0
- package/src/languages/javascript/index.ts +9 -0
- package/src/languages/jsx/index.ts +9 -0
- package/src/languages/prose/index.ts +270 -0
- package/src/languages/prose/line-bytes.ts +52 -0
- package/src/languages/python/README.md +246 -0
- package/src/languages/python/__golden__/python-basic.json +44 -0
- package/src/languages/python/create-adapter.ts +29 -0
- package/src/languages/python/index.ts +8 -0
- package/src/languages/python/profile.ts +341 -0
- package/src/languages/python/signature.ts +183 -0
- package/src/languages/python/table.ts +135 -0
- package/src/languages/shared/__fixtures__/large-over-32kib.ts.txt +1207 -0
- package/src/languages/shared/call-detection.ts +112 -0
- package/src/languages/shared/chunks.ts +255 -0
- package/src/languages/shared/create-adapter.ts +136 -0
- package/src/languages/shared/decisions.ts +204 -0
- package/src/languages/shared/dialect.ts +55 -0
- package/src/languages/shared/doc-binding.ts +78 -0
- package/src/languages/shared/engine.ts +461 -0
- package/src/languages/shared/extract-symbols.ts +35 -0
- package/src/languages/shared/fingerprint.ts +99 -0
- package/src/languages/shared/grammar-loader.ts +67 -0
- package/src/languages/shared/import-detection.ts +154 -0
- package/src/languages/shared/js-family-profile.ts +246 -0
- package/src/languages/shared/node-kinds.ts +153 -0
- package/src/languages/shared/node-utils.ts +120 -0
- package/src/languages/shared/parse-diagnostics.ts +125 -0
- package/src/languages/shared/parse-limits.ts +147 -0
- package/src/languages/shared/profile.ts +184 -0
- package/src/languages/shared/scope-model.ts +43 -0
- package/src/languages/shared/scope-naming.ts +124 -0
- package/src/languages/shared/scope-signature.ts +108 -0
- package/src/languages/shared/signature.ts +149 -0
- package/src/languages/shared/syntax.ts +116 -0
- package/src/languages/shared/table-profile-decisions.ts +251 -0
- package/src/languages/shared/table-profile-module-facts.ts +177 -0
- package/src/languages/shared/table-profile-queries.ts +85 -0
- package/src/languages/shared/table-profile-scopes.ts +198 -0
- package/src/languages/shared/table-profile.ts +427 -0
- package/src/languages/shared/tree-sitter-types.ts +46 -0
- package/src/languages/structured-text/index.ts +192 -0
- package/src/languages/tsx/index.ts +9 -0
- package/src/languages/typescript/index.ts +9 -0
- package/src/languages/vue/index.ts +312 -0
- package/src/languages/vue/mapping.ts +93 -0
- package/src/registry.ts +61 -0
- package/src/text/byte-offset-table.ts +63 -0
package/NOTICE
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# NOTICE
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Luke Bölling and contributors.
|
|
4
|
+
|
|
5
|
+
This attribution covers original Untangle work. Contributors retain copyright in
|
|
6
|
+
their contributions. Third-party packages, grammars and other materials retain
|
|
7
|
+
their own copyright holders, licenses and notices; this line does not replace them.
|
|
8
|
+
|
|
9
|
+
## License — binding decision
|
|
10
|
+
|
|
11
|
+
Untangle is licensed under the **GNU Affero General Public License, Version 3
|
|
12
|
+
(AGPL-3.0-only)**. See [`LICENSE`](./LICENSE).
|
|
13
|
+
|
|
14
|
+
This decision is **final, not provisional**, and was explicitly instructed by
|
|
15
|
+
the project owner. No contributor, agent or tool may change it without a new
|
|
16
|
+
explicit instruction.
|
|
17
|
+
|
|
18
|
+
The repository-wide license covers Untangle's first-party source code, scripts,
|
|
19
|
+
tests, fixtures, configuration, documentation, website and brand artwork, including
|
|
20
|
+
the logo and 3D yarn illustrations. Every workspace `package.json` declares
|
|
21
|
+
`"license": "AGPL-3.0-only"`. There is no separately licensed enterprise component
|
|
22
|
+
or separate permissive license for documentation or brand assets.
|
|
23
|
+
|
|
24
|
+
Third-party code, embedded grammars, dependency assets and their notices retain
|
|
25
|
+
their original licenses. Their inclusion does not relicense those works. The
|
|
26
|
+
repository license does not grant trademark rights or change the license of a
|
|
27
|
+
repository analyzed with Untangle. See the repository's `docs/LICENSING.md` for
|
|
28
|
+
scope and verification details.
|
|
29
|
+
|
|
30
|
+
This resolves the license question left open in `vision.md` §14 and completes
|
|
31
|
+
`product.md` §16, item 2.
|
|
32
|
+
|
|
33
|
+
## Rationale
|
|
34
|
+
|
|
35
|
+
- **Network copyleft fits the intended product model.** AGPL §13 sets source
|
|
36
|
+
availability requirements for modified versions used through a computer network.
|
|
37
|
+
The current local CLI/stdio-MCP entry and future shared-server modes share the
|
|
38
|
+
same license.
|
|
39
|
+
- **Local-first analysis has a clear boundary.** Running Untangle against a codebase
|
|
40
|
+
does not replace that codebase's own license with Untangle's license.
|
|
41
|
+
- **First-party components share one license.** Implemented components and future
|
|
42
|
+
official plugins use this repository's licensing policy. Planned integrations do
|
|
43
|
+
not establish implemented or published products.
|
|
44
|
+
|
|
45
|
+
## Deliberately accepted consequence
|
|
46
|
+
|
|
47
|
+
The project deliberately chooses AGPL rather than a permissive embedding license.
|
|
48
|
+
Redistribution, modifications and combined works must be assessed against the
|
|
49
|
+
actual terms in `LICENSE`, including applicable Corresponding Source requirements.
|
|
50
|
+
No permissive exception, commercial dual license or special contract-only package
|
|
51
|
+
license is granted or promised by this notice.
|
|
52
|
+
|
|
53
|
+
## Dependencies
|
|
54
|
+
|
|
55
|
+
Third-party runtime dependencies are checked against the allowlist in
|
|
56
|
+
`scripts/check-licenses.mjs`. Their licenses and copyright notices remain unchanged
|
|
57
|
+
and traceable through package `THIRD_PARTY_LICENSES.md` files, grammar provenance,
|
|
58
|
+
the lockfile and release SBOM. The allowlist includes MIT / Apache-2.0 / BSD / ISC
|
|
59
|
+
and other explicitly listed licenses; it is not a license grant for dependencies.
|
|
60
|
+
|
|
61
|
+
The allowlist in `scripts/check-licenses.mjs` applies to **dependencies**, not
|
|
62
|
+
workspace packages. Untangle's own packages carry AGPL-3.0-only and are excluded
|
|
63
|
+
from that check.
|
|
64
|
+
|
|
65
|
+
## Clean room
|
|
66
|
+
|
|
67
|
+
Untangle is an independent implementation with its own data models, APIs, tool
|
|
68
|
+
names, tests and sources. Feature ideas may be derived from publicly observable
|
|
69
|
+
behavior and generally known techniques. Third-party source code is not copied,
|
|
70
|
+
including from AGPL projects even where the license would permit it.
|
|
71
|
+
|
|
72
|
+
## Contribution terms
|
|
73
|
+
|
|
74
|
+
Pull requests are welcome under the repository's existing AGPL-3.0-only license.
|
|
75
|
+
No separate CLA, copyright assignment or DCO sign-off is required. Contributors
|
|
76
|
+
must have the right to submit their work under those terms. See CONTRIBUTING.md.
|
|
77
|
+
|
|
78
|
+
## Release decisions
|
|
79
|
+
|
|
80
|
+
- [x] Copyright attribution: Luke Bölling, with contributors retaining their rights.
|
|
81
|
+
- [x] Contributions use AGPL-3.0-only without an additional CLA or DCO gate.
|
|
82
|
+
|
|
83
|
+
## Open legal items before public beta
|
|
84
|
+
|
|
85
|
+
- [ ] Trademark search for the product name `Untangle`.
|
|
86
|
+
- [ ] Registration and legal review of the npm scope `@untangle-code`.
|
|
87
|
+
- [ ] Verify source availability and notices for each released network daemon/server
|
|
88
|
+
mode (WP-59). The current stdio MCP `untangle_about` already reports the license,
|
|
89
|
+
source repository and build commit when supplied; metadata alone does not prove
|
|
90
|
+
that a concrete deployed version's source is available.
|
package/README.md
CHANGED
|
@@ -1,3 +1,353 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @untangle-code/parser-registry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
WP-06: the `ParserRegistry` implementation (a port from `@untangle-code/domain`), plus
|
|
4
|
+
`LanguageAdapter` implementations for TypeScript, JavaScript, TSX, JSX and Vue SFCs,
|
|
5
|
+
Python, additional native languages, prose and structured text. This package is part
|
|
6
|
+
of Untangle's public package surface.
|
|
7
|
+
|
|
8
|
+
**Two backends (WP-220).** Since WP-220, two parser backends operate behind the same
|
|
9
|
+
`LanguageAdapter` contract: **tree-sitter** for TypeScript/JavaScript/TSX/JSX (measured
|
|
10
|
+
3.74× faster traversal, lower memory use, complete `nodeIsMissing` support) and
|
|
11
|
+
**ast-grep** for Go and Rust — languages that would not be available without existing
|
|
12
|
+
third-party grammars. `src/languages/astgrep-backend/README.md` documents which backend
|
|
13
|
+
serves each language, **why**, and the differences (size limit, heuristic
|
|
14
|
+
`missingNodeCount`, separate `parser_version`). The unified traversal in
|
|
15
|
+
`src/languages/shared/` serves both backends; native tree-sitter shapes satisfy the
|
|
16
|
+
tree contract structurally, so the faster backend pays no abstraction cost.
|
|
17
|
+
|
|
18
|
+
Normative sources: spec.md §7.1–§7.3, §8.2–§8.3, §14.2, §16.2–§16.7, §17.3;
|
|
19
|
+
architecture.md §6.5, §15.1. All types (`LanguageAdapter`, `ParsedAst`, `ExtractedSymbol`,
|
|
20
|
+
`RawImport`, `RawCall`, `ComplexityFacts`, `HalsteadTokens`, `AstRegion`, `ParserRegistry`
|
|
21
|
+
and others) come unchanged from `@untangle-code/domain`; this package defines no
|
|
22
|
+
competing types.
|
|
23
|
+
|
|
24
|
+
<a id="grammatik-wahl"></a>
|
|
25
|
+
|
|
26
|
+
## Grammar selection
|
|
27
|
+
|
|
28
|
+
Tested under Node 22/26, ESM, `verbatimModuleSyntax`:
|
|
29
|
+
|
|
30
|
+
- **web-tree-sitter (WASM)**: `Parser.init()`/`Language.load()` must be `async`.
|
|
31
|
+
The domain's `LanguageAdapter.parse()` is **synchronous**. A WASM load cannot be
|
|
32
|
+
hidden cleanly before the first `parse()` call without loading all languages at
|
|
33
|
+
startup (prohibited by the task) or requiring an async registry factory (outside
|
|
34
|
+
the port contract). Rejected.
|
|
35
|
+
- **typescript (`ts.createSourceFile`) as a fallback**: allowed by the task, but only
|
|
36
|
+
for the TS/JS family. It provides no AST for actual JSX in JS without a TS compiler
|
|
37
|
+
mode, no uniform byte-range API, and a completely different compatibility path
|
|
38
|
+
for later languages such as Python. Unnecessary because the next option works.
|
|
39
|
+
- **`tree-sitter` (native N-API bindings) + `tree-sitter-typescript` + `tree-sitter-javascript`**:
|
|
40
|
+
selected. Empirically verified (see this package's test history): on Node 22/26
|
|
41
|
+
arm64/Darwin, `npm install` supplies working precompiled binaries immediately
|
|
42
|
+
(`node-gyp-build` finds them in the package; no compilation required).
|
|
43
|
+
`parser.parse(text)` is fully **synchronous**. `tree-sitter-javascript` also parses
|
|
44
|
+
JSX natively, which is why `jsx` uses the same grammar loader as `javascript` below.
|
|
45
|
+
Version constraint: `tree-sitter@0.21.1` + `tree-sitter-typescript@0.23.2` +
|
|
46
|
+
`tree-sitter-javascript@0.23.1` (newer `tree-sitter-javascript`/`-typescript` versions
|
|
47
|
+
require `tree-sitter@^0.25`, conflicting with `tree-sitter-typescript`'s `^0.21.0`
|
|
48
|
+
peer dependency; this combination is the only one jointly resolvable at that point).
|
|
49
|
+
|
|
50
|
+
**Language → grammar mapping** (`languages/shared/dialect.ts`):
|
|
51
|
+
|
|
52
|
+
| languageId | Extensions | Grammar module | Export |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| `typescript` | `.ts .mts .cts` | `tree-sitter-typescript` | `.typescript` |
|
|
55
|
+
| `tsx` | `.tsx` | `tree-sitter-typescript` | `.tsx` |
|
|
56
|
+
| `javascript` | `.js .mjs .cjs` | `tree-sitter-javascript` | (default) |
|
|
57
|
+
| `jsx` | `.jsx` | `tree-sitter-javascript` | (default) |
|
|
58
|
+
| `vue` | `.vue` | `@vue/compiler-sfc` for block boundaries; existing JS/TS grammars for inline scripts | See below |
|
|
59
|
+
|
|
60
|
+
`javascript` and `jsx` are two **separate** `LanguageAdapter` instances (their own
|
|
61
|
+
`languageId`/extensions, as required by the task's “four LanguageAdapters”). Internally
|
|
62
|
+
they share a grammar because `tree-sitter-javascript` parses JSX without extra configuration.
|
|
63
|
+
|
|
64
|
+
<a id="vue-ausführbaren-quelltext-messen-sfc-grenzen-sichtbar-halten"></a>
|
|
65
|
+
|
|
66
|
+
### Vue: measure executable source and expose SFC boundaries
|
|
67
|
+
|
|
68
|
+
`createVueAdapter()` registers `.vue` at support level `structural`. The official
|
|
69
|
+
[`@vue/compiler-sfc` parser](https://github.com/vuejs/core/tree/main/packages/compiler-sfc)
|
|
70
|
+
identifies SFC block boundaries and loads only on `parse()`. The adapter passes the
|
|
71
|
+
unchanged contents of `<script>` and `<script setup>` to the existing JS, TS, JSX or
|
|
72
|
+
TSX adapters. It neither generates nor measures compiled render or setup code; existing
|
|
73
|
+
rules for decisions, Halstead and symbol detection stay the same.
|
|
74
|
+
|
|
75
|
+
All ranges are then shifted to the original UTF-8 bytes and lines of the `.vue` file,
|
|
76
|
+
including imports, calls, comments and diagnostics. A single script block retains its
|
|
77
|
+
qualified symbol names. With two blocks, `script.<Name>` and `setup.<Name>` distinguish
|
|
78
|
+
the execution contexts. File facts share one file scope; child script scopes and logical
|
|
79
|
+
decision groups remain distinct. This does not model Vue runtime bindings between blocks.
|
|
80
|
+
|
|
81
|
+
The single chunk root covers the entire original file. Template, style and custom blocks
|
|
82
|
+
therefore remain searchable as text. Their complexity, directives, template calls,
|
|
83
|
+
component use and CSS dependencies are **not** captured as code facts. Each such block
|
|
84
|
+
receives a warning with `kind: "other"`, `code: "analysis_scope_limited"`, the prefix
|
|
85
|
+
`Vue analysis scope:` and its original range. `parseQuality: "complete"` means the SFC
|
|
86
|
+
structure and analyzed inline scripts are syntactically valid; it claims neither complete
|
|
87
|
+
Vue semantics nor successful Vue compilation.
|
|
88
|
+
|
|
89
|
+
Template-only files, external `script src`, unsupported script languages, different
|
|
90
|
+
`lang` attributes on the two scripts and syntax damage produce `partial` with specific
|
|
91
|
+
diagnostics. External scripts must be analyzed as separate source files. Without an
|
|
92
|
+
analyzed inline script, no executable scopes or artificial complexity values are created.
|
|
93
|
+
The SFC input has the same 8 MiB byte limit as the existing tree-sitter adapters. The
|
|
94
|
+
separate parser version `untangle-parser-vue-sfc-v1` distinguishes this analysis from
|
|
95
|
+
earlier text fallbacks.
|
|
96
|
+
|
|
97
|
+
`src/languages/vue/adapter.test.ts` checks real SFCs with all four script dialects,
|
|
98
|
+
Options API, both scripts, Unicode/CRLF offsets, imports/calls, nested symbol regions,
|
|
99
|
+
unchanged TS facts, invalid and external scripts, and visible analysis limits.
|
|
100
|
+
|
|
101
|
+
**Implication for later languages** (documented as the task requires): Python (WP-09)
|
|
102
|
+
can also use native `tree-sitter` bindings (recommended, following the same pattern)
|
|
103
|
+
or another approach. The registry itself is grammar-independent (`register(adapter)`);
|
|
104
|
+
nothing in `registry.ts` or `languages/index.ts` needs to change.
|
|
105
|
+
|
|
106
|
+
## Lazy Loading
|
|
107
|
+
|
|
108
|
+
`createParserRegistry()` registers four `LanguageAdapter` objects without loading **any**
|
|
109
|
+
native module. `languages/shared/grammar-loader.ts` loads `tree-sitter` itself and each
|
|
110
|
+
grammar only on the first `parse()` call for that language, through
|
|
111
|
+
`node:module#createRequire` (synchronous CJS `require` from ESM, needed because `parse()`
|
|
112
|
+
must be synchronous), with a module-level cache. A CLI reading only TypeScript files
|
|
113
|
+
never loads `tree-sitter-javascript`.
|
|
114
|
+
|
|
115
|
+
<a id="eine-einzige-analyse-pro-datei"></a>
|
|
116
|
+
|
|
117
|
+
## One analysis per file
|
|
118
|
+
|
|
119
|
+
Every `LanguageAdapter` method (`extractSymbols`, `extractImports`, `extractCalls`,
|
|
120
|
+
`computeComplexity`, `tokenizeForHalstead`, `extractChunks`) is a thin projection over
|
|
121
|
+
**one** `AnalysisResult`. `languages/shared/engine.ts#analyzeTree` computes it in a single
|
|
122
|
+
AST traversal, and `create-adapter.ts` memoizes it per `ParsedAst` through a `WeakMap`.
|
|
123
|
+
This also guarantees consistency: a `SymbolScopeFact`'s `symbolScopeId`
|
|
124
|
+
(`computeComplexity`) is exactly the same string as a `RawCall`'s `callerScopeId`
|
|
125
|
+
(`extractCalls`) for a call inside that scope. Both come from the same live scope stack
|
|
126
|
+
frame in the same traversal, rather than independently reconstructed scope ID algorithms
|
|
127
|
+
that could diverge.
|
|
128
|
+
|
|
129
|
+
<a id="traversierung-cursor-nicht-children-wp-95"></a>
|
|
130
|
+
|
|
131
|
+
## Traversal: cursors instead of `.children` (WP-95)
|
|
132
|
+
|
|
133
|
+
Traversal navigates through the **cursor API** (`tree.walk()`, `gotoFirstChild`,
|
|
134
|
+
`gotoNextSibling`, `gotoParent`), never `node.children`. There are two reasons, and the
|
|
135
|
+
second matters more than the first.
|
|
136
|
+
|
|
137
|
+
**Speed.** Each `.children` access creates a JS array of node wrappers and crosses the
|
|
138
|
+
native library boundary once per node. Measured against this repository (738 files,
|
|
139
|
+
134,782 lines, `pnpm walk:messung`):
|
|
140
|
+
|
|
141
|
+
| Stage | Through `.children` | Through cursors | Factor |
|
|
142
|
+
|---|---:|---:|---:|
|
|
143
|
+
| `parse` (including parse diagnostics) | 2,803 ms | 853 ms | 3.29× |
|
|
144
|
+
| Traversal (`computeComplexity`) | 16,596 ms | 4,662 ms | 3.56× |
|
|
145
|
+
| **Total** | **19,440 ms** (6.93 kLOC/s) | **5,541 ms** (24.32 kLOC/s) | **3.51×** |
|
|
146
|
+
|
|
147
|
+
**Correctness.** `tree-sitter@0.21.1` reports a node's type reliably only when the cursor
|
|
148
|
+
**descended from the root**. Neither `node.children` nor a cursor reset to a subtree
|
|
149
|
+
(`node.walk()`) knows the parent node's alias context. In this repository both reported
|
|
150
|
+
**1,411 comment nodes in 207 files** as `interface_body`. The previous traversal therefore
|
|
151
|
+
failed to recognize them as comments: they were absent from `ComplexityFacts.comments`,
|
|
152
|
+
counted as Halstead **operators**, and included in `astHash` and `tokenFingerprint`,
|
|
153
|
+
contrary to `fingerprint.ts`'s promise that both fingerprints exclude comments. A comment-only
|
|
154
|
+
edit therefore appeared to change the symbol's structure (`spec.md` §17.3).
|
|
155
|
+
|
|
156
|
+
Measured across this repository: **1,411** comments counted as Halstead operators
|
|
157
|
+
(out of 133,282) and were missing from `comments` (6,821 instead of 8,232);
|
|
158
|
+
**531 of 10,328** symbols (5.1%) now have corrected fingerprints. Cyclomatic and cognitive
|
|
159
|
+
complexity do **not** change: neither calculation includes comments.
|
|
160
|
+
|
|
161
|
+
Three rules follow for this package:
|
|
162
|
+
|
|
163
|
+
1. `engine.ts#analyzeTree` creates **one** cursor at the root and passes it through.
|
|
164
|
+
Every helper that moves it returns it to its original position.
|
|
165
|
+
2. `computeAstHash`/`computeTokenFingerprint` accept **this** cursor, not a node.
|
|
166
|
+
Switching them back to `node.walk()` would reintroduce the defect.
|
|
167
|
+
3. A `SyntaxNode` wrapper is created only where a detector actually needs it
|
|
168
|
+
(`engine.ts#visitInnerNode`, prefilter `decisions.ts#mayCarryDecisionOrNesting`).
|
|
169
|
+
|
|
170
|
+
Verified by `languages/shared/cursor-walk.test.ts` (regression: all four assertions fail
|
|
171
|
+
before WP-95) and `scripts/walk-gegenprobe.mjs`, which runs both approaches over every
|
|
172
|
+
source file and checks that **every** difference has precisely this cause.
|
|
173
|
+
|
|
174
|
+
<a id="byte-offsets--kritische-falle"></a>
|
|
175
|
+
|
|
176
|
+
## Byte offsets — a critical pitfall
|
|
177
|
+
|
|
178
|
+
The domain contract defines `SourceRange.startByte`/`endByte` as **UTF-8 bytes**. Native
|
|
179
|
+
`tree-sitter` Node bindings return `startIndex`/`endIndex` in **UTF-16 code units**
|
|
180
|
+
(empirically verified: a 4-byte astral character increases `endIndex` by 2, not 4).
|
|
181
|
+
`text/byte-offset-table.ts#buildByteOffsetTable` builds one prefix-sum table per file
|
|
182
|
+
(O(n) construction, O(1) lookup). **Every** `SourceRange` construction in this package
|
|
183
|
+
goes through `node-utils.ts#rangeOf`, which uses that table. Never copy
|
|
184
|
+
`node.startIndex`/`endIndex` directly into a `SourceRange`.
|
|
185
|
+
|
|
186
|
+
<a id="signaturnormalisierung-specmd-55"></a>
|
|
187
|
+
|
|
188
|
+
## Signature normalization (spec.md §5.5)
|
|
189
|
+
|
|
190
|
+
See the detailed documentation in the header comment of `languages/shared/signature.ts`.
|
|
191
|
+
The rules are:
|
|
192
|
+
|
|
193
|
+
1. **Whitespace**: arbitrary runs collapse to one space; spacing around `,`/`:`/`(`/`)`/
|
|
194
|
+
`<`/`>`/`?:` is canonicalized instead of copied literally.
|
|
195
|
+
2. **Default values** (`= <expr>`) are removed from parameters AND generic type parameters
|
|
196
|
+
(a depth scanner over `(`/`[`/`{`/`<`, splitting top-level commas first; see
|
|
197
|
+
`splitTopLevel`/`stripDefaultValue`).
|
|
198
|
+
3. **Optional markers** (`?`) are retained and canonicalized immediately before `:`
|
|
199
|
+
(`a ?: string` and `a?:string` → `a?: string`); they change the call contract
|
|
200
|
+
independently of defaults.
|
|
201
|
+
4. **Type annotations** are preserved literally, subject to the whitespace rules.
|
|
202
|
+
|
|
203
|
+
Known documented limit: the depth scanner treats `<`/`>` as generic brackets. A comparison
|
|
204
|
+
operator `<`/`>` **inside a default value** (`(a = b < c ? 1 : 2)`) can confuse depth
|
|
205
|
+
counting for that parameter. This is accepted as a rare case outside the chosen scope.
|
|
206
|
+
|
|
207
|
+
<a id="entscheidungen"></a>
|
|
208
|
+
|
|
209
|
+
## Decisions
|
|
210
|
+
|
|
211
|
+
1. **One AST traversal instead of six independent method implementations.** See “One
|
|
212
|
+
analysis per file” above. `create-adapter.ts` caches per `ParsedAst`.
|
|
213
|
+
2. **`RawImportKind` has no `require` value.** `require("x")` maps to `importKind: "import"`
|
|
214
|
+
(functionally a synchronous import); `"package_dependency"` is reserved for an edge
|
|
215
|
+
**resolved** by the import resolver/file graph, rather than a source syntax form.
|
|
216
|
+
3. **The `namespace` scope kind maps to chunk kind `"module"`.** `ChunkKind` (domain) has
|
|
217
|
+
no `"namespace"` member; a TS `namespace`/`module` block is itself a module-like
|
|
218
|
+
grouping of symbols.
|
|
219
|
+
4. **`exportedNames` recognizes only direct wrapping.** `export function f() {}` and
|
|
220
|
+
`export default class {}` are recognized. A later `export { f }` elsewhere in the file,
|
|
221
|
+
or `export default f;` as a separate statement referencing an already declared name,
|
|
222
|
+
is NOT traced back (see `scope-naming.ts#resolveExportedNames`). This can be added
|
|
223
|
+
when a consumer needs it.
|
|
224
|
+
5. **The `parse()` return value has no `parserVersion` field.** The WP-06 task mentions it,
|
|
225
|
+
but `ParseResult` (domain `analysis.ts`) defines exactly `{parseQuality, ast, diagnostics,
|
|
226
|
+
errorNodeCount, missingNodeCount}`, without `parserVersion`. Because the domain defines
|
|
227
|
+
the contracts exactly and this package may not add competing fields, the field is NOT
|
|
228
|
+
appended (see openIssues: “belongs in domain”).
|
|
229
|
+
6. **`failed` at ≥50% damaged nodes.** tree-sitter's error recovery almost always produces
|
|
230
|
+
a usable tree; a small absolute number of `ERROR`/missing nodes means `partial`,
|
|
231
|
+
while a mostly damaged file means `failed` (`ast: null`). Neither spec.md nor
|
|
232
|
+
architecture.md specifies a normative value; this is the package's documented
|
|
233
|
+
threshold (`parse-diagnostics.ts`).
|
|
234
|
+
7. **Guard clause heuristic**: an `if` without `else` whose only consequence is a
|
|
235
|
+
`return`/`throw`/`break`/`continue` is classified as `DecisionKind: "guard"` instead of
|
|
236
|
+
`"if"` (spec.md §16.2: “guards when they create independent paths”).
|
|
237
|
+
8. **Property fields are separate scopes**, unless their initializer is itself a
|
|
238
|
+
function/class (`class C { handler = () => {} }`). The function then receives the
|
|
239
|
+
scope (borrowing the field's name), avoiding duplicated `C.handler.handler`
|
|
240
|
+
(`scope-naming.ts#fieldDelegatesToFunctionValue`).
|
|
241
|
+
9. **Halstead classification**: brackets/commas/semicolons/periods (`( ) { } [ ] , ; .`)
|
|
242
|
+
do **not** count as operators. All other symbol/keyword terminals count as operators;
|
|
243
|
+
identifiers/`this`/`super` and literals (including template text fragments) count as
|
|
244
|
+
operands. TS type keywords such as `number`/`string`/`void` (kind `predefined_type`)
|
|
245
|
+
do **not** count: they are pure type syntax, not values. Grammar pitfall: the `string`
|
|
246
|
+
type keyword node has the same `node.type` as a string literal container; see the
|
|
247
|
+
comment in `engine.ts`.
|
|
248
|
+
10. **`property_group` chunks combine consecutive class fields**; a method/constructor
|
|
249
|
+
chunk interrupts the group. A class can have multiple groups.
|
|
250
|
+
11. **The file region is always exactly one `AstRegion` of `ChunkKind: "module"`**, with
|
|
251
|
+
`children` for top-level symbols (and recursively for class members). The region
|
|
252
|
+
contract is documented normatively in exactly ONE place: the `AstRegion` type in
|
|
253
|
+
`packages/domain/src/analysis.ts`. The chunker unpacks the root region and handles
|
|
254
|
+
each `chunkKind` according to its kind at every depth. Symbol chunks
|
|
255
|
+
(function/method/constructor/class_overview) therefore exist even when the entire
|
|
256
|
+
file fits within the token budget (spec.md §8.3 steps 3–5).
|
|
257
|
+
12. **Symbol regions include the `export` wrapper.** The tree-sitter scope node is only
|
|
258
|
+
the declaration (`function_declaration`, etc.); the enclosing `export_statement`
|
|
259
|
+
belongs to the symbol's chunk, rather than a module-level gap. `chunks.ts#ownRange`
|
|
260
|
+
expands the region accordingly, in addition to the already associated documentation/
|
|
261
|
+
decorator range (spec.md §8.3 step 2).
|
|
262
|
+
13. **`static { ... }` blocks are modeled as separate child regions of the class**
|
|
263
|
+
(`chunkKind: "property_group"`, not splittable). They open no symbol scope (no name
|
|
264
|
+
or stable symbol ID), but contain executable content that would otherwise escape
|
|
265
|
+
the chunker's member traversal (spec.md §8.4, no silent data loss). Comparable
|
|
266
|
+
unmodeled constructs in a class body (comments between methods, delimiters) are
|
|
267
|
+
covered by the chunker's gap handling; see region contract item 4 in
|
|
268
|
+
`domain/src/analysis.ts`.
|
|
269
|
+
|
|
270
|
+
## Tests
|
|
271
|
+
|
|
272
|
+
`npx vitest run` (55 tests, co-located `*.test.ts`):
|
|
273
|
+
|
|
274
|
+
- `text/byte-offset-table.test.ts` — UTF-8/UTF-16 conversion, including astral characters.
|
|
275
|
+
- `languages/shared/signature.test.ts` — whitespace/default/optional-marker normalization.
|
|
276
|
+
- `languages/shared/grammar-loader.test.ts` — caching, end-to-end parse sanity.
|
|
277
|
+
- `registry.test.ts` — extension/language resolution, override semantics.
|
|
278
|
+
- `languages/golden.test.ts` — golden fixtures (`__golden__/*.json`) for TS/JS/TSX: symbols,
|
|
279
|
+
imports, calls, decision kinds, scope ID consistency, AST depth.
|
|
280
|
+
- `languages/adapters.test.ts` — syntax errors → `partial`/`failed` without crashing;
|
|
281
|
+
classes with multiple methods → separate, non-overlapping regions; dynamic imports
|
|
282
|
+
and re-exports; signature normalization stable under whitespace changes (including
|
|
283
|
+
the cross-check “same result with different formatting, different result for actual
|
|
284
|
+
semantic changes such as optional instead of default”); astHash stable under whitespace
|
|
285
|
+
reformatting and literal-only edits; tokenFingerprint changes under literal edits;
|
|
286
|
+
guard clause detection.
|
|
287
|
+
- `index.test.ts` — `createParserRegistry()` correctly registers all four MVP languages.
|
|
288
|
+
|
|
289
|
+
<a id="verifikation"></a>
|
|
290
|
+
|
|
291
|
+
## Verification
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
npx tsc -p tsconfig.typecheck.json # 0 errors
|
|
295
|
+
npx tsc -p tsconfig.json # Build, 0 errors
|
|
296
|
+
npx vitest run # 55/55 passing
|
|
297
|
+
npx eslint packages/parser-registry # 0 errors, 0 warnings
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
<a id="e4-ehrlichkeitspruefung-wp-165"></a>
|
|
301
|
+
|
|
302
|
+
## E4 honesty check (WP-165)
|
|
303
|
+
|
|
304
|
+
`src/honesty.test.ts` runs `assertHonestUnderDamage` from `@untangle-code/testkit` against
|
|
305
|
+
both adapter families — TypeScript (tree-sitter) and Python (this package's handwritten
|
|
306
|
+
tokenizer/parser) — using ONE shared adapter instance per family, so concurrency damage
|
|
307
|
+
can affect shared state (grammar cache, offset tables).
|
|
308
|
+
|
|
309
|
+
It does not check symbol counts (shorter input may correctly reduce them). It checks that
|
|
310
|
+
the returned region tree still spans the entire input, all reported ranges lie within the
|
|
311
|
+
input, and the single `"module"` root required by the adapter contract is present.
|
|
312
|
+
|
|
313
|
+
**Result: both adapters pass every damage case.** For damaged structure, the Python
|
|
314
|
+
adapter reports seven diagnostics and lowers quality; the TypeScript adapter keeps its
|
|
315
|
+
promises unchanged. Also checked and correct: byte offsets for characters outside the
|
|
316
|
+
BMP (emoji) and umlauts. The classic UTF-16-instead-of-byte error is absent here.
|
|
317
|
+
|
|
318
|
+
<a id="bekannte-grenzen-e4"></a>
|
|
319
|
+
|
|
320
|
+
### Known limits (E4)
|
|
321
|
+
|
|
322
|
+
- **Not every `.children` use in this package has been converted.** The three traversals
|
|
323
|
+
covering the entire tree have been converted: `engine.ts`, `fingerprint.ts` and
|
|
324
|
+
`parse-diagnostics.ts`. Targeted accesses in `import-detection.ts`, `scope-signature.ts`,
|
|
325
|
+
`scope-naming.ts`, `chunks.ts` and `node-utils.ts` still use `.children`. They are not
|
|
326
|
+
measurably expensive (each sees only a handful of children), but share the type defect
|
|
327
|
+
described above: a comment node could appear under the wrong type. This currently
|
|
328
|
+
causes no damage because each location checks specific type names (`import_clause`,
|
|
329
|
+
`get`, `set`, `*`, `default`, `class_static_block`, …), none of which is the observed
|
|
330
|
+
incorrect type `interface_body`. `scripts/walk-gegenprobe.mjs` verifies that imports,
|
|
331
|
+
regions, chunk IDs and call edges remain unchanged. A different incorrect type with
|
|
332
|
+
another grammar could change this; those accesses would then need conversion too.
|
|
333
|
+
- **`LanguageAdapter.parse/extractChunks/extractSymbols` accept no `AbortSignal`.** The
|
|
334
|
+
signature belongs to `@untangle-code/domain` (`analysis.ts`) and cannot be changed
|
|
335
|
+
here; spec.md §22 requires cancellation support for public APIs. The `abort_signal`
|
|
336
|
+
damage case is therefore waived for precisely this reason and appears in the test
|
|
337
|
+
report's skip ledger.
|
|
338
|
+
|
|
339
|
+
<a id="lizenz"></a>
|
|
340
|
+
|
|
341
|
+
## License
|
|
342
|
+
|
|
343
|
+
**AGPL-3.0-only.** This package includes the full license text in [`LICENSE`](./LICENSE),
|
|
344
|
+
the rationale for the license choice in [`NOTICE`](./NOTICE), and the licenses of all
|
|
345
|
+
third-party production dependencies in [`THIRD_PARTY_LICENSES.md`](./THIRD_PARTY_LICENSES.md).
|
|
346
|
+
All three files are part of the npm tarball — AGPL-3.0-only §4 and §5 require every recipient
|
|
347
|
+
to receive the license, and a README alone is not a copy of the license.
|
|
348
|
+
|
|
349
|
+
Local use creates no obligation. Copyleft obligations apply to redistribution and provision
|
|
350
|
+
as a network service (AGPL §13).
|
|
351
|
+
|
|
352
|
+
The corresponding TypeScript source is included under `src/` in the same tarball; the full
|
|
353
|
+
repository is available at <https://github.com/lboel/untangle>.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Third-party licenses — @untangle-code/parser-registry
|
|
2
|
+
|
|
3
|
+
Generated by `pnpm third-party-licenses` from this package's installed
|
|
4
|
+
production dependency tree: transitive `dependencies`, across
|
|
5
|
+
workspace edges, with no `devDependencies` included. The generator reads
|
|
6
|
+
each resolved package's `package.json` in `node_modules`; nothing is maintained by hand
|
|
7
|
+
or estimated.
|
|
8
|
+
|
|
9
|
+
Do not edit manually: `pnpm third-party-licenses --check` fails on drift,
|
|
10
|
+
and `pnpm check-publishable` rejects packages without a current file.
|
|
11
|
+
|
|
12
|
+
This file exists because `docs/BUILD_PLAN.md`, risk R6, makes
|
|
13
|
+
per-package `THIRD_PARTY_LICENSES.md` a release gate for npm publication.
|
|
14
|
+
|
|
15
|
+
Untangle itself is **AGPL-3.0-only** (see `LICENSE` and `NOTICE` in
|
|
16
|
+
this package). The packages below are third-party works; their own
|
|
17
|
+
licenses and copyright notices continue to apply unchanged. Workspace
|
|
18
|
+
packages (`@untangle-code/*`) are not listed here; they belong to the same
|
|
19
|
+
work and use the same AGPL-3.0-only license.
|
|
20
|
+
|
|
21
|
+
## Production dependencies (transitive, 25)
|
|
22
|
+
|
|
23
|
+
| Package | Version | License | Project |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `@ast-grep/lang-python` | 0.0.6 | ISC | — |
|
|
26
|
+
| `@ast-grep/napi` | 0.45.3 | MIT | <https://ast-grep.github.io> |
|
|
27
|
+
| `@ast-grep/setup-lang` | 0.0.6 | ISC | — |
|
|
28
|
+
| `@babel/helper-string-parser` | 7.29.7 | MIT | <https://babel.dev/docs/en/next/babel-helper-string-parser> |
|
|
29
|
+
| `@babel/helper-validator-identifier` | 7.29.7 | MIT | <https://github.com/babel/babel> |
|
|
30
|
+
| `@babel/parser` | 7.29.9 | MIT | <https://babel.dev/docs/en/next/babel-parser> |
|
|
31
|
+
| `@babel/types` | 7.29.8 | MIT | <https://babel.dev/docs/en/next/babel-types> |
|
|
32
|
+
| `@jridgewell/sourcemap-codec` | 1.6.0 | MIT | <https://github.com/jridgewell/sourcemaps/tree/main/packages/sourcemap-codec> |
|
|
33
|
+
| `@vue/compiler-core` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-core#readme> |
|
|
34
|
+
| `@vue/compiler-dom` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-dom#readme> |
|
|
35
|
+
| `@vue/compiler-sfc` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme> |
|
|
36
|
+
| `@vue/compiler-ssr` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/compiler-ssr#readme> |
|
|
37
|
+
| `@vue/shared` | 3.5.44 | MIT | <https://github.com/vuejs/core/tree/main/packages/shared#readme> |
|
|
38
|
+
| `entities` | 7.0.1 | BSD-2-Clause | <https://github.com/fb55/entities> |
|
|
39
|
+
| `estree-walker` | 2.0.2 | MIT | <https://github.com/Rich-Harris/estree-walker> |
|
|
40
|
+
| `magic-string` | 0.30.21 | MIT | <https://github.com/Rich-Harris/magic-string> |
|
|
41
|
+
| `nanoid` | 3.3.20 | MIT | `ai/nanoid` |
|
|
42
|
+
| `node-addon-api` | 8.9.2 | MIT | <https://github.com/nodejs/node-addon-api> |
|
|
43
|
+
| `node-gyp-build` | 4.8.4 | MIT | <https://github.com/prebuild/node-gyp-build> |
|
|
44
|
+
| `picocolors` | 1.1.1 | ISC | `alexeyraspopov/picocolors` |
|
|
45
|
+
| `postcss` | 8.5.31 | MIT | <https://postcss.org/> |
|
|
46
|
+
| `source-map-js` | 1.2.2 | BSD-3-Clause | <https://github.com/7rulnik/source-map-js> |
|
|
47
|
+
| `tree-sitter` | 0.21.1 | MIT | <http://github.com/tree-sitter/node-tree-sitter> |
|
|
48
|
+
| `tree-sitter-javascript` | 0.23.1 | MIT | <https://github.com/tree-sitter/tree-sitter-javascript> |
|
|
49
|
+
| `tree-sitter-typescript` | 0.23.2 | MIT | <https://github.com/tree-sitter/tree-sitter-typescript> |
|
|
50
|
+
|
|
51
|
+
The allowlist (MIT / Apache-2.0 / BSD / ISC / …) is checked by
|
|
52
|
+
`scripts/check-licenses.mjs` against this exact tree on every run;
|
|
53
|
+
the GPL family is excluded (architecture.md §2.4, BUILD_PLAN R6).
|
|
54
|
+
|
|
55
|
+
## Embedded tree-sitter grammars (12)
|
|
56
|
+
|
|
57
|
+
The `@ast-grep/lang-*` packages distribute third-party tree-sitter grammars:
|
|
58
|
+
their `src/parser.c` files are byte-identical to the listed grammar versions,
|
|
59
|
+
as verified by `pnpm grammar-provenance --update`
|
|
60
|
+
(field `parserMatchesGrammar`). However, their own `LICENSE` only names
|
|
61
|
+
`Copyright (c) 2025 ast-grep`; the grammar authors are not listed there.
|
|
62
|
+
Untangle therefore records their notices here.
|
|
63
|
+
|
|
64
|
+
| Language package | Dependency | Grammar | License | Copyright notice |
|
|
65
|
+
| --- | --- | --- | --- | --- |
|
|
66
|
+
| `@ast-grep/lang-bash` | optional; install separately | `tree-sitter-bash` 0.25.1 | MIT | Copyright (c) 2017 Max Brunsfeld |
|
|
67
|
+
| `@ast-grep/lang-c` | optional; install separately | `tree-sitter-c` 0.24.1 | MIT | Copyright (c) 2014 Max Brunsfeld |
|
|
68
|
+
| `@ast-grep/lang-cpp` | optional; install separately | `tree-sitter-cpp` 0.23.4 | MIT | Copyright (c) 2014 Max Brunsfeld |
|
|
69
|
+
| `@ast-grep/lang-csharp` | optional; install separately | `tree-sitter-c-sharp` 0.23.1 | MIT | Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors. |
|
|
70
|
+
| `@ast-grep/lang-go` | optional; install separately | `tree-sitter-go` 0.25.0 | MIT | Copyright (c) 2014 Max Brunsfeld |
|
|
71
|
+
| `@ast-grep/lang-java` | optional; install separately | `tree-sitter-java` 0.23.5 | MIT | Copyright (c) 2017 Ayman Nadeem |
|
|
72
|
+
| `@ast-grep/lang-kotlin` | optional; install separately | `tree-sitter-kotlin` 0.3.8 | MIT | Copyright (c) 2019 fwcd |
|
|
73
|
+
| `@ast-grep/lang-php` | optional; install separately | `tree-sitter-php` 0.24.2 | MIT | Copyright (c) 2017 Josh Vera, GitHub<br>Copyright (c) 2019 Max Brunsfeld, Amaan Qureshi, Christian Frøystad, Caleb White |
|
|
74
|
+
| `@ast-grep/lang-python` | Dependency | `tree-sitter-python` 0.25.0 | MIT | Copyright (c) 2016 Max Brunsfeld |
|
|
75
|
+
| `@ast-grep/lang-ruby` | optional; install separately | `tree-sitter-ruby` 0.23.1 | MIT | Copyright (c) 2016 Rob Rix |
|
|
76
|
+
| `@ast-grep/lang-rust` | optional; install separately | `tree-sitter-rust` 0.23.2 | MIT | Copyright (c) 2017 Maxim Sokolov |
|
|
77
|
+
| `@ast-grep/lang-swift` | optional; install separately | `tree-sitter-swift` 0.7.1 | MIT | Copyright (c) 2021 alex-pinkus |
|
|
78
|
+
|
|
79
|
+
**An unresolved question that Untangle cannot decide.** All language packages above
|
|
80
|
+
declare `"license": "ISC"` in `package.json`, but include an **MIT** license text.
|
|
81
|
+
Both declarations cannot apply simultaneously. Which declaration ast-grep intends
|
|
82
|
+
cannot be determined externally; this file records
|
|
83
|
+
the contradiction instead of inventing a resolution. For the embedded
|
|
84
|
+
grammars, the license is unambiguous: the table uses the license text
|
|
85
|
+
inside each grammar version's tarball rather than its
|
|
86
|
+
registry metadata's `license` field.
|
|
87
|
+
|
|
88
|
+
Packages marked *optional* are not included in an Untangle installation:
|
|
89
|
+
they are optional `peerDependencies`, which npm
|
|
90
|
+
does not install automatically. They are listed for users who
|
|
91
|
+
add them to enable the corresponding language.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HttpExpressionV1 } from "@untangle-code/domain";
|
|
2
|
+
import type { SyntaxNode } from "../languages/shared/syntax.js";
|
|
3
|
+
export declare function namedChildren(node: SyntaxNode): SyntaxNode[];
|
|
4
|
+
export declare function field(node: SyntaxNode, name: string): SyntaxNode | null;
|
|
5
|
+
export declare function unknown(detail: string): HttpExpressionV1;
|
|
6
|
+
/** Only unescaped literals are accepted. Unsupported escapes remain explicit unknowns. */
|
|
7
|
+
export declare function stringValue(node: SyntaxNode | null): string | null;
|
|
8
|
+
/** Interpret syntax, never execute source expressions or scan comments/string contents as code. */
|
|
9
|
+
export declare function expression(node: SyntaxNode | null, depth?: number): HttpExpressionV1;
|
|
10
|
+
//# sourceMappingURL=expression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../src/boundaries/expression.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAEhE,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,EAAE,CAE5D;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAEvE;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAExD;AAED,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAOlE;AAED,mGAAmG;AACnG,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,KAAK,SAAI,GAAG,gBAAgB,CAmE/E"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
export function namedChildren(node) {
|
|
2
|
+
return node.children.filter((child) => child.isNamed && child.type !== "comment");
|
|
3
|
+
}
|
|
4
|
+
export function field(node, name) {
|
|
5
|
+
return node.childForFieldName(name);
|
|
6
|
+
}
|
|
7
|
+
export function unknown(detail) {
|
|
8
|
+
return { kind: "unknown", detail };
|
|
9
|
+
}
|
|
10
|
+
/** Only unescaped literals are accepted. Unsupported escapes remain explicit unknowns. */
|
|
11
|
+
export function stringValue(node) {
|
|
12
|
+
if (node === null || (node.type !== "string" && node.type !== "string_literal"))
|
|
13
|
+
return null;
|
|
14
|
+
const raw = node.text;
|
|
15
|
+
const quote = raw[0];
|
|
16
|
+
if ((quote !== "'" && quote !== '"') || raw.at(-1) !== quote || raw.includes("\\"))
|
|
17
|
+
return null;
|
|
18
|
+
if (raw.startsWith(quote.repeat(3)))
|
|
19
|
+
return null;
|
|
20
|
+
return raw.slice(1, -1);
|
|
21
|
+
}
|
|
22
|
+
/** Interpret syntax, never execute source expressions or scan comments/string contents as code. */
|
|
23
|
+
export function expression(node, depth = 0) {
|
|
24
|
+
if (node === null)
|
|
25
|
+
return unknown("missing expression");
|
|
26
|
+
if (depth > 40)
|
|
27
|
+
return unknown("expression depth budget exceeded");
|
|
28
|
+
const next = (child) => expression(child, depth + 1);
|
|
29
|
+
const string = stringValue(node);
|
|
30
|
+
if (string !== null)
|
|
31
|
+
return { kind: "string", value: string };
|
|
32
|
+
if (node.type === "identifier" || node.type === "shorthand_property_identifier") {
|
|
33
|
+
return node.text === "undefined" ? { kind: "undefined" } : { kind: "name", name: node.text };
|
|
34
|
+
}
|
|
35
|
+
if (["parenthesized_expression", "as_expression", "type_assertion", "await_expression"].includes(node.type)) {
|
|
36
|
+
return next(namedChildren(node)[0] ?? null);
|
|
37
|
+
}
|
|
38
|
+
if (node.type === "member_expression" || node.type === "attribute") {
|
|
39
|
+
const property = field(node, "property") ?? field(node, "attribute");
|
|
40
|
+
return property === null
|
|
41
|
+
? unknown("computed member")
|
|
42
|
+
: {
|
|
43
|
+
kind: "member",
|
|
44
|
+
object: next(field(node, "object")),
|
|
45
|
+
property: property.text,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (node.type === "call_expression" || node.type === "call") {
|
|
49
|
+
return {
|
|
50
|
+
kind: "call",
|
|
51
|
+
callee: next(field(node, "function")),
|
|
52
|
+
arguments: namedChildren(field(node, "arguments") ?? node).map(next),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (node.type === "template_string") {
|
|
56
|
+
const parts = [];
|
|
57
|
+
for (const child of namedChildren(node)) {
|
|
58
|
+
if (child.type === "string_fragment")
|
|
59
|
+
parts.push(child.text);
|
|
60
|
+
else if (child.type === "template_substitution")
|
|
61
|
+
parts.push(next(namedChildren(child)[0] ?? null));
|
|
62
|
+
else
|
|
63
|
+
return unknown("escaped or unsupported template segment");
|
|
64
|
+
}
|
|
65
|
+
return { kind: "template", parts };
|
|
66
|
+
}
|
|
67
|
+
if (node.type === "binary_expression" &&
|
|
68
|
+
node.children.some((child) => child.text === "+" && !child.isNamed)) {
|
|
69
|
+
return { kind: "template", parts: [next(field(node, "left")), next(field(node, "right"))] };
|
|
70
|
+
}
|
|
71
|
+
if (node.type === "object") {
|
|
72
|
+
const entries = [];
|
|
73
|
+
for (const child of namedChildren(node)) {
|
|
74
|
+
if (child.type === "spread_element")
|
|
75
|
+
entries.push({ spread: next(namedChildren(child)[0] ?? null) });
|
|
76
|
+
else if (child.type === "pair") {
|
|
77
|
+
const key = field(child, "key");
|
|
78
|
+
const literalKey = stringValue(key);
|
|
79
|
+
if (key === null || (literalKey === null && key.type !== "property_identifier")) {
|
|
80
|
+
entries.push({ spread: unknown("computed object key") });
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
entries.push({ key: literalKey ?? key.text, value: next(field(child, "value")) });
|
|
84
|
+
}
|
|
85
|
+
else if (child.type === "shorthand_property_identifier") {
|
|
86
|
+
entries.push({ key: child.text, value: next(child) });
|
|
87
|
+
}
|
|
88
|
+
else
|
|
89
|
+
entries.push({ spread: unknown("unsupported object entry") });
|
|
90
|
+
}
|
|
91
|
+
return { kind: "object", entries };
|
|
92
|
+
}
|
|
93
|
+
return unknown(`unsupported ${node.type}`);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=expression.js.map
|