@untangle-code/parser-registry 0.0.0-stage → 0.1.0
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
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Der backend-neutrale Baumvertrag (`shared/syntax.ts`), nachgebaut ueber
|
|
3
|
+
* `SgNode`.
|
|
4
|
+
*
|
|
5
|
+
* WARUM DAS HIER TEURER IST ALS DER ANDERE WEG, und warum wir es trotzdem so
|
|
6
|
+
* bauen: ast-grep hat KEINE Cursor-API. Es gibt kein Gegenstueck zu
|
|
7
|
+
* `gotoFirstChild`/`gotoNextSibling`/`gotoParent`; jeder Abstieg geht ueber
|
|
8
|
+
* `children()`, und jedes `children()` baut ein frisches JS-Array aus
|
|
9
|
+
* Knotenwrappern. Gemessen an diesem Repositorium (721 Dateien, 1.143.212
|
|
10
|
+
* Knoten): tree-sitter-Cursor 1.703.642 Knoten/s gegen ast-grep 455.329
|
|
11
|
+
* Knoten/s — Faktor 3,74, Mehrkosten 1,61 us je Knoten. Das ist das Niveau des
|
|
12
|
+
* `.children`-Weges, den WP-95 abgeschafft hat.
|
|
13
|
+
*
|
|
14
|
+
* Deshalb: die JS/TS-Familie bleibt bei tree-sitter, und dieser Cursor ist der
|
|
15
|
+
* Weg fuer Sprachen, die es sonst GAR NICHT gaebe. Fuer sie ist der Aufpreis
|
|
16
|
+
* kein Rueckschritt — er ist der Eintrittspreis.
|
|
17
|
+
*
|
|
18
|
+
* WAS DIESER CURSOR TROTZDEM RICHTIG MACHT:
|
|
19
|
+
* - Er ist ITERATIV. Ein Baum kann zehntausende Ebenen tief sein (eine lange
|
|
20
|
+
* `a || b || c`-Kette genuegt); ein rekursiver Walk zerbricht daran mit
|
|
21
|
+
* `RangeError: Maximum call stack size exceeded`, nachgemessen an 50.000
|
|
22
|
+
* Gliedern.
|
|
23
|
+
* - Er materialisiert die Kindliste je Ebene EINMAL, nicht je Zugriff.
|
|
24
|
+
* - Er merkt sich den Bereich (`range()`) des aktuellen Knotens, weil
|
|
25
|
+
* `rangeOfCursor` vier Werte daraus liest und ast-grep bei jedem Aufruf ein
|
|
26
|
+
* verschachteltes Objekt neu baut.
|
|
27
|
+
*
|
|
28
|
+
* WAS ER NICHT KANN — und was der Adapter deshalb ehrlich sagen muss:
|
|
29
|
+
* - `nodeIsMissing` gibt es bei ast-grep nicht. Hier steht eine HEURISTIK:
|
|
30
|
+
* ein Blatt der Breite null. An diesem Repositorium war sie exakt (3 von 3
|
|
31
|
+
* MISSING-Knoten), sie bleibt aber eine Heuristik. `create-adapter.ts`
|
|
32
|
+
* schreibt das in JEDE davon erzeugte Diagnose.
|
|
33
|
+
* - `currentFieldName` gibt es nicht als Rueckrichtung. Wir fragen die
|
|
34
|
+
* Felder ab, die das Sprachprofil nennt, und vergleichen ueber `id()` —
|
|
35
|
+
* prozesslokal gueltig, nie in Ergebnisdaten (siehe `napi.ts`).
|
|
36
|
+
*/
|
|
37
|
+
import type { SyntaxCursor, SyntaxNode, SyntaxPoint } from "../shared/syntax.js";
|
|
38
|
+
|
|
39
|
+
import type { SgNode, SgPos } from "./napi.js";
|
|
40
|
+
|
|
41
|
+
function pointOf(pos: SgPos): SyntaxPoint {
|
|
42
|
+
return { row: pos.line, column: pos.column };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Ein `SgNode` in der Form, die `shared/` erwartet. */
|
|
46
|
+
export class AstGrepSyntaxNode implements SyntaxNode {
|
|
47
|
+
constructor(
|
|
48
|
+
/** Der rohe ast-grep-Knoten. Nur `syntax.ts` fasst ihn an. */
|
|
49
|
+
readonly sg: SgNode,
|
|
50
|
+
private readonly fieldNames: readonly string[],
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
get type(): string {
|
|
54
|
+
return this.sg.kind();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get text(): string {
|
|
58
|
+
return this.sg.text();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get isNamed(): boolean {
|
|
62
|
+
return this.sg.isNamed();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get startIndex(): number {
|
|
66
|
+
return this.sg.range().start.index;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get endIndex(): number {
|
|
70
|
+
return this.sg.range().end.index;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
get startPosition(): SyntaxPoint {
|
|
74
|
+
return pointOf(this.sg.range().start);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get endPosition(): SyntaxPoint {
|
|
78
|
+
return pointOf(this.sg.range().end);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get parent(): SyntaxNode | null {
|
|
82
|
+
const parent = this.sg.parent();
|
|
83
|
+
return parent === null ? null : new AstGrepSyntaxNode(parent, this.fieldNames);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get previousSibling(): SyntaxNode | null {
|
|
87
|
+
// Geprueft: ast-grep `prev()` liefert auch ANONYME Geschwister (das
|
|
88
|
+
// vorangehende `{` einer Blockklammer ebenso wie einen Kommentar). Waere
|
|
89
|
+
// es nur das vorherige benannte Geschwister, verschoebe sich die
|
|
90
|
+
// Doc-Bindung stillschweigend.
|
|
91
|
+
const previous = this.sg.prev();
|
|
92
|
+
return previous === null ? null : new AstGrepSyntaxNode(previous, this.fieldNames);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get children(): readonly SyntaxNode[] {
|
|
96
|
+
return this.sg.children().map((child) => new AstGrepSyntaxNode(child, this.fieldNames));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get namedChildCount(): number {
|
|
100
|
+
return this.sg.namedChildren().length;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
namedChild(index: number): SyntaxNode | null {
|
|
104
|
+
const child = this.sg.namedChildren()[index];
|
|
105
|
+
return child === undefined ? null : new AstGrepSyntaxNode(child, this.fieldNames);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
childForFieldName(fieldName: string): SyntaxNode | null {
|
|
109
|
+
// Ein unbekannter Feldname liefert bei ast-grep `null` (geprueft), wirft
|
|
110
|
+
// also nicht — ein Profil darf nach Feldern fragen, die es in dieser
|
|
111
|
+
// Grammatik nicht gibt.
|
|
112
|
+
const field = this.sg.field(fieldName);
|
|
113
|
+
return field === null ? null : new AstGrepSyntaxNode(field, this.fieldNames);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
walk(): SyntaxCursor {
|
|
117
|
+
return new AstGrepCursor(this.sg, this.fieldNames);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** Eine Ebene des Abstiegs: die Geschwisterliste und die Stelle darin. */
|
|
122
|
+
interface CursorLevel {
|
|
123
|
+
siblings: SgNode[];
|
|
124
|
+
index: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export class AstGrepCursor implements SyntaxCursor {
|
|
128
|
+
private readonly levels: CursorLevel[] = [];
|
|
129
|
+
private rangeCacheNode: SgNode | null = null;
|
|
130
|
+
private rangeCacheValue: { start: SgPos; end: SgPos } | null = null;
|
|
131
|
+
|
|
132
|
+
constructor(
|
|
133
|
+
private readonly rootNode: SgNode,
|
|
134
|
+
private readonly fieldNames: readonly string[],
|
|
135
|
+
) {}
|
|
136
|
+
|
|
137
|
+
private get node(): SgNode {
|
|
138
|
+
const level = this.levels[this.levels.length - 1];
|
|
139
|
+
if (level === undefined) return this.rootNode;
|
|
140
|
+
return level.siblings[level.index] as SgNode;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private get range(): { start: SgPos; end: SgPos } {
|
|
144
|
+
const node = this.node;
|
|
145
|
+
if (this.rangeCacheNode === node && this.rangeCacheValue !== null) return this.rangeCacheValue;
|
|
146
|
+
const value = node.range();
|
|
147
|
+
this.rangeCacheNode = node;
|
|
148
|
+
this.rangeCacheValue = value;
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
get nodeType(): string {
|
|
153
|
+
return this.node.kind();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get nodeText(): string {
|
|
157
|
+
return this.node.text();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
get nodeIsMissing(): boolean {
|
|
161
|
+
// HEURISTIK, kein Messwert: ast-grep kennt `ts_node_is_missing` nicht.
|
|
162
|
+
// Ein von der Fehlerkorrektur eingefuegter Knoten hat die Breite null und
|
|
163
|
+
// keine Kinder; die Wurzel ist ausgenommen (eine leere Datei ist kein
|
|
164
|
+
// fehlender Knoten).
|
|
165
|
+
if (this.levels.length === 0) return false;
|
|
166
|
+
const range = this.range;
|
|
167
|
+
return range.start.index === range.end.index && this.node.isLeaf();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
get currentFieldName(): string | undefined {
|
|
171
|
+
const parent = this.parentNode();
|
|
172
|
+
if (parent === null) return undefined;
|
|
173
|
+
const nodeId = this.node.id();
|
|
174
|
+
for (const fieldName of this.fieldNames) {
|
|
175
|
+
const field = parent.field(fieldName);
|
|
176
|
+
if (field !== null && field.id() === nodeId) return fieldName;
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Der Elternknoten der aktuellen Position, oder `null` auf der Wurzel. */
|
|
182
|
+
private parentNode(): SgNode | null {
|
|
183
|
+
if (this.levels.length === 0) return null;
|
|
184
|
+
if (this.levels.length === 1) return this.rootNode;
|
|
185
|
+
const level = this.levels[this.levels.length - 2] as CursorLevel;
|
|
186
|
+
return level.siblings[level.index] as SgNode;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get currentNode(): SyntaxNode {
|
|
190
|
+
return new AstGrepSyntaxNode(this.node, this.fieldNames);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get startPosition(): SyntaxPoint {
|
|
194
|
+
return pointOf(this.range.start);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
get endPosition(): SyntaxPoint {
|
|
198
|
+
return pointOf(this.range.end);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
get startIndex(): number {
|
|
202
|
+
return this.range.start.index;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
get endIndex(): number {
|
|
206
|
+
return this.range.end.index;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
gotoParent(): boolean {
|
|
210
|
+
if (this.levels.length === 0) return false;
|
|
211
|
+
this.levels.pop();
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
gotoFirstChild(): boolean {
|
|
216
|
+
const children = this.node.children();
|
|
217
|
+
if (children.length === 0) return false;
|
|
218
|
+
this.levels.push({ siblings: children, index: 0 });
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
gotoLastChild(): boolean {
|
|
223
|
+
const children = this.node.children();
|
|
224
|
+
if (children.length === 0) return false;
|
|
225
|
+
this.levels.push({ siblings: children, index: children.length - 1 });
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
gotoNextSibling(): boolean {
|
|
230
|
+
const level = this.levels[this.levels.length - 1];
|
|
231
|
+
if (level === undefined || level.index + 1 >= level.siblings.length) return false;
|
|
232
|
+
level.index += 1;
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
gotoPreviousSibling(): boolean {
|
|
237
|
+
const level = this.levels[this.levels.length - 1];
|
|
238
|
+
if (level === undefined || level.index === 0) return false;
|
|
239
|
+
level.index -= 1;
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Central builtin-language registration point.
|
|
3
|
+
*
|
|
4
|
+
* Dateibesitz (BUILD_PLAN §4): every path under `packages/parser-registry/`
|
|
5
|
+
* belongs to WP-06, EXCEPT `src/languages/python/**` and "the registration
|
|
6
|
+
* line" in this file, both owned by WP-09 (a later wave). WP-09 adds its
|
|
7
|
+
* import and ONE `registry.register(createPythonAdapter());` line below,
|
|
8
|
+
* without touching any line above it — that is the whole contract for
|
|
9
|
+
* adding a language without editing existing files/lines.
|
|
10
|
+
*/
|
|
11
|
+
import type { LazyParserRegistry } from "../registry.js";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
createBreadthAdapters,
|
|
15
|
+
createGoAdapter,
|
|
16
|
+
createRustAdapter,
|
|
17
|
+
} from "./astgrep-backend/index.js";
|
|
18
|
+
import { createJavaScriptAdapter } from "./javascript/index.js";
|
|
19
|
+
import { createJsxAdapter } from "./jsx/index.js";
|
|
20
|
+
import { createProseAdapter } from "./prose/index.js";
|
|
21
|
+
import { createPythonAdapter } from "./python/index.js";
|
|
22
|
+
import { createStructuredTextAdapter } from "./structured-text/index.js";
|
|
23
|
+
import { createTsxAdapter } from "./tsx/index.js";
|
|
24
|
+
import { createTypeScriptAdapter } from "./typescript/index.js";
|
|
25
|
+
import { createVueAdapter } from "./vue/index.js";
|
|
26
|
+
|
|
27
|
+
/** Registers every builtin language adapter. Registration is cheap and lazy — see `registry.ts`'s doc comment. */
|
|
28
|
+
export function registerBuiltinLanguages(registry: LazyParserRegistry): void {
|
|
29
|
+
registry.register(createTypeScriptAdapter());
|
|
30
|
+
registry.register(createJavaScriptAdapter());
|
|
31
|
+
registry.register(createTsxAdapter());
|
|
32
|
+
registry.register(createJsxAdapter());
|
|
33
|
+
registry.register(createVueAdapter());
|
|
34
|
+
registry.register(createPythonAdapter());
|
|
35
|
+
// WP-110/WP-217: Prosa und strukturierte Daten sind Stufe `text`, nicht
|
|
36
|
+
// `unsupported_language` (vision.md §1c, spec.md §7.2). Beide Adapter
|
|
37
|
+
// laden keine Grammatik und kosten bei der Registrierung nichts.
|
|
38
|
+
registry.register(createProseAdapter());
|
|
39
|
+
registry.register(createStructuredTextAdapter());
|
|
40
|
+
// WP-220: Go und Rust laufen ueber das ast-grep-Backend
|
|
41
|
+
// (`languages/astgrep-backend/README.md` sagt, warum GENAU diese Sprachen
|
|
42
|
+
// dort laufen und die JS/TS-Familie nicht). Die Anmeldung kostet nichts:
|
|
43
|
+
// weder `@ast-grep/napi` noch eine Grammatik wird dabei geladen — das
|
|
44
|
+
// passiert erst beim ersten Parse einer dieser Sprachen.
|
|
45
|
+
registry.register(createGoAdapter());
|
|
46
|
+
registry.register(createRustAdapter());
|
|
47
|
+
// WP-86: neun weitere Sprachen ueber DASSELBE Backend und DIESELBE
|
|
48
|
+
// Tabellenform — Java, C#, Ruby, PHP, Kotlin, C, C++, Swift, Bash. Auch sie
|
|
49
|
+
// laden beim Registrieren nichts.
|
|
50
|
+
for (const adapter of createBreadthAdapters()) {
|
|
51
|
+
registry.register(adapter);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LanguageAdapter } from "@untangle-code/domain";
|
|
2
|
+
|
|
3
|
+
import { createTreeSitterAdapter } from "../shared/create-adapter.js";
|
|
4
|
+
import { JAVASCRIPT_DIALECT } from "../shared/dialect.js";
|
|
5
|
+
|
|
6
|
+
/** JavaScript `LanguageAdapter` (`.js`, `.mjs`, `.cjs`), support level "deep" (spec.md §7.2). */
|
|
7
|
+
export function createJavaScriptAdapter(): LanguageAdapter {
|
|
8
|
+
return createTreeSitterAdapter(JAVASCRIPT_DIALECT);
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LanguageAdapter } from "@untangle-code/domain";
|
|
2
|
+
|
|
3
|
+
import { createTreeSitterAdapter } from "../shared/create-adapter.js";
|
|
4
|
+
import { JSX_DIALECT } from "../shared/dialect.js";
|
|
5
|
+
|
|
6
|
+
/** JSX `LanguageAdapter` (`.jsx`), support level "deep" (spec.md §7.2). */
|
|
7
|
+
export function createJsxAdapter(): LanguageAdapter {
|
|
8
|
+
return createTreeSitterAdapter(JSX_DIALECT);
|
|
9
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prosa-`LanguageAdapter` (vision.md §1c, WP-110/WP-217).
|
|
3
|
+
*
|
|
4
|
+
* WAS ER LOEST
|
|
5
|
+
*
|
|
6
|
+
* Vor ihm kannte `getAdapterForPath("spec.md")` nur `null`. Jede Stelle, die
|
|
7
|
+
* das fragt — `untangle complexity`, der Watcher, der Selbstanalyse-Report —
|
|
8
|
+
* schrieb daraufhin `unsupported_language` ins Skip-Ledger. Bei der ersten
|
|
9
|
+
* Selbstanalyse dieses Repositories waren das allein 35 Markdown-Dateien,
|
|
10
|
+
* bei 654 KB Markdown gegen 2.006 KB TypeScript. vision.md §1c sagt genau
|
|
11
|
+
* das Gegenteil: Prosa ist erstklassiger Inhalt, und `text` ist kein
|
|
12
|
+
* abgeschwaechtes `deep`.
|
|
13
|
+
*
|
|
14
|
+
* WAS ER LIEFERT — UND WAS BEWUSST NICHT
|
|
15
|
+
*
|
|
16
|
+
* - `extractChunks` liefert ueberschriftenbewusste Abschnitte mit
|
|
17
|
+
* Breadcrumb. Die Gliederung ist NICHT neu gebaut: es ist dieselbe
|
|
18
|
+
* `outlineMarkdown()`, die `@untangle-code/context-artifacts` schon fuer
|
|
19
|
+
* konfigurierte Markdown-Artefakte benutzt hat (WP-110 hat sie nach
|
|
20
|
+
* domain gehoben). Damit bekommt eine gewoehnliche `.md`-Datei im Chunker
|
|
21
|
+
* die AST-Strategie statt `line_fallback` — statt willkuerlicher
|
|
22
|
+
* Zeilenfenster also dieselben semantischen Einheiten wie eine
|
|
23
|
+
* konfigurierte.
|
|
24
|
+
* - `extractSymbols` liefert je Abschnitt ein Symbol der Art `"section"`.
|
|
25
|
+
* Das ist die Zuordnung, ueber die der Chunker `symbolId`/`symbolFqn` an
|
|
26
|
+
* jeden Abschnitt und an jedes Fragment eines zu grossen Abschnitts
|
|
27
|
+
* haengt (spec.md §8.5).
|
|
28
|
+
* - `extractImports` liefert relative Dateiverweise. Ein Verweis von
|
|
29
|
+
* `vision.md` auf `spec.md` IST eine Kante im Dateigraphen; sie zu
|
|
30
|
+
* verschweigen waere derselbe Verlust wie ein verschwiegener Import.
|
|
31
|
+
* - `extractCalls` liefert NICHTS. Prosa hat keine Aufrufe.
|
|
32
|
+
* - `computeComplexity` liefert LEERE Facts: keine `symbolScopes`, keine
|
|
33
|
+
* `decisions`. Das ist der Kern von WP-217 und keine Nachlaessigkeit —
|
|
34
|
+
* zyklomatische Komplexitaet ueber ein Dokument ist keine schlechte Zahl,
|
|
35
|
+
* sondern gar keine. Wer Prosa messen will, nimmt die Prosa-Metriken aus
|
|
36
|
+
* `@untangle-code/complexity` (`computeProseMetrics`), die als eigene
|
|
37
|
+
* Metrikfamilie (`ProseNumberV1`) gefuehrt werden und deshalb strukturell
|
|
38
|
+
* nie in eine Code-Summe geraten koennen.
|
|
39
|
+
* - `tokenizeForHalstead` liefert NICHTS: Halstead zaehlt Operatoren und
|
|
40
|
+
* Operanden; in Prosa gibt es beides nicht.
|
|
41
|
+
*
|
|
42
|
+
* `parse()` kann nicht scheitern. Markdown hat keine Syntaxfehler — jeder
|
|
43
|
+
* Text ist gueltiges Markdown —, deshalb ist `parseQuality` immer
|
|
44
|
+
* `"complete"` und `ast` nie `null`. Das ist eine Aussage ueber das Format,
|
|
45
|
+
* keine Beschoenigung.
|
|
46
|
+
*/
|
|
47
|
+
import type {
|
|
48
|
+
AstRegion,
|
|
49
|
+
ComplexityFacts,
|
|
50
|
+
ExtractedSymbol,
|
|
51
|
+
HalsteadTokens,
|
|
52
|
+
LanguageAdapter,
|
|
53
|
+
MarkdownSectionV1,
|
|
54
|
+
ParsedAst,
|
|
55
|
+
ParseResult,
|
|
56
|
+
RawCall,
|
|
57
|
+
RawImport,
|
|
58
|
+
SourceFile,
|
|
59
|
+
SourceRange,
|
|
60
|
+
} from "@untangle-code/domain";
|
|
61
|
+
import {
|
|
62
|
+
classifyLinkTarget,
|
|
63
|
+
findMarkdownLinks,
|
|
64
|
+
outlineMarkdown,
|
|
65
|
+
sha256Hex,
|
|
66
|
+
textFormatExtensions,
|
|
67
|
+
} from "@untangle-code/domain";
|
|
68
|
+
|
|
69
|
+
import { buildLineByteIndex, rangeForLines, type LineByteIndex } from "./line-bytes.js";
|
|
70
|
+
|
|
71
|
+
/** Sprachkennung dieses Adapters; identisch mit der Scanner-Klassifikation fuer `.md`. */
|
|
72
|
+
export const PROSE_LANGUAGE_ID = "markdown";
|
|
73
|
+
|
|
74
|
+
/** Symbolart eines Prosa-Abschnitts. Ein Abschnitt ist keine Funktion und heisst auch nicht so. */
|
|
75
|
+
export const PROSE_SYMBOL_KIND = "section";
|
|
76
|
+
|
|
77
|
+
/** Name des Abschnitts vor der ersten Ueberschrift. */
|
|
78
|
+
const PREAMBLE_NAME = "(Vorspann)";
|
|
79
|
+
|
|
80
|
+
/** Der in `ParsedAst.root` abgelegte Nutzinhalt; nur dieser Adapter sieht hinein. */
|
|
81
|
+
interface ProseAstRoot {
|
|
82
|
+
readonly fileId: string;
|
|
83
|
+
readonly lines: readonly string[];
|
|
84
|
+
readonly index: LineByteIndex;
|
|
85
|
+
readonly sections: readonly ProseSection[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface ProseSection extends MarkdownSectionV1 {
|
|
89
|
+
/** Eindeutiger Name innerhalb des Dokuments (siehe `uniqueName`). */
|
|
90
|
+
readonly qualifiedName: string;
|
|
91
|
+
readonly range: SourceRange;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Physische Zeilen ohne Zeilenende. Ein abschliessendes `\r` faellt weg,
|
|
96
|
+
* damit die Ueberschriften- und Verweiserkennung nicht daran scheitert.
|
|
97
|
+
*/
|
|
98
|
+
function splitLines(content: string): string[] {
|
|
99
|
+
return content.split("\n").map((line) => (line.endsWith("\r") ? line.slice(0, -1) : line));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Zwei Abschnitte koennen denselben Breadcrumb tragen (zweimal dieselbe
|
|
104
|
+
* Ueberschrift unter demselben Elternteil). Der Chunker schluesselt Symbole
|
|
105
|
+
* ueber `qualifiedName` in einer `Map`; ohne Vereindeutigung wuerde der
|
|
106
|
+
* zweite Abschnitt den ersten ueberschreiben und beide dieselbe `symbolId`
|
|
107
|
+
* bekommen. Angehaengt wird deshalb eine laufende Nummer — sichtbar, nicht
|
|
108
|
+
* still.
|
|
109
|
+
*/
|
|
110
|
+
function uniqueName(breadcrumb: string, seen: Map<string, number>): string {
|
|
111
|
+
const base = breadcrumb === "" ? PREAMBLE_NAME : breadcrumb;
|
|
112
|
+
const count = (seen.get(base) ?? 0) + 1;
|
|
113
|
+
seen.set(base, count);
|
|
114
|
+
return count === 1 ? base : `${base} (${String(count)})`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function buildSections(lines: readonly string[], index: LineByteIndex): ProseSection[] {
|
|
118
|
+
const seen = new Map<string, number>();
|
|
119
|
+
return outlineMarkdown(lines).map((section) => ({
|
|
120
|
+
...section,
|
|
121
|
+
qualifiedName: uniqueName(section.breadcrumb, seen),
|
|
122
|
+
range: rangeForLines(index, section.startLine, section.endLine),
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function rootOf(ast: ParsedAst): ProseAstRoot {
|
|
127
|
+
return ast.root as ProseAstRoot;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function sectionContent(root: ProseAstRoot, section: ProseSection): string {
|
|
131
|
+
return root.lines.slice(section.startLine - 1, section.endLine).join("\n");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function headingTextOf(section: ProseSection): string {
|
|
135
|
+
return section.level === 0 ? PREAMBLE_NAME : `${"#".repeat(section.level)} ${section.title}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function symbolOf(root: ProseAstRoot, section: ProseSection): ExtractedSymbol {
|
|
139
|
+
return {
|
|
140
|
+
name: section.level === 0 ? PREAMBLE_NAME : section.title,
|
|
141
|
+
qualifiedName: section.qualifiedName,
|
|
142
|
+
kind: PROSE_SYMBOL_KIND,
|
|
143
|
+
signature: headingTextOf(section),
|
|
144
|
+
// Die "Signatur" eines Abschnitts ist seine Ueberschriftenebene plus
|
|
145
|
+
// Pfad: was ihn im Dokument identifiziert, unabhaengig von seiner Zeile.
|
|
146
|
+
normalizedSignature: `h${String(section.level)} ${section.qualifiedName}`,
|
|
147
|
+
range: section.range,
|
|
148
|
+
exportedNames: [],
|
|
149
|
+
// Formhash: Ebene und Pfad — aendert sich, wenn der Abschnitt umbenannt
|
|
150
|
+
// oder verschoben wird, nicht wenn sein Text sich aendert.
|
|
151
|
+
astHash: sha256Hex(`prose-section ${String(section.level)} ${section.qualifiedName}`),
|
|
152
|
+
// Inhaltshash: der Rohtext des Abschnitts.
|
|
153
|
+
tokenFingerprint: sha256Hex(sectionContent(root, section)),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function createProseAdapter(): LanguageAdapter {
|
|
158
|
+
return {
|
|
159
|
+
languageId: PROSE_LANGUAGE_ID,
|
|
160
|
+
extensions: textFormatExtensions("prose"),
|
|
161
|
+
supportLevel: "text",
|
|
162
|
+
|
|
163
|
+
parse(source: SourceFile): ParseResult {
|
|
164
|
+
const lines = splitLines(source.content);
|
|
165
|
+
const index = buildLineByteIndex(source.content);
|
|
166
|
+
const root: ProseAstRoot = {
|
|
167
|
+
fileId: source.fileId,
|
|
168
|
+
lines,
|
|
169
|
+
index,
|
|
170
|
+
sections: buildSections(lines, index),
|
|
171
|
+
};
|
|
172
|
+
const ast: ParsedAst = {
|
|
173
|
+
languageId: PROSE_LANGUAGE_ID,
|
|
174
|
+
parseQuality: "complete",
|
|
175
|
+
root,
|
|
176
|
+
diagnostics: [],
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
parseQuality: "complete",
|
|
180
|
+
ast,
|
|
181
|
+
diagnostics: [],
|
|
182
|
+
errorNodeCount: 0,
|
|
183
|
+
missingNodeCount: 0,
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
extractChunks(ast: ParsedAst): AstRegion[] {
|
|
188
|
+
const root = rootOf(ast);
|
|
189
|
+
const children: AstRegion[] = root.sections.map((section) => ({
|
|
190
|
+
// Der Vorspann vor der ersten Ueberschrift ist genau das, was
|
|
191
|
+
// `file_preamble` beschreibt; alles Weitere ist ein Prosa-Abschnitt.
|
|
192
|
+
chunkKind: section.level === 0 ? "file_preamble" : "prose_section",
|
|
193
|
+
range: section.range,
|
|
194
|
+
scopeId: `${root.fileId}#${section.qualifiedName}`,
|
|
195
|
+
symbolFqn: section.qualifiedName,
|
|
196
|
+
headerText:
|
|
197
|
+
section.level === 0
|
|
198
|
+
? PREAMBLE_NAME
|
|
199
|
+
: `${"#".repeat(section.level)} ${section.breadcrumb}`,
|
|
200
|
+
// Ein Abschnitt hat keine feineren AST-Grenzen; ist er zu gross,
|
|
201
|
+
// teilt der Chunker ihn an Tokengrenzen in `symbol_fragment`s, die
|
|
202
|
+
// seine `symbolId` erben (spec.md §8.5).
|
|
203
|
+
splittable: false,
|
|
204
|
+
}));
|
|
205
|
+
return [
|
|
206
|
+
{
|
|
207
|
+
chunkKind: "module",
|
|
208
|
+
range: {
|
|
209
|
+
startLine: 1,
|
|
210
|
+
endLine: root.index.lineCount,
|
|
211
|
+
startByte: 0,
|
|
212
|
+
endByte: root.index.totalBytes,
|
|
213
|
+
},
|
|
214
|
+
scopeId: root.fileId,
|
|
215
|
+
splittable: children.length > 0,
|
|
216
|
+
...(children.length > 0 ? { children } : {}),
|
|
217
|
+
},
|
|
218
|
+
];
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
extractSymbols(ast: ParsedAst): ExtractedSymbol[] {
|
|
222
|
+
const root = rootOf(ast);
|
|
223
|
+
return root.sections.map((section) => symbolOf(root, section));
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
extractImports(ast: ParsedAst): RawImport[] {
|
|
227
|
+
const root = rootOf(ast);
|
|
228
|
+
const imports: RawImport[] = [];
|
|
229
|
+
for (const link of findMarkdownLinks(root.lines)) {
|
|
230
|
+
if (classifyLinkTarget(link.target) !== "relative_file") continue;
|
|
231
|
+
imports.push({
|
|
232
|
+
specifier: link.target,
|
|
233
|
+
importKind: "import",
|
|
234
|
+
range: rangeForLines(root.index, link.line, link.line),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
return imports;
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
extractCalls(_ast: ParsedAst): RawCall[] {
|
|
241
|
+
// Prosa hat keine Aufrufe. Eine leere Liste ist hier die vollstaendige
|
|
242
|
+
// Antwort, keine Abstufung.
|
|
243
|
+
return [];
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
computeComplexity(ast: ParsedAst): ComplexityFacts {
|
|
247
|
+
// KEINE `symbolScopes` und KEINE `decisions` — siehe Kopfkommentar.
|
|
248
|
+
// Stuende hier je Abschnitt ein Scope, rechnete jede
|
|
249
|
+
// Code-Metrik-Pipeline anschliessend `cyclomatic = 1` je Ueberschrift
|
|
250
|
+
// und addierte das zur Summe des Repositories. Genau das verhindert
|
|
251
|
+
// diese leere Antwort.
|
|
252
|
+
return {
|
|
253
|
+
symbolScopes: [],
|
|
254
|
+
decisions: [],
|
|
255
|
+
nestingEvents: [],
|
|
256
|
+
operators: [],
|
|
257
|
+
operands: [],
|
|
258
|
+
nodeKinds: [],
|
|
259
|
+
comments: [],
|
|
260
|
+
identifiers: [],
|
|
261
|
+
literals: [],
|
|
262
|
+
parseDiagnostics: ast.diagnostics,
|
|
263
|
+
};
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
tokenizeForHalstead(_ast: ParsedAst): HalsteadTokens {
|
|
267
|
+
return { operators: [], operands: [] };
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zeilenanfaenge als UTF-8-Byte-Versaetze.
|
|
3
|
+
*
|
|
4
|
+
* `SourceRange` (domain `types/common.ts`) ist auf BYTES normativ; die
|
|
5
|
+
* Prosa-Gliederung arbeitet in ZEILEN. Diese Tabelle ist die Uebersetzung.
|
|
6
|
+
* Geschnitten wird ausschliesslich unmittelbar nach `\n` (0x0A) — ein
|
|
7
|
+
* Einzelbyte, nie ein UTF-8-Folgebyte —, damit jede erzeugte Grenze eine
|
|
8
|
+
* gueltige Zeichengrenze ist.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface LineByteIndex {
|
|
12
|
+
/** Byte-Versatz jedes Zeilenanfangs, plus ein Schlusswaechter = Dateigroesse. */
|
|
13
|
+
readonly lineStarts: readonly number[];
|
|
14
|
+
/** Anzahl physischer Zeilen. */
|
|
15
|
+
readonly lineCount: number;
|
|
16
|
+
readonly totalBytes: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function buildLineByteIndex(content: string): LineByteIndex {
|
|
20
|
+
const buffer = Buffer.from(content, "utf8");
|
|
21
|
+
const lineStarts: number[] = [0];
|
|
22
|
+
for (let i = 0; i < buffer.length; i += 1) {
|
|
23
|
+
if (buffer[i] === 0x0a) lineStarts.push(i + 1);
|
|
24
|
+
}
|
|
25
|
+
const lineCount = lineStarts.length;
|
|
26
|
+
lineStarts.push(buffer.length);
|
|
27
|
+
return { lineStarts, lineCount, totalBytes: buffer.length };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Byte-Versatz des Anfangs der 1-basierten Zeile `line`, geklemmt. */
|
|
31
|
+
export function lineStartByte(index: LineByteIndex, line: number): number {
|
|
32
|
+
const clamped = Math.min(Math.max(line, 1), index.lineStarts.length);
|
|
33
|
+
return index.lineStarts[clamped - 1] ?? index.totalBytes;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* `SourceRange` fuer die 1-basierte inklusive Zeilenspanne. `endByte` ist der
|
|
38
|
+
* Anfang der Zeile NACH `endLine`, also sind zwei benachbarte Spannen
|
|
39
|
+
* lueckenlos und ueberlappungsfrei.
|
|
40
|
+
*/
|
|
41
|
+
export function rangeForLines(
|
|
42
|
+
index: LineByteIndex,
|
|
43
|
+
startLine: number,
|
|
44
|
+
endLine: number,
|
|
45
|
+
): { startLine: number; endLine: number; startByte: number; endByte: number } {
|
|
46
|
+
return {
|
|
47
|
+
startLine,
|
|
48
|
+
endLine,
|
|
49
|
+
startByte: lineStartByte(index, startLine),
|
|
50
|
+
endByte: lineStartByte(index, endLine + 1),
|
|
51
|
+
};
|
|
52
|
+
}
|