@backbencher/brain 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/CHANGELOG.md +298 -0
- package/EMBEDDINGS.md +355 -0
- package/LICENSE +21 -0
- package/README.md +415 -2
- package/bin/bb +13 -0
- package/dist/analysis-exclusions-7ZJDXOVZ.js +35 -0
- package/dist/brain-index-health-KY7K552E.js +17 -0
- package/dist/brain-relationship-enrichment-QH7OOHUF.js +558 -0
- package/dist/brain.sql-EIM4WS4D.js +29 -0
- package/dist/chunk-2BSKD7O3.js +40 -0
- package/dist/chunk-2DE27DVC.js +1314 -0
- package/dist/chunk-2RRBMNBQ.js +322 -0
- package/dist/chunk-2RTN2DFU.js +711 -0
- package/dist/chunk-2WXYNLBA.js +29 -0
- package/dist/chunk-3CTFIJJB.js +17 -0
- package/dist/chunk-3LFTSMIV.js +174 -0
- package/dist/chunk-47HKX4AJ.js +930 -0
- package/dist/chunk-4H22TLOT.js +543 -0
- package/dist/chunk-5SD45FLC.js +818 -0
- package/dist/chunk-66A5ZFYA.js +1758 -0
- package/dist/chunk-6AIRWAO2.js +247 -0
- package/dist/chunk-6WNGD3NN.js +196 -0
- package/dist/chunk-7AN7U5IZ.js +371 -0
- package/dist/chunk-BHB7BYYI.js +626 -0
- package/dist/chunk-BQ3OVQ3P.js +125 -0
- package/dist/chunk-CW4XXSNN.js +1479 -0
- package/dist/chunk-D2Q4Y47A.js +53 -0
- package/dist/chunk-DIYAGQJL.js +34 -0
- package/dist/chunk-DYM4FQEE.js +90 -0
- package/dist/chunk-EWMWK7WN.js +75 -0
- package/dist/chunk-FVVQTSIM.js +3427 -0
- package/dist/chunk-FWSL4VG6.js +1290 -0
- package/dist/chunk-GBI7V7KY.js +69 -0
- package/dist/chunk-GEFFO6O2.js +152 -0
- package/dist/chunk-HOWAQXJO.js +236 -0
- package/dist/chunk-HQSPJDHI.js +613 -0
- package/dist/chunk-IFZNR5UJ.js +2863 -0
- package/dist/chunk-J4PMBXQQ.js +336 -0
- package/dist/chunk-KAET47ZL.js +125 -0
- package/dist/chunk-KCDECRJY.js +440 -0
- package/dist/chunk-KLK3PBTO.js +1119 -0
- package/dist/chunk-L5TDYKYK.js +76 -0
- package/dist/chunk-MLKGABMK.js +9 -0
- package/dist/chunk-OWISBAOF.js +61 -0
- package/dist/chunk-PJTNGD3Z.js +6924 -0
- package/dist/chunk-QLK6ED4Q.js +235 -0
- package/dist/chunk-R2GW4F6R.js +19 -0
- package/dist/chunk-RCMTFSEF.js +87 -0
- package/dist/chunk-RH7KC5HU.js +12050 -0
- package/dist/chunk-RM3PY6TG.js +376 -0
- package/dist/chunk-ROMM6KMC.js +433 -0
- package/dist/chunk-SK6YVHFZ.js +211 -0
- package/dist/chunk-SM7RFQRO.js +214 -0
- package/dist/chunk-UFE77L67.js +782 -0
- package/dist/chunk-UGR4QIGS.js +67 -0
- package/dist/chunk-UUNHHX4M.js +13 -0
- package/dist/chunk-V44PGPA6.js +2104 -0
- package/dist/chunk-VL52PL2T.js +71 -0
- package/dist/chunk-VURYFIHW.js +201 -0
- package/dist/chunk-XJKJYIPP.js +7436 -0
- package/dist/chunk-YI6FF2ZR.js +340 -0
- package/dist/cli/index.js +37 -0
- package/dist/config-HZAAYDP3.js +10 -0
- package/dist/content-search-642F7E5V.js +593 -0
- package/dist/database-TCTZDLE5.js +9 -0
- package/dist/doctor-GXCKSJOX.js +395 -0
- package/dist/edit-engine-KM7MPFEC.js +51 -0
- package/dist/engine-42TZFNIZ.js +11 -0
- package/dist/engine-LO6L4JLQ.js +18 -0
- package/dist/fingerprint-XDXFRWO6.js +33 -0
- package/dist/framework-intelligence-DWFCKV44.js +860 -0
- package/dist/freshness-3K6VU5OT.js +174 -0
- package/dist/graph-engine-PL5YA7BA.js +21 -0
- package/dist/graph_request-MM4REP6H.js +350 -0
- package/dist/impact_request-WDE47IZ5.js +68 -0
- package/dist/index-space-IUUN5WYV.js +15 -0
- package/dist/index-status-6BD7UBHR.js +34 -0
- package/dist/index.js +159 -0
- package/dist/instance-FO6QZRLH.js +19 -0
- package/dist/language-detection-DFCAU5DZ.js +11 -0
- package/dist/lsp/server.js +4301 -0
- package/dist/mcp/server.js +132 -0
- package/dist/onboard-DIQZV2NW.js +161 -0
- package/dist/override-companion-pass-XR7MHTP7.js +117 -0
- package/dist/parallel-indexer-4PW3AFXP.js +88 -0
- package/dist/pool-worker.js +1153 -0
- package/dist/project-health-ZS5TS2Z6.js +94 -0
- package/dist/project-index-5SDPHITE.js +57 -0
- package/dist/project-registry-DGZBIZS7.js +355 -0
- package/dist/real-bash-analyzer-SXSV67E2.js +2201 -0
- package/dist/real-c-analyzer-SY7FTZ6W.js +5942 -0
- package/dist/real-clean-analyzer-IGDHHLZK.js +3470 -0
- package/dist/real-clojure-analyzer-4OH7IWLB.js +2818 -0
- package/dist/real-cpp-analyzer-7LTDRJRJ.js +4101 -0
- package/dist/real-csharp-analyzer-KICU3TLH.js +3298 -0
- package/dist/real-css-analyzer-HPU277Q6.js +15 -0
- package/dist/real-dart-analyzer-7LZ5LCMW.js +3944 -0
- package/dist/real-elixir-analyzer-BE3MEVZO.js +2192 -0
- package/dist/real-erlang-analyzer-BZMAKYBK.js +1731 -0
- package/dist/real-fsharp-analyzer-5QLTOV3E.js +2390 -0
- package/dist/real-go-analyzer-POD7MZQR.js +4126 -0
- package/dist/real-graphql-analyzer-MAQRZ6QW.js +1442 -0
- package/dist/real-groovy-analyzer-MEWSUPMJ.js +2285 -0
- package/dist/real-haskell-analyzer-I5L2GR3Y.js +2533 -0
- package/dist/real-hcl-analyzer-DBOPXSWJ.js +725 -0
- package/dist/real-html-analyzer-O63XZLZD.js +1759 -0
- package/dist/real-java-analyzer-CHCW3EKA.js +4677 -0
- package/dist/real-javascript-analyzer-QAAJQYZE.js +14 -0
- package/dist/real-json-analyzer-UGBR7YQN.js +1640 -0
- package/dist/real-julia-analyzer-35Q4GHOZ.js +2085 -0
- package/dist/real-kotlin-analyzer-GRAYCWW2.js +3956 -0
- package/dist/real-lua-analyzer-5BAPDZDF.js +1957 -0
- package/dist/real-makefile-analyzer-YJKAHNAS.js +920 -0
- package/dist/real-markdown-analyzer-UKUQZO4F.js +1215 -0
- package/dist/real-matlab-analyzer-FVIKQZKG.js +480 -0
- package/dist/real-nim-analyzer-M7FAIABG.js +3603 -0
- package/dist/real-objective-c-analyzer-XMYQIGQI.js +1518 -0
- package/dist/real-perl-analyzer-ZLY6M2DZ.js +1865 -0
- package/dist/real-php-analyzer-KI2ZAM7X.js +9368 -0
- package/dist/real-powershell-analyzer-B3T5ZP6U.js +2915 -0
- package/dist/real-protobuf-analyzer-23OZ75XV.js +867 -0
- package/dist/real-python-analyzer-I4TIUB6D.js +4880 -0
- package/dist/real-r-analyzer-FJZJXXS6.js +2596 -0
- package/dist/real-ruby-analyzer-M3UFIVTQ.js +2429 -0
- package/dist/real-rust-analyzer-LVSONPAN.js +3359 -0
- package/dist/real-scala-analyzer-CWPI33Q2.js +3293 -0
- package/dist/real-scss-analyzer-TGRJQ7TH.js +1515 -0
- package/dist/real-solidity-analyzer-4P2VBVWA.js +2608 -0
- package/dist/real-sql-analyzer-J7DYZOZR.js +3840 -0
- package/dist/real-svelte-analyzer-NHEN2SX5.js +2532 -0
- package/dist/real-swift-analyzer-2NSYULWI.js +2311 -0
- package/dist/real-toml-analyzer-L3C66L7Q.js +929 -0
- package/dist/real-typescript-analyzer-FTC6ETRQ.js +14 -0
- package/dist/real-vb-analyzer-ORY7LAQS.js +3145 -0
- package/dist/real-vba-analyzer-JH2TTUFI.js +466 -0
- package/dist/real-vue-analyzer-OO4FUGBV.js +2680 -0
- package/dist/real-xml-analyzer-6CQVR477.js +2405 -0
- package/dist/real-yaml-analyzer-J6MQG3YX.js +3528 -0
- package/dist/real-zig-analyzer-EFKCPJNU.js +2430 -0
- package/dist/regex-search-OPTLKUN5.js +239 -0
- package/dist/rules-I453JTRC.js +152 -0
- package/dist/scoped-path-MJYWJZQX.js +11 -0
- package/dist/setup-show-Y5GB5KXA.js +15 -0
- package/dist/setup-wizard-G5YYR5T6.js +24 -0
- package/dist/symbol-search-KB4MU4SI.js +16 -0
- package/dist/taint-YOTN5X55.js +202 -0
- package/dist/taint-analyzer-N7YLZU3N.js +163 -0
- package/dist/tool-handlers-G4NAGJIH.js +72 -0
- package/dist/tool-registry-BPEJNSZG.js +17 -0
- package/dist/tool-validation-RF675A3C.js +32 -0
- package/dist/type-inference-4Y7WTMFE.js +13 -0
- package/dist/vector-binary-LMY4QGAN.js +19 -0
- package/dist/version-LXGNFO37.js +9 -0
- package/dist/wasm-NMWO3WXY.js +16 -0
- package/docs/EMBEDDINGS.md +132 -0
- package/docs/README.md +178 -0
- package/docs/data/m10-baseline.json +602 -0
- package/docs/data/m10-benchmark-baseline.json +57 -0
- package/docs/data/m10-benchmark-last-run.json +127 -0
- package/docs/data/m10-final-audit.json +215 -0
- package/docs/data/m12-final-audit.json +138 -0
- package/docs/data/m12-surface-matrix.json +50 -0
- package/docs/data/public-tools.json +1902 -0
- package/docs/indexing/DEAD-ASSETS.md +88 -0
- package/docs/indexing/INDEXER-REVIEW.md +634 -0
- package/docs/indexing/PERFORMANCE-FINDINGS.md +106 -0
- package/docs/indexing/README.md +427 -0
- package/docs/indexing/discovery-matrix.md +41 -0
- package/docs/indexing/embeddings.md +325 -0
- package/docs/indexing/environment-variables.md +77 -0
- package/docs/indexing/performance.md +323 -0
- package/docs/indexing/resume.md +345 -0
- package/docs/indexing/troubleshooting.md +391 -0
- package/docs/man/bb.1 +190 -0
- package/docs/tools/bb_analyze.md +147 -0
- package/docs/tools/bb_annotate.md +110 -0
- package/docs/tools/bb_annotations.md +106 -0
- package/docs/tools/bb_ask.md +101 -0
- package/docs/tools/bb_cross_language.md +103 -0
- package/docs/tools/bb_doc.md +169 -0
- package/docs/tools/bb_edit.md +185 -0
- package/docs/tools/bb_graph.md +169 -0
- package/docs/tools/bb_health.md +156 -0
- package/docs/tools/bb_impact.md +117 -0
- package/docs/tools/bb_index.md +108 -0
- package/docs/tools/bb_migrate.md +135 -0
- package/docs/tools/bb_patterns.md +140 -0
- package/docs/tools/bb_search.md +150 -0
- package/docs/tools/bb_security.md +100 -0
- package/docs/tools/bb_visualize.md +184 -0
- package/grammars/README.md +57 -0
- package/grammars/THIRD-PARTY-NOTICES.md +50 -0
- package/grammars/tree-sitter-c/LICENSE +21 -0
- package/grammars/tree-sitter-clojure/LICENSE.md +21 -0
- package/grammars/tree-sitter-cpp/LICENSE +21 -0
- package/grammars/tree-sitter-csharp/LICENSE +21 -0
- package/grammars/tree-sitter-css/LICENSE +21 -0
- package/grammars/tree-sitter-css/README.md +21 -0
- package/grammars/tree-sitter-dart/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/LICENSE +20 -0
- package/grammars/tree-sitter-dart-upstream/README.md +18 -0
- package/grammars/tree-sitter-elixir/LICENSE +176 -0
- package/grammars/tree-sitter-elixir/README.md +11 -0
- package/grammars/tree-sitter-fsharp/LICENSE +21 -0
- package/grammars/tree-sitter-fsharp/README.md +45 -0
- package/grammars/tree-sitter-graphql/LICENSE +21 -0
- package/grammars/tree-sitter-graphql/README.md +106 -0
- package/grammars/tree-sitter-groovy/LICENSE +21 -0
- package/grammars/tree-sitter-groovy/README.md +4 -0
- package/grammars/tree-sitter-haskell/LICENSE +21 -0
- package/grammars/tree-sitter-haskell/README.md +394 -0
- package/grammars/tree-sitter-hcl/CHANGELOG.md +102 -0
- package/grammars/tree-sitter-hcl/LICENSE +201 -0
- package/grammars/tree-sitter-hcl/README.md +39 -0
- package/grammars/tree-sitter-html/LICENSE +21 -0
- package/grammars/tree-sitter-html/README.md +21 -0
- package/grammars/tree-sitter-julia/LICENSE +21 -0
- package/grammars/tree-sitter-julia/README.md +24 -0
- package/grammars/tree-sitter-kotlin/LICENSE +9 -0
- package/grammars/tree-sitter-lua/LICENSE.md +21 -0
- package/grammars/tree-sitter-lua/README.md +29 -0
- package/grammars/tree-sitter-make/LICENSE +21 -0
- package/grammars/tree-sitter-matlab/LICENSE +19 -0
- package/grammars/tree-sitter-matlab/README.md +99 -0
- package/grammars/tree-sitter-nim/LICENSE +373 -0
- package/grammars/tree-sitter-nim/README.md +46 -0
- package/grammars/tree-sitter-objc/LICENSE +21 -0
- package/grammars/tree-sitter-objc/README.md +20 -0
- package/grammars/tree-sitter-perl/LICENSE +7 -0
- package/grammars/tree-sitter-perl/README.md +100 -0
- package/grammars/tree-sitter-powershell/LICENSE +21 -0
- package/grammars/tree-sitter-powershell/README.md +7 -0
- package/grammars/tree-sitter-proto/LICENSE +21 -0
- package/grammars/tree-sitter-proto/README.md +105 -0
- package/grammars/tree-sitter-r/LICENSE +9 -0
- package/grammars/tree-sitter-r/README.md +66 -0
- package/grammars/tree-sitter-ruby/LICENSE +22 -0
- package/grammars/tree-sitter-scss/LICENSE +21 -0
- package/grammars/tree-sitter-scss/README.md +17 -0
- package/grammars/tree-sitter-solidity/LICENSE +7 -0
- package/grammars/tree-sitter-sql/LICENSE +21 -0
- package/grammars/tree-sitter-typescript/LICENSE +21 -0
- package/grammars/tree-sitter-vba/LICENSE +21 -0
- package/grammars/tree-sitter-vba/README.md +738 -0
- package/grammars/tree-sitter-vbnet/LICENSE +21 -0
- package/grammars/tree-sitter-vbnet/README.md +322 -0
- package/grammars/tree-sitter-xml/LICENSE +19 -0
- package/grammars/tree-sitter-yaml/LICENSE +20 -0
- package/grammars/tree-sitter-yaml/README.md +21 -0
- package/package.json +184 -4
- package/wasm/dart.wasm +0 -0
- package/wasm/tree-sitter-bash.wasm +0 -0
- package/wasm/tree-sitter-c.wasm +0 -0
- package/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/wasm/tree-sitter-clean.wasm +0 -0
- package/wasm/tree-sitter-clojure.wasm +0 -0
- package/wasm/tree-sitter-core_schema.wasm +0 -0
- package/wasm/tree-sitter-cpp.wasm +0 -0
- package/wasm/tree-sitter-css.wasm +0 -0
- package/wasm/tree-sitter-dart.wasm +0 -0
- package/wasm/tree-sitter-elisp.wasm +0 -0
- package/wasm/tree-sitter-elixir.wasm +0 -0
- package/wasm/tree-sitter-elm.wasm +0 -0
- package/wasm/tree-sitter-embedded_template.wasm +0 -0
- package/wasm/tree-sitter-erlang.wasm +0 -0
- package/wasm/tree-sitter-fsharp.wasm +0 -0
- package/wasm/tree-sitter-fsharp_signature.wasm +0 -0
- package/wasm/tree-sitter-go.wasm +0 -0
- package/wasm/tree-sitter-graphql.wasm +0 -0
- package/wasm/tree-sitter-groovy.wasm +0 -0
- package/wasm/tree-sitter-haskell.wasm +0 -0
- package/wasm/tree-sitter-hcl.wasm +0 -0
- package/wasm/tree-sitter-html.wasm +0 -0
- package/wasm/tree-sitter-java.wasm +0 -0
- package/wasm/tree-sitter-javascript.wasm +0 -0
- package/wasm/tree-sitter-json.wasm +0 -0
- package/wasm/tree-sitter-json_schema.wasm +0 -0
- package/wasm/tree-sitter-julia.wasm +0 -0
- package/wasm/tree-sitter-kotlin.wasm +0 -0
- package/wasm/tree-sitter-lua.wasm +0 -0
- package/wasm/tree-sitter-make.wasm +0 -0
- package/wasm/tree-sitter-markdown.wasm +0 -0
- package/wasm/tree-sitter-markdown_inline.wasm +0 -0
- package/wasm/tree-sitter-matlab.wasm +0 -0
- package/wasm/tree-sitter-nim.wasm +0 -0
- package/wasm/tree-sitter-objc.wasm +0 -0
- package/wasm/tree-sitter-ocaml.wasm +0 -0
- package/wasm/tree-sitter-perl.wasm +0 -0
- package/wasm/tree-sitter-php.wasm +0 -0
- package/wasm/tree-sitter-php_only.wasm +0 -0
- package/wasm/tree-sitter-powershell.wasm +0 -0
- package/wasm/tree-sitter-protobuf.wasm +0 -0
- package/wasm/tree-sitter-python.wasm +0 -0
- package/wasm/tree-sitter-ql.wasm +0 -0
- package/wasm/tree-sitter-r.wasm +0 -0
- package/wasm/tree-sitter-rescript.wasm +0 -0
- package/wasm/tree-sitter-ruby.wasm +0 -0
- package/wasm/tree-sitter-rust.wasm +0 -0
- package/wasm/tree-sitter-scala.wasm +0 -0
- package/wasm/tree-sitter-scss.wasm +0 -0
- package/wasm/tree-sitter-solidity.wasm +0 -0
- package/wasm/tree-sitter-sql.wasm +0 -0
- package/wasm/tree-sitter-svelte.wasm +0 -0
- package/wasm/tree-sitter-swift.wasm +0 -0
- package/wasm/tree-sitter-systemrdl.wasm +0 -0
- package/wasm/tree-sitter-terraform.wasm +0 -0
- package/wasm/tree-sitter-tlaplus.wasm +0 -0
- package/wasm/tree-sitter-toml.wasm +0 -0
- package/wasm/tree-sitter-tsx.wasm +0 -0
- package/wasm/tree-sitter-typescript.wasm +0 -0
- package/wasm/tree-sitter-vba.wasm +0 -0
- package/wasm/tree-sitter-vbnet.wasm +0 -0
- package/wasm/tree-sitter-vue.wasm +0 -0
- package/wasm/tree-sitter-xml.wasm +0 -0
- package/wasm/tree-sitter-yaml.wasm +0 -0
- package/wasm/tree-sitter-zig.wasm +0 -0
- package/wasm/tree-sitter.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ASTEngine
|
|
3
|
+
} from "./chunk-V44PGPA6.js";
|
|
4
|
+
import "./chunk-BQ3OVQ3P.js";
|
|
5
|
+
import "./chunk-SK6YVHFZ.js";
|
|
6
|
+
import "./chunk-2BSKD7O3.js";
|
|
7
|
+
import "./chunk-KAET47ZL.js";
|
|
8
|
+
import "./chunk-KCDECRJY.js";
|
|
9
|
+
import "./chunk-MLKGABMK.js";
|
|
10
|
+
|
|
11
|
+
// src/ast/real-matlab-analyzer.ts
|
|
12
|
+
var { SymbolKind, RelationshipType } = ASTEngine;
|
|
13
|
+
var DECLARATIONS = /* @__PURE__ */ new Map([
|
|
14
|
+
["function_definition", SymbolKind.Function],
|
|
15
|
+
["class_definition", SymbolKind.Class],
|
|
16
|
+
["property", SymbolKind.Property],
|
|
17
|
+
["enum", SymbolKind.EnumMember]
|
|
18
|
+
]);
|
|
19
|
+
var RealMatlabAnalyzer = class {
|
|
20
|
+
symbols = [];
|
|
21
|
+
relationships = [];
|
|
22
|
+
declarations = /* @__PURE__ */ new Map();
|
|
23
|
+
nodeSymbols = /* @__PURE__ */ new Map();
|
|
24
|
+
emitted = /* @__PURE__ */ new Set();
|
|
25
|
+
/** Class names declared in THIS file, folded -> as written. Object construction is a
|
|
26
|
+
* same-file fact here, and so is the extra-superclass half of `&`. */
|
|
27
|
+
classNames = /* @__PURE__ */ new Map();
|
|
28
|
+
/** The file's `+pkg/` package and its module name, derived from the path. MATLAB has no
|
|
29
|
+
* textual namespace or module construct: `+pkg/` FOLDERS are the namespace mechanism, so
|
|
30
|
+
* the path the engine hands the analyzer is the only place that fact exists. */
|
|
31
|
+
moduleName = "";
|
|
32
|
+
packageName = "";
|
|
33
|
+
analyze(rootNode, _content, filePath, context) {
|
|
34
|
+
this.symbols = [];
|
|
35
|
+
this.relationships = [];
|
|
36
|
+
this.declarations.clear();
|
|
37
|
+
this.nodeSymbols.clear();
|
|
38
|
+
this.emitted.clear();
|
|
39
|
+
this.classNames.clear();
|
|
40
|
+
this.packageName = this.packageFromPath(filePath);
|
|
41
|
+
this.moduleName = this.moduleNameFromPath(filePath, this.packageName);
|
|
42
|
+
const declarations = [];
|
|
43
|
+
this.collectDeclarations(rootNode, declarations);
|
|
44
|
+
for (const declaration of declarations) this.publish(declaration);
|
|
45
|
+
this.walk(rootNode);
|
|
46
|
+
this.emitFileScopeRelationships(declarations, context);
|
|
47
|
+
return {
|
|
48
|
+
symbols: this.symbols,
|
|
49
|
+
relationships: this.relationships,
|
|
50
|
+
imports: [],
|
|
51
|
+
metadata: {
|
|
52
|
+
analysisVersion: "m1-matlab-2",
|
|
53
|
+
hasTypeInference: false,
|
|
54
|
+
hasFrameworkIntelligence: false,
|
|
55
|
+
matlabGaps: {
|
|
56
|
+
packageNamespace: "`+pkg/` namespace membership is a FOLDER fact, derived from the file path; the grammar has no namespace or module node",
|
|
57
|
+
overrides: "an override is a method-name shadow of a base member; a base outside this file is visible only through the companion index, and an unverifiable base publishes no row",
|
|
58
|
+
overloads: "Function/index ambiguity is retained as inferred calls",
|
|
59
|
+
scripts: "Script-local variables have no declaration construct in the grammar"
|
|
60
|
+
},
|
|
61
|
+
linesOfCode: this.lineCount(_content)
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
collectDeclarations(node, out) {
|
|
66
|
+
const kind = DECLARATIONS.get(node.type);
|
|
67
|
+
if (kind) {
|
|
68
|
+
const name = node.childForFieldName("name") ?? this.firstIdentifier(node);
|
|
69
|
+
if (name) {
|
|
70
|
+
let declarationKind = kind;
|
|
71
|
+
if (kind === SymbolKind.Function && node.parent?.type === "methods") declarationKind = SymbolKind.Method;
|
|
72
|
+
if (kind === SymbolKind.Function && this.enclosingClassName(node) === name.text) {
|
|
73
|
+
declarationKind = SymbolKind.Constructor;
|
|
74
|
+
}
|
|
75
|
+
out.push({ node, name, kind: declarationKind });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (node.type === "events") {
|
|
79
|
+
for (const child of node.namedChildren) {
|
|
80
|
+
if (child?.type === "identifier") out.push({ node: child, name: child, kind: SymbolKind.Event });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const child of node.namedChildren) if (child) this.collectDeclarations(child, out);
|
|
84
|
+
}
|
|
85
|
+
publish(declaration) {
|
|
86
|
+
const name = declaration.name.text;
|
|
87
|
+
if (!name) return;
|
|
88
|
+
const symbol = {
|
|
89
|
+
name,
|
|
90
|
+
qualifiedName: name,
|
|
91
|
+
kind: declaration.kind,
|
|
92
|
+
range: this.range(declaration.node),
|
|
93
|
+
visibility: this.visibility(declaration.node),
|
|
94
|
+
parameters: this.parameters(declaration.node),
|
|
95
|
+
metadata: {
|
|
96
|
+
language: "matlab",
|
|
97
|
+
grammarNode: declaration.node.type,
|
|
98
|
+
...this.attributes(declaration.node).length > 0 ? { attributes: this.attributes(declaration.node) } : {}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
this.symbols.push(symbol);
|
|
102
|
+
this.nodeSymbols.set(declaration.node.startIndex, symbol);
|
|
103
|
+
if (!this.declarations.has(this.fold(name))) this.declarations.set(this.fold(name), symbol);
|
|
104
|
+
if (declaration.kind === SymbolKind.Class) this.classNames.set(this.fold(name), name);
|
|
105
|
+
}
|
|
106
|
+
walk(node, owner) {
|
|
107
|
+
const declaration = this.nodeSymbols.get(node.startIndex);
|
|
108
|
+
const active = declaration ?? owner;
|
|
109
|
+
if (declaration && owner && declaration !== owner) {
|
|
110
|
+
const name = node.childForFieldName("name") ?? this.firstIdentifier(node);
|
|
111
|
+
if (name) {
|
|
112
|
+
this.emit(RelationshipType.Contains, owner.name, declaration.name, name, 1);
|
|
113
|
+
declaration.ownerName = owner.qualifiedName ?? owner.name;
|
|
114
|
+
declaration.ownerKind = owner.kind;
|
|
115
|
+
declaration.qualifiedName = `${declaration.ownerName}.${declaration.name}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (declaration?.kind === SymbolKind.Class) {
|
|
119
|
+
const supers = node.namedChildren.find((child) => child?.type === "superclasses") ?? null;
|
|
120
|
+
const bases = supers ? supers.namedChildren.filter((child) => !!child && child.type === "property_name") : [];
|
|
121
|
+
bases.forEach((base, index) => {
|
|
122
|
+
const target = this.dottedText(base);
|
|
123
|
+
if (target === "") return;
|
|
124
|
+
if (index === 0) {
|
|
125
|
+
this.emit(RelationshipType.Extends, declaration.name, target, base, this.confidence(target));
|
|
126
|
+
} else {
|
|
127
|
+
this.emit(RelationshipType.Implements, declaration.name, target, base, this.confidence(target), { construct: "additional_superclass" });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
if (node.type === "function_call") {
|
|
132
|
+
const target = node.childForFieldName("name") ?? this.firstIdentifier(node);
|
|
133
|
+
if (target) this.emitCallee(node, target, active?.name ?? "root");
|
|
134
|
+
} else if (node.type === "field_expression") {
|
|
135
|
+
const object = node.childForFieldName("object");
|
|
136
|
+
const field = node.childForFieldName("field");
|
|
137
|
+
if (object && field && active) {
|
|
138
|
+
this.emit(RelationshipType.Uses, active.name, object.text, object, this.confidence(object.text), { construct: "field_receiver", field: field.text });
|
|
139
|
+
this.emit(RelationshipType.Uses, active.name, field.text, field, this.confidence(field.text), { construct: "field_member", receiver: object.text });
|
|
140
|
+
}
|
|
141
|
+
} else if (node.type === "command") {
|
|
142
|
+
this.emitImportCommand(node, active);
|
|
143
|
+
} else if (node.type === "handle_operator" || node.type === "metaclass_operator") {
|
|
144
|
+
const target = this.dottedText(node);
|
|
145
|
+
if (this.isIdentifierPath(target)) {
|
|
146
|
+
const construct = node.type === "handle_operator" ? "function_handle" : "metaclass_object";
|
|
147
|
+
this.emit(RelationshipType.References, active?.name ?? "root", target, node, this.confidence(target), { construct });
|
|
148
|
+
}
|
|
149
|
+
} else if (node.type === "superclass") {
|
|
150
|
+
const target = this.dottedText(node);
|
|
151
|
+
if (this.isIdentifierPath(target)) {
|
|
152
|
+
this.emit(RelationshipType.References, active?.name ?? "root", target, node, this.confidence(target), { construct: "superclass_method_call" });
|
|
153
|
+
}
|
|
154
|
+
} else if (node.type === "assignment") {
|
|
155
|
+
this.emitReads(node.childForFieldName("right"), active);
|
|
156
|
+
} else if (node.type === "identifier") {
|
|
157
|
+
this.emitIdentifierRead(node, active);
|
|
158
|
+
}
|
|
159
|
+
for (const child of node.namedChildren) if (child) this.walk(child, active);
|
|
160
|
+
}
|
|
161
|
+
emitReads(node, owner) {
|
|
162
|
+
if (!node) return;
|
|
163
|
+
if (node.type === "function_call") {
|
|
164
|
+
const target = node.childForFieldName("name") ?? this.firstIdentifier(node);
|
|
165
|
+
if (target) this.emitCallee(node, target, owner?.name ?? "root");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (node.type === "field_expression") {
|
|
169
|
+
const object = node.childForFieldName("object");
|
|
170
|
+
const field = node.childForFieldName("field");
|
|
171
|
+
if (object && field && owner) {
|
|
172
|
+
this.emit(RelationshipType.Uses, owner.name, object.text, object, this.confidence(object.text), { construct: "field_receiver", field: field.text });
|
|
173
|
+
this.emit(RelationshipType.Uses, owner.name, field.text, field, this.confidence(field.text), { construct: "field_member", receiver: object.text });
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
for (const child of node.namedChildren) if (child) this.emitReads(child, owner);
|
|
178
|
+
}
|
|
179
|
+
emitIdentifierRead(node, owner) {
|
|
180
|
+
if (!owner || this.isDeclarationName(node)) return;
|
|
181
|
+
const parent = node.parent;
|
|
182
|
+
if (!parent || parent.type === "function_arguments") return;
|
|
183
|
+
if (parent.type === "superclasses" || parent.parent?.type === "superclasses") return;
|
|
184
|
+
if (parent.type === "handle_operator" || parent.type === "metaclass_operator" || parent.type === "superclass") return;
|
|
185
|
+
if (this.isClassMetadata(node)) return;
|
|
186
|
+
if (parent.type === "assignment" && parent.childForFieldName("left")?.startIndex === node.startIndex) return;
|
|
187
|
+
if (parent.type === "function_call" && parent.childForFieldName("name")?.startIndex === node.startIndex) return;
|
|
188
|
+
if (parent.type === "field_expression") return;
|
|
189
|
+
this.emit(RelationshipType.Uses, owner.name, node.text, node, this.confidence(node.text));
|
|
190
|
+
}
|
|
191
|
+
isDeclarationName(node) {
|
|
192
|
+
if (!node.parent) return false;
|
|
193
|
+
if (node.parent.type === "events") return true;
|
|
194
|
+
if (node.parent.type === "enum") return true;
|
|
195
|
+
return ["function_definition", "class_definition", "property"].includes(node.parent.type) && node.parent.childForFieldName("name")?.startIndex === node.startIndex;
|
|
196
|
+
}
|
|
197
|
+
isClassMetadata(node) {
|
|
198
|
+
let parent = node.parent;
|
|
199
|
+
while (parent) {
|
|
200
|
+
if (parent.type === "attributes" || parent.type === "attribute") return true;
|
|
201
|
+
if (["function_definition", "class_definition", "property", "events", "enum"].includes(parent.type)) return false;
|
|
202
|
+
parent = parent.parent;
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
attributes(node) {
|
|
207
|
+
const sources = [node, node.parent].filter((candidate) => !!candidate);
|
|
208
|
+
return sources.flatMap((source) => {
|
|
209
|
+
const attributes = source.namedChildren.find((child) => child?.type === "attributes");
|
|
210
|
+
if (!attributes) return [];
|
|
211
|
+
return attributes.namedChildren.filter((child) => !!child && child.type === "attribute").map((attribute) => attribute.text);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
visibility(node) {
|
|
215
|
+
const attributes = this.attributes(node).map((attribute) => attribute.toLowerCase());
|
|
216
|
+
if (attributes.some((attribute) => attribute.includes("private"))) return "private";
|
|
217
|
+
if (attributes.some((attribute) => attribute.includes("protected"))) return "protected";
|
|
218
|
+
return "public";
|
|
219
|
+
}
|
|
220
|
+
parameters(node) {
|
|
221
|
+
const args = node.namedChildren.find((child) => child?.type === "function_arguments") ?? null;
|
|
222
|
+
if (!args) return void 0;
|
|
223
|
+
return args.namedChildren.flatMap((child) => child && child.type === "identifier" ? [{ name: child.text }] : []);
|
|
224
|
+
}
|
|
225
|
+
identifiers(node) {
|
|
226
|
+
if (!node) return [];
|
|
227
|
+
if (node.type === "identifier") return [node];
|
|
228
|
+
return node.namedChildren.flatMap((child) => child ? this.identifiers(child) : []);
|
|
229
|
+
}
|
|
230
|
+
firstIdentifier(node) {
|
|
231
|
+
return this.identifiers(node)[0] ?? null;
|
|
232
|
+
}
|
|
233
|
+
enclosingClassName(node) {
|
|
234
|
+
let parent = node.parent;
|
|
235
|
+
while (parent) {
|
|
236
|
+
if (parent.type === "class_definition") {
|
|
237
|
+
const name = parent.childForFieldName("name") ?? this.firstIdentifier(parent);
|
|
238
|
+
return name?.text ?? null;
|
|
239
|
+
}
|
|
240
|
+
parent = parent.parent;
|
|
241
|
+
}
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
emitCallee(_call, target, source) {
|
|
245
|
+
const name = target.type === "identifier" ? target.text : "";
|
|
246
|
+
if (name !== "" && this.classNames.has(this.fold(name))) {
|
|
247
|
+
this.emit(RelationshipType.Instantiates, source, name, target, this.confidence(name), { construct: "class_constructor_call" });
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
this.emit(RelationshipType.Calls, source, target.text, target, this.confidence(target.text));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* `import` is a COMMAND statement, not a call: the grammar gives it `command_name` +
|
|
254
|
+
* `command_argument` external tokens. Only the `import` command is a name-resolution
|
|
255
|
+
* directive; every other command (`clear all`, `hold on`, …) is left alone here because a
|
|
256
|
+
* command is not a module import.
|
|
257
|
+
*
|
|
258
|
+
* The argument is published only when it is a SYMBOL-SHAPED path: `mypkg.f` (qualified
|
|
259
|
+
* name), `mypkg` (bare name) and `mypkg.*` (the package, which is what the wildcard makes
|
|
260
|
+
* reachable — the raw `mypkg.*` spelling is a wildcard, never a symbol, so it is never the
|
|
261
|
+
* target). A header path such as `<Foundation/Foundation.h>` is not identifier-shaped and
|
|
262
|
+
* publishes nothing.
|
|
263
|
+
*/
|
|
264
|
+
emitImportCommand(node, owner) {
|
|
265
|
+
const nameNode = node.namedChildren.find((child) => child?.type === "command_name") ?? null;
|
|
266
|
+
if ((nameNode?.text ?? "").trim() !== "import") return;
|
|
267
|
+
const source = owner?.name ?? "root";
|
|
268
|
+
for (const child of node.namedChildren) {
|
|
269
|
+
if (!child || child.type !== "command_argument") continue;
|
|
270
|
+
const argument = child.text.trim();
|
|
271
|
+
if (argument.length === 0) continue;
|
|
272
|
+
const wildcard = argument.endsWith(".*");
|
|
273
|
+
const target = wildcard ? argument.slice(0, argument.length - 2) : argument;
|
|
274
|
+
if (!this.isIdentifierPath(target)) continue;
|
|
275
|
+
let importForm = "name";
|
|
276
|
+
if (wildcard) importForm = "package_wildcard";
|
|
277
|
+
else if (target.includes(".")) importForm = "qualified_name";
|
|
278
|
+
this.emit(RelationshipType.Imports, source, target, child, this.confidence(target), { importForm });
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/** File-scoped facts that need the whole declaration list: overrides, exports and the
|
|
282
|
+
* folder-namespace `part_of`. */
|
|
283
|
+
emitFileScopeRelationships(declarations, context) {
|
|
284
|
+
this.emitOverrides(declarations, context);
|
|
285
|
+
this.emitModuleMembership(declarations);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* A MATLAB override is a METHOD that redeclares a member of a superclass. MATLAB allows one
|
|
289
|
+
* `classdef` per file, so the base is usually in ANOTHER file and the analyzer can only see
|
|
290
|
+
* it through `context.overrideCompanion` (the same companion the other file-scoped analyzers
|
|
291
|
+
* read). A base declared in THIS file is provable directly. An unverifiable base publishes
|
|
292
|
+
* nothing: guessing would invent an override the file cannot show.
|
|
293
|
+
*/
|
|
294
|
+
emitOverrides(declarations, context) {
|
|
295
|
+
const classes = /* @__PURE__ */ new Map();
|
|
296
|
+
for (const declaration of declarations) {
|
|
297
|
+
if (declaration.kind !== SymbolKind.Class) continue;
|
|
298
|
+
classes.set(this.fold(declaration.name.text), { display: declaration.name.text, node: declaration.node, methods: /* @__PURE__ */ new Map() });
|
|
299
|
+
}
|
|
300
|
+
if (classes.size === 0) return;
|
|
301
|
+
for (const declaration of declarations) {
|
|
302
|
+
if (declaration.kind !== SymbolKind.Method) continue;
|
|
303
|
+
const ownerName = this.enclosingClassName(declaration.node);
|
|
304
|
+
const owner = ownerName ? classes.get(this.fold(ownerName)) : void 0;
|
|
305
|
+
if (!owner) continue;
|
|
306
|
+
owner.methods.set(this.fold(declaration.name.text), { name: declaration.name.text, node: declaration.node });
|
|
307
|
+
}
|
|
308
|
+
const companion = context?.overrideCompanion;
|
|
309
|
+
for (const entry of classes.values()) {
|
|
310
|
+
const supers = entry.node.namedChildren.find((child) => child?.type === "superclasses") ?? null;
|
|
311
|
+
if (!supers) continue;
|
|
312
|
+
for (const base of supers.namedChildren) {
|
|
313
|
+
if (!base || base.type !== "property_name") continue;
|
|
314
|
+
const baseName = this.dottedText(base);
|
|
315
|
+
if (baseName === "") continue;
|
|
316
|
+
const sameFile = classes.get(this.fold(baseName));
|
|
317
|
+
const baseMethods = sameFile ? new Set(sameFile.methods.keys()) : this.companionMethodsFor(companion, baseName);
|
|
318
|
+
if (baseMethods.size === 0) continue;
|
|
319
|
+
for (const method of entry.methods.values()) {
|
|
320
|
+
if (!baseMethods.has(this.fold(method.name))) continue;
|
|
321
|
+
this.emit(RelationshipType.Overrides, entry.display, method.name, method.node, 1, {
|
|
322
|
+
overridingMember: `${entry.display}.${method.name}`,
|
|
323
|
+
overriddenMember: `${baseName}.${method.name}`,
|
|
324
|
+
overriddenClass: baseName,
|
|
325
|
+
reasonCode: sameFile ? "base_class_declared_in_same_file" : "companion_index"
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* THE FILE IS MATLAB'S MODULE, and `+pkg/` FOLDERS are its namespace — neither fact has a
|
|
333
|
+
* textual construct, so both are read from the path the engine hands the analyzer.
|
|
334
|
+
*
|
|
335
|
+
* exports the file exports its primary (first, top-level) declaration under the module's
|
|
336
|
+
* name. When the module and that declaration share one spelling — the ordinary
|
|
337
|
+
* `foo.m`/`foo` identity — the row would be X -> X and carries no information, so
|
|
338
|
+
* it is withheld rather than published as noise.
|
|
339
|
+
* part_of a declaration in a `+pkg/` file is a part of that folder's package. The package
|
|
340
|
+
* is a folder-based namespace with no textual inclusion, which is why the row's
|
|
341
|
+
* `partRole` is `part` (this declaration is a part of the package).
|
|
342
|
+
*/
|
|
343
|
+
emitModuleMembership(declarations) {
|
|
344
|
+
const topLevel = declarations.filter((declaration) => this.isTopLevelDeclaration(declaration.node));
|
|
345
|
+
if (topLevel.length === 0) return;
|
|
346
|
+
const primary = topLevel[0];
|
|
347
|
+
if (this.moduleName !== "" && this.moduleName !== primary.name.text) {
|
|
348
|
+
this.emit(RelationshipType.Exports, this.moduleName, primary.name.text, primary.name, 1, {
|
|
349
|
+
exportForm: this.packageName !== "" ? "package_qualified_module" : "file_module"
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (this.packageName === "") return;
|
|
353
|
+
for (const declaration of topLevel) {
|
|
354
|
+
this.emit(RelationshipType.PartOf, declaration.name.text, this.packageName, declaration.name, 1, {
|
|
355
|
+
partRole: "part",
|
|
356
|
+
packagePath: this.packageName,
|
|
357
|
+
construct: "package_folder_membership"
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/** A declaration is top-level when no enclosing declaration owns it: a method of a class,
|
|
362
|
+
* a nested function and a local function are all owned, so none of them is exported. */
|
|
363
|
+
isTopLevelDeclaration(node) {
|
|
364
|
+
let parent = node.parent;
|
|
365
|
+
while (parent) {
|
|
366
|
+
if (parent.type === "function_definition" || parent.type === "class_definition") return false;
|
|
367
|
+
parent = parent.parent;
|
|
368
|
+
}
|
|
369
|
+
return true;
|
|
370
|
+
}
|
|
371
|
+
companionMethodsFor(companion, baseName) {
|
|
372
|
+
const folded = /* @__PURE__ */ new Set();
|
|
373
|
+
if (!companion) return folded;
|
|
374
|
+
const leaf = baseName.includes(".") ? baseName.slice(baseName.lastIndexOf(".") + 1) : baseName;
|
|
375
|
+
for (const key of [baseName, leaf]) {
|
|
376
|
+
const members = companion.get(key);
|
|
377
|
+
if (!members) continue;
|
|
378
|
+
for (const member of members) folded.add(this.fold(member));
|
|
379
|
+
}
|
|
380
|
+
return folded;
|
|
381
|
+
}
|
|
382
|
+
/** The dotted text of a `property_name` / `handle_operator` / `metaclass_operator` /
|
|
383
|
+
* `superclass` node — its identifiers joined with dots, so `pkg.f` is ONE target. */
|
|
384
|
+
dottedText(node) {
|
|
385
|
+
return this.identifiers(node).map((identifier) => identifier.text).join(".");
|
|
386
|
+
}
|
|
387
|
+
/** Is `text` a dotted sequence of identifier segments? Character-class test only: a name may
|
|
388
|
+
* not be a path, a wildcard or a bracketed header. No regular expression is used anywhere in
|
|
389
|
+
* this analyzer. */
|
|
390
|
+
isIdentifierPath(text) {
|
|
391
|
+
if (text.length === 0) return false;
|
|
392
|
+
let start = 0;
|
|
393
|
+
for (let i = 0; i <= text.length; i++) {
|
|
394
|
+
if (i !== text.length && text[i] !== ".") continue;
|
|
395
|
+
if (i === start) return false;
|
|
396
|
+
if (!this.isIdentifierSegment(text.slice(start, i))) return false;
|
|
397
|
+
start = i + 1;
|
|
398
|
+
}
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
isIdentifierSegment(segment) {
|
|
402
|
+
if (segment.length === 0) return false;
|
|
403
|
+
const first = segment.charCodeAt(0);
|
|
404
|
+
const firstOk = first >= 65 && first <= 90 || first >= 97 && first <= 122 || first === 95;
|
|
405
|
+
if (!firstOk) return false;
|
|
406
|
+
for (let i = 1; i < segment.length; i++) {
|
|
407
|
+
const code = segment.charCodeAt(i);
|
|
408
|
+
const ok = code >= 65 && code <= 90 || code >= 97 && code <= 122 || code >= 48 && code <= 57 || code === 95;
|
|
409
|
+
if (!ok) return false;
|
|
410
|
+
}
|
|
411
|
+
return true;
|
|
412
|
+
}
|
|
413
|
+
/** Path segments, split on both separators so the analyzer is host-independent. */
|
|
414
|
+
splitPath(filePath) {
|
|
415
|
+
const out = [];
|
|
416
|
+
let start = 0;
|
|
417
|
+
for (let i = 0; i <= filePath.length; i++) {
|
|
418
|
+
if (i !== filePath.length && filePath[i] !== "/" && filePath[i] !== "\\") continue;
|
|
419
|
+
if (i > start) out.push(filePath.slice(start, i));
|
|
420
|
+
start = i + 1;
|
|
421
|
+
}
|
|
422
|
+
return out;
|
|
423
|
+
}
|
|
424
|
+
/** The dotted package a file belongs to, from the `+pkg` FOLDER names in its path. A nested
|
|
425
|
+
* `+a/+b/f.m` is `a.b`, which is MATLAB's own package nesting rule. */
|
|
426
|
+
packageFromPath(filePath) {
|
|
427
|
+
const segments = this.splitPath(filePath);
|
|
428
|
+
const names = [];
|
|
429
|
+
for (const segment of segments.slice(0, -1)) {
|
|
430
|
+
if (segment.length > 1 && segment[0] === "+" && this.isIdentifierSegment(segment.slice(1))) {
|
|
431
|
+
names.push(segment.slice(1));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return names.join(".");
|
|
435
|
+
}
|
|
436
|
+
moduleNameFromPath(filePath, packageName) {
|
|
437
|
+
const segments = this.splitPath(filePath);
|
|
438
|
+
let base = segments.length > 0 ? segments[segments.length - 1] : "";
|
|
439
|
+
if (base.length > 2 && base.slice(base.length - 2).toLowerCase() === ".m") base = base.slice(0, base.length - 2);
|
|
440
|
+
if (base === "") return "";
|
|
441
|
+
return packageName === "" ? base : `${packageName}.${base}`;
|
|
442
|
+
}
|
|
443
|
+
confidence(target) {
|
|
444
|
+
return this.declarations.has(this.fold(target)) ? 1 : 0.6;
|
|
445
|
+
}
|
|
446
|
+
emit(type, source, target, node, confidence, metadata = {}) {
|
|
447
|
+
const key = `${source}\0${type}\0${target}\0${node.startPosition.row + 1}`;
|
|
448
|
+
if (this.emitted.has(key)) return;
|
|
449
|
+
this.emitted.add(key);
|
|
450
|
+
this.relationships.push({
|
|
451
|
+
source,
|
|
452
|
+
target,
|
|
453
|
+
type,
|
|
454
|
+
confidence,
|
|
455
|
+
line_number: node.startPosition.row + 1,
|
|
456
|
+
metadata: { evidenceClass: confidence < 0.7 ? "inferred" : "structural", ...metadata }
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
fold(value) {
|
|
460
|
+
return value.toLowerCase();
|
|
461
|
+
}
|
|
462
|
+
lineCount(value) {
|
|
463
|
+
let count = 1;
|
|
464
|
+
for (const character of value) if (character === "\n") count += 1;
|
|
465
|
+
return count;
|
|
466
|
+
}
|
|
467
|
+
range(node) {
|
|
468
|
+
return {
|
|
469
|
+
startLine: node.startPosition.row + 1,
|
|
470
|
+
startColumn: node.startPosition.column,
|
|
471
|
+
endLine: node.endPosition.row + 1,
|
|
472
|
+
endColumn: node.endPosition.column,
|
|
473
|
+
startIndex: node.startIndex,
|
|
474
|
+
endIndex: node.endIndex
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
export {
|
|
479
|
+
RealMatlabAnalyzer
|
|
480
|
+
};
|