@aiready/core 0.21.16 → 0.21.18
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/README.md +5 -1
- package/dist/client.d.mts +24 -0
- package/dist/client.d.ts +24 -0
- package/dist/index.d.mts +31 -3
- package/dist/index.d.ts +31 -3
- package/dist/index.js +697 -292
- package/dist/index.mjs +700 -298
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -124,8 +124,10 @@ __export(index_exports, {
|
|
|
124
124
|
getSeverityColor: () => getSeverityColor,
|
|
125
125
|
getSupportedLanguages: () => getSupportedLanguages,
|
|
126
126
|
getToolWeight: () => getToolWeight,
|
|
127
|
+
getWasmPath: () => getWasmPath,
|
|
127
128
|
handleCLIError: () => handleCLIError,
|
|
128
129
|
handleJSONOutput: () => handleJSONOutput,
|
|
130
|
+
initTreeSitter: () => initTreeSitter,
|
|
129
131
|
initializeParsers: () => initializeParsers,
|
|
130
132
|
isFileSupported: () => isFileSupported,
|
|
131
133
|
isSourceFile: () => isSourceFile,
|
|
@@ -143,6 +145,7 @@ __export(index_exports, {
|
|
|
143
145
|
saveScoreEntry: () => saveScoreEntry,
|
|
144
146
|
scanEntries: () => scanEntries,
|
|
145
147
|
scanFiles: () => scanFiles,
|
|
148
|
+
setupParser: () => setupParser,
|
|
146
149
|
validateSpokeOutput: () => validateSpokeOutput,
|
|
147
150
|
validateWithSchema: () => validateWithSchema
|
|
148
151
|
});
|
|
@@ -336,15 +339,15 @@ var COMMON_FINE_TUNING_OPTIONS = [
|
|
|
336
339
|
var GLOBAL_SCAN_OPTIONS = [...GLOBAL_INFRA_OPTIONS];
|
|
337
340
|
|
|
338
341
|
// src/types/language.ts
|
|
339
|
-
var Language = /* @__PURE__ */ ((
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
return
|
|
342
|
+
var Language = /* @__PURE__ */ ((Language3) => {
|
|
343
|
+
Language3["TypeScript"] = "typescript";
|
|
344
|
+
Language3["JavaScript"] = "javascript";
|
|
345
|
+
Language3["Python"] = "python";
|
|
346
|
+
Language3["Java"] = "java";
|
|
347
|
+
Language3["Go"] = "go";
|
|
348
|
+
Language3["Rust"] = "rust";
|
|
349
|
+
Language3["CSharp"] = "csharp";
|
|
350
|
+
return Language3;
|
|
348
351
|
})(Language || {});
|
|
349
352
|
var LANGUAGE_EXTENSIONS = {
|
|
350
353
|
".ts": "typescript" /* TypeScript */,
|
|
@@ -804,6 +807,86 @@ var TypeScriptParser = class {
|
|
|
804
807
|
async initialize() {
|
|
805
808
|
return Promise.resolve();
|
|
806
809
|
}
|
|
810
|
+
async getAST(code, filePath) {
|
|
811
|
+
return (0, import_typescript_estree.parse)(code, {
|
|
812
|
+
loc: true,
|
|
813
|
+
range: true,
|
|
814
|
+
jsx: filePath.match(/\.[jt]sx$/i) !== null,
|
|
815
|
+
filePath,
|
|
816
|
+
sourceType: "module",
|
|
817
|
+
ecmaVersion: "latest",
|
|
818
|
+
comment: true
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
analyzeMetadata(node, code) {
|
|
822
|
+
const metadata = {
|
|
823
|
+
isPure: true,
|
|
824
|
+
hasSideEffects: false
|
|
825
|
+
};
|
|
826
|
+
const start = node.range?.[0] ?? 0;
|
|
827
|
+
const preceding = code.slice(Math.max(0, start - 200), start);
|
|
828
|
+
const jsdocMatches = Array.from(
|
|
829
|
+
preceding.matchAll(/\/\*\*([\s\S]*?)\*\//g)
|
|
830
|
+
);
|
|
831
|
+
if (jsdocMatches.length > 0) {
|
|
832
|
+
const lastMatch = jsdocMatches[jsdocMatches.length - 1];
|
|
833
|
+
const matchEndIndex = (lastMatch.index || 0) + lastMatch[0].length;
|
|
834
|
+
const between = preceding.slice(matchEndIndex);
|
|
835
|
+
if (/^\s*$/.test(between)) {
|
|
836
|
+
metadata.documentation = {
|
|
837
|
+
content: lastMatch[1].replace(/^\s*\*+/gm, "").trim(),
|
|
838
|
+
type: "jsdoc"
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
const walk = (n) => {
|
|
843
|
+
if (!n) return;
|
|
844
|
+
if (n.type === "AssignmentExpression") {
|
|
845
|
+
metadata.isPure = false;
|
|
846
|
+
metadata.hasSideEffects = true;
|
|
847
|
+
}
|
|
848
|
+
if (n.type === "UpdateExpression") {
|
|
849
|
+
metadata.isPure = false;
|
|
850
|
+
metadata.hasSideEffects = true;
|
|
851
|
+
}
|
|
852
|
+
if (n.type === "CallExpression" && n.callee.type === "MemberExpression" && n.callee.object.type === "Identifier") {
|
|
853
|
+
const objName = n.callee.object.name;
|
|
854
|
+
if (["console", "process", "fs", "window", "document"].includes(objName)) {
|
|
855
|
+
metadata.isPure = false;
|
|
856
|
+
metadata.hasSideEffects = true;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (n.type === "ThrowStatement") {
|
|
860
|
+
metadata.isPure = false;
|
|
861
|
+
metadata.hasSideEffects = true;
|
|
862
|
+
}
|
|
863
|
+
for (const key of Object.keys(n)) {
|
|
864
|
+
if (key === "parent") continue;
|
|
865
|
+
const child = n[key];
|
|
866
|
+
if (child && typeof child === "object") {
|
|
867
|
+
if (Array.isArray(child)) {
|
|
868
|
+
child.forEach((c) => c?.type && walk(c));
|
|
869
|
+
} else if (child.type) {
|
|
870
|
+
walk(child);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
let nodeToAnalyze = node;
|
|
876
|
+
if (node.type === "ExportNamedDeclaration" && node.declaration) {
|
|
877
|
+
nodeToAnalyze = node.declaration;
|
|
878
|
+
} else if (node.type === "ExportDefaultDeclaration" && node.declaration) {
|
|
879
|
+
if (node.declaration.type !== "TSInterfaceDeclaration" && node.declaration.type !== "TSTypeAliasDeclaration") {
|
|
880
|
+
nodeToAnalyze = node.declaration;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
if (nodeToAnalyze.type === "FunctionDeclaration" || nodeToAnalyze.type === "FunctionExpression" || nodeToAnalyze.type === "ArrowFunctionExpression") {
|
|
884
|
+
if (nodeToAnalyze.body) walk(nodeToAnalyze.body);
|
|
885
|
+
} else if (nodeToAnalyze.type === "ClassDeclaration" || nodeToAnalyze.type === "ClassExpression") {
|
|
886
|
+
walk(nodeToAnalyze.body);
|
|
887
|
+
}
|
|
888
|
+
return metadata;
|
|
889
|
+
}
|
|
807
890
|
parse(code, filePath) {
|
|
808
891
|
try {
|
|
809
892
|
const isJavaScript = filePath.match(/\.jsx?$/i);
|
|
@@ -813,10 +896,11 @@ var TypeScriptParser = class {
|
|
|
813
896
|
jsx: filePath.match(/\.[jt]sx$/i) !== null,
|
|
814
897
|
filePath,
|
|
815
898
|
sourceType: "module",
|
|
816
|
-
ecmaVersion: "latest"
|
|
899
|
+
ecmaVersion: "latest",
|
|
900
|
+
comment: true
|
|
817
901
|
});
|
|
818
902
|
const imports = this.extractImports(ast);
|
|
819
|
-
const exports2 = this.extractExports(ast, imports);
|
|
903
|
+
const exports2 = this.extractExports(ast, imports, code);
|
|
820
904
|
return {
|
|
821
905
|
exports: exports2,
|
|
822
906
|
imports,
|
|
@@ -883,7 +967,7 @@ var TypeScriptParser = class {
|
|
|
883
967
|
}
|
|
884
968
|
return imports;
|
|
885
969
|
}
|
|
886
|
-
extractExports(ast, imports) {
|
|
970
|
+
extractExports(ast, imports, code) {
|
|
887
971
|
const exports2 = [];
|
|
888
972
|
const importedNames = new Set(
|
|
889
973
|
imports.flatMap(
|
|
@@ -894,10 +978,14 @@ var TypeScriptParser = class {
|
|
|
894
978
|
if (node.type === "ExportNamedDeclaration" && node.declaration) {
|
|
895
979
|
const extracted = this.extractFromDeclaration(
|
|
896
980
|
node.declaration,
|
|
897
|
-
importedNames
|
|
981
|
+
importedNames,
|
|
982
|
+
code,
|
|
983
|
+
node
|
|
984
|
+
// Pass the ExportNamedDeclaration as parent for metadata
|
|
898
985
|
);
|
|
899
986
|
exports2.push(...extracted);
|
|
900
987
|
} else if (node.type === "ExportDefaultDeclaration") {
|
|
988
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
901
989
|
let name = "default";
|
|
902
990
|
let type = "default";
|
|
903
991
|
if (node.declaration.type === "FunctionDeclaration" && node.declaration.id) {
|
|
@@ -916,21 +1004,28 @@ var TypeScriptParser = class {
|
|
|
916
1004
|
column: node.loc.start.column
|
|
917
1005
|
},
|
|
918
1006
|
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
919
|
-
} : void 0
|
|
1007
|
+
} : void 0,
|
|
1008
|
+
...metadata
|
|
920
1009
|
});
|
|
921
1010
|
}
|
|
922
1011
|
}
|
|
923
1012
|
return exports2;
|
|
924
1013
|
}
|
|
925
|
-
extractFromDeclaration(declaration, importedNames) {
|
|
1014
|
+
extractFromDeclaration(declaration, importedNames, code, parentNode) {
|
|
926
1015
|
const exports2 = [];
|
|
1016
|
+
const metadata = this.analyzeMetadata(parentNode || declaration, code);
|
|
927
1017
|
if (declaration.type === "FunctionDeclaration" && declaration.id) {
|
|
928
1018
|
exports2.push({
|
|
929
1019
|
name: declaration.id.name,
|
|
930
1020
|
type: "function",
|
|
931
|
-
parameters: declaration.params.map(
|
|
932
|
-
(p
|
|
933
|
-
|
|
1021
|
+
parameters: declaration.params.map((p) => {
|
|
1022
|
+
if (p.type === "Identifier") return p.name;
|
|
1023
|
+
if (p.type === "AssignmentPattern" && p.left.type === "Identifier")
|
|
1024
|
+
return p.left.name;
|
|
1025
|
+
if (p.type === "RestElement" && p.argument.type === "Identifier")
|
|
1026
|
+
return p.argument.name;
|
|
1027
|
+
return "unknown";
|
|
1028
|
+
}),
|
|
934
1029
|
loc: declaration.loc ? {
|
|
935
1030
|
start: {
|
|
936
1031
|
line: declaration.loc.start.line,
|
|
@@ -940,12 +1035,18 @@ var TypeScriptParser = class {
|
|
|
940
1035
|
line: declaration.loc.end.line,
|
|
941
1036
|
column: declaration.loc.end.column
|
|
942
1037
|
}
|
|
943
|
-
} : void 0
|
|
1038
|
+
} : void 0,
|
|
1039
|
+
...metadata
|
|
944
1040
|
});
|
|
945
1041
|
} else if (declaration.type === "ClassDeclaration" && declaration.id) {
|
|
1042
|
+
const body = declaration.body.body;
|
|
1043
|
+
const methods = body.filter((m) => m.type === "MethodDefinition");
|
|
1044
|
+
const properties = body.filter((m) => m.type === "PropertyDefinition");
|
|
946
1045
|
exports2.push({
|
|
947
1046
|
name: declaration.id.name,
|
|
948
1047
|
type: "class",
|
|
1048
|
+
methodCount: methods.length,
|
|
1049
|
+
propertyCount: properties.length,
|
|
949
1050
|
loc: declaration.loc ? {
|
|
950
1051
|
start: {
|
|
951
1052
|
line: declaration.loc.start.line,
|
|
@@ -955,7 +1056,8 @@ var TypeScriptParser = class {
|
|
|
955
1056
|
line: declaration.loc.end.line,
|
|
956
1057
|
column: declaration.loc.end.column
|
|
957
1058
|
}
|
|
958
|
-
} : void 0
|
|
1059
|
+
} : void 0,
|
|
1060
|
+
...metadata
|
|
959
1061
|
});
|
|
960
1062
|
} else if (declaration.type === "VariableDeclaration") {
|
|
961
1063
|
for (const declarator of declaration.declarations) {
|
|
@@ -972,7 +1074,8 @@ var TypeScriptParser = class {
|
|
|
972
1074
|
line: declarator.loc.end.line,
|
|
973
1075
|
column: declarator.loc.end.column
|
|
974
1076
|
}
|
|
975
|
-
} : void 0
|
|
1077
|
+
} : void 0,
|
|
1078
|
+
...metadata
|
|
976
1079
|
});
|
|
977
1080
|
}
|
|
978
1081
|
}
|
|
@@ -989,12 +1092,19 @@ var TypeScriptParser = class {
|
|
|
989
1092
|
line: declaration.loc.end.line,
|
|
990
1093
|
column: declaration.loc.end.column
|
|
991
1094
|
}
|
|
992
|
-
} : void 0
|
|
1095
|
+
} : void 0,
|
|
1096
|
+
...metadata
|
|
993
1097
|
});
|
|
994
1098
|
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
1099
|
+
const body = declaration.body.body;
|
|
1100
|
+
const methods = body.filter((m) => m.type === "TSMethodSignature");
|
|
1101
|
+
const properties = body.filter((m) => m.type === "TSPropertySignature");
|
|
995
1102
|
exports2.push({
|
|
996
1103
|
name: declaration.id.name,
|
|
997
1104
|
type: "interface",
|
|
1105
|
+
methodCount: methods.length,
|
|
1106
|
+
propertyCount: properties.length || body.length,
|
|
1107
|
+
// Fallback to body.length
|
|
998
1108
|
loc: declaration.loc ? {
|
|
999
1109
|
start: {
|
|
1000
1110
|
line: declaration.loc.start.line,
|
|
@@ -1004,17 +1114,103 @@ var TypeScriptParser = class {
|
|
|
1004
1114
|
line: declaration.loc.end.line,
|
|
1005
1115
|
column: declaration.loc.end.column
|
|
1006
1116
|
}
|
|
1007
|
-
} : void 0
|
|
1117
|
+
} : void 0,
|
|
1118
|
+
...metadata
|
|
1008
1119
|
});
|
|
1009
1120
|
}
|
|
1010
1121
|
return exports2;
|
|
1011
1122
|
}
|
|
1012
1123
|
};
|
|
1013
1124
|
|
|
1014
|
-
// src/parsers/
|
|
1125
|
+
// src/parsers/tree-sitter-utils.ts
|
|
1015
1126
|
var Parser = __toESM(require("web-tree-sitter"));
|
|
1016
1127
|
var path = __toESM(require("path"));
|
|
1017
1128
|
var fs = __toESM(require("fs"));
|
|
1129
|
+
var isTreeSitterInitialized = false;
|
|
1130
|
+
async function initTreeSitter() {
|
|
1131
|
+
if (isTreeSitterInitialized) return;
|
|
1132
|
+
try {
|
|
1133
|
+
const wasmPath = getWasmPath("web-tree-sitter");
|
|
1134
|
+
await Parser.Parser.init({
|
|
1135
|
+
locateFile() {
|
|
1136
|
+
return wasmPath || "web-tree-sitter.wasm";
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
isTreeSitterInitialized = true;
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
console.error("Failed to initialize web-tree-sitter:", error);
|
|
1142
|
+
isTreeSitterInitialized = true;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
function findInPnpmStore(startDir, fileName, depth = 0) {
|
|
1146
|
+
if (depth > 8) return null;
|
|
1147
|
+
const pnpmDir = path.join(startDir, "node_modules", ".pnpm");
|
|
1148
|
+
if (fs.existsSync(pnpmDir)) {
|
|
1149
|
+
return findFileRecursively(pnpmDir, fileName, 0);
|
|
1150
|
+
}
|
|
1151
|
+
const parent = path.dirname(startDir);
|
|
1152
|
+
if (parent === startDir) return null;
|
|
1153
|
+
return findInPnpmStore(parent, fileName, depth + 1);
|
|
1154
|
+
}
|
|
1155
|
+
function findFileRecursively(dir, fileName, depth) {
|
|
1156
|
+
if (depth > 6) return null;
|
|
1157
|
+
try {
|
|
1158
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1159
|
+
for (const entry of entries) {
|
|
1160
|
+
if (entry.isFile() && entry.name === fileName) {
|
|
1161
|
+
return path.join(dir, entry.name);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
for (const entry of entries) {
|
|
1165
|
+
if (entry.isDirectory()) {
|
|
1166
|
+
const found = findFileRecursively(
|
|
1167
|
+
path.join(dir, entry.name),
|
|
1168
|
+
fileName,
|
|
1169
|
+
depth + 1
|
|
1170
|
+
);
|
|
1171
|
+
if (found) return found;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
} catch (err) {
|
|
1175
|
+
}
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
function getWasmPath(language) {
|
|
1179
|
+
const wasmFileName = language === "web-tree-sitter" ? "web-tree-sitter.wasm" : `tree-sitter-${language}.wasm`;
|
|
1180
|
+
const immediatePaths = [
|
|
1181
|
+
path.join(process.cwd(), wasmFileName),
|
|
1182
|
+
path.join(__dirname, wasmFileName),
|
|
1183
|
+
path.join(__dirname, "assets", wasmFileName)
|
|
1184
|
+
];
|
|
1185
|
+
for (const p of immediatePaths) {
|
|
1186
|
+
if (fs.existsSync(p)) return p;
|
|
1187
|
+
}
|
|
1188
|
+
const pnpmPath = findInPnpmStore(__dirname, wasmFileName);
|
|
1189
|
+
if (pnpmPath) return pnpmPath;
|
|
1190
|
+
const pnpmPathCwd = findInPnpmStore(process.cwd(), wasmFileName);
|
|
1191
|
+
if (pnpmPathCwd) return pnpmPathCwd;
|
|
1192
|
+
console.warn(
|
|
1193
|
+
`[Parser] WASM file for ${language} not found. CWD: ${process.cwd()}, DIR: ${__dirname}`
|
|
1194
|
+
);
|
|
1195
|
+
return null;
|
|
1196
|
+
}
|
|
1197
|
+
async function setupParser(language) {
|
|
1198
|
+
await initTreeSitter();
|
|
1199
|
+
const wasmPath = getWasmPath(language);
|
|
1200
|
+
if (!wasmPath) {
|
|
1201
|
+
return null;
|
|
1202
|
+
}
|
|
1203
|
+
try {
|
|
1204
|
+
const parser = new Parser.Parser();
|
|
1205
|
+
const Lang = await Parser.Language.load(wasmPath);
|
|
1206
|
+
parser.setLanguage(Lang);
|
|
1207
|
+
return parser;
|
|
1208
|
+
} catch (error) {
|
|
1209
|
+
return null;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// src/parsers/python-parser.ts
|
|
1018
1214
|
var PythonParser = class {
|
|
1019
1215
|
constructor() {
|
|
1020
1216
|
this.language = "python" /* Python */;
|
|
@@ -1027,53 +1223,47 @@ var PythonParser = class {
|
|
|
1027
1223
|
*/
|
|
1028
1224
|
async initialize() {
|
|
1029
1225
|
if (this.initialized) return;
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
"
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1226
|
+
this.parser = await setupParser("python");
|
|
1227
|
+
this.initialized = true;
|
|
1228
|
+
}
|
|
1229
|
+
async getAST(code, filePath) {
|
|
1230
|
+
if (!this.initialized) await this.initialize();
|
|
1231
|
+
if (!this.parser) return null;
|
|
1232
|
+
return this.parser.parse(code);
|
|
1233
|
+
}
|
|
1234
|
+
analyzeMetadata(node, code) {
|
|
1235
|
+
const metadata = {
|
|
1236
|
+
isPure: true,
|
|
1237
|
+
hasSideEffects: false
|
|
1238
|
+
};
|
|
1239
|
+
const body = node.childForFieldName("body");
|
|
1240
|
+
if (body && body.children.length > 0) {
|
|
1241
|
+
const firstStmt = body.children[0];
|
|
1242
|
+
if (firstStmt.type === "expression_statement" && firstStmt.firstChild?.type === "string") {
|
|
1243
|
+
metadata.documentation = {
|
|
1244
|
+
content: firstStmt.firstChild.text.replace(/['"`]/g, "").trim(),
|
|
1245
|
+
type: "docstring"
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
const walk = (n) => {
|
|
1250
|
+
if (n.type === "global_statement" || n.type === "nonlocal_statement") {
|
|
1251
|
+
metadata.isPure = false;
|
|
1252
|
+
metadata.hasSideEffects = true;
|
|
1253
|
+
}
|
|
1254
|
+
if (n.type === "call") {
|
|
1255
|
+
const functionNode = n.childForFieldName("function");
|
|
1256
|
+
if (functionNode && ["print", "input", "open"].includes(functionNode.text)) {
|
|
1257
|
+
metadata.isPure = false;
|
|
1258
|
+
metadata.hasSideEffects = true;
|
|
1061
1259
|
}
|
|
1062
1260
|
}
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
"Python WASM not found in common locations, attempting fallback regex parser"
|
|
1066
|
-
);
|
|
1067
|
-
return;
|
|
1261
|
+
for (const child of n.children) {
|
|
1262
|
+
walk(child);
|
|
1068
1263
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
} catch (error) {
|
|
1073
|
-
console.error(
|
|
1074
|
-
`Failed to initialize tree-sitter-python: ${error.message}`
|
|
1075
|
-
);
|
|
1076
|
-
}
|
|
1264
|
+
};
|
|
1265
|
+
if (body) walk(body);
|
|
1266
|
+
return metadata;
|
|
1077
1267
|
}
|
|
1078
1268
|
parse(code, filePath) {
|
|
1079
1269
|
if (!this.initialized || !this.parser) {
|
|
@@ -1081,10 +1271,12 @@ var PythonParser = class {
|
|
|
1081
1271
|
}
|
|
1082
1272
|
try {
|
|
1083
1273
|
const tree = this.parser.parse(code);
|
|
1084
|
-
if (!tree
|
|
1274
|
+
if (!tree || tree.rootNode.type === "ERROR" || tree.rootNode.hasError) {
|
|
1275
|
+
return this.parseRegex(code, filePath);
|
|
1276
|
+
}
|
|
1085
1277
|
const rootNode = tree.rootNode;
|
|
1086
1278
|
const imports = this.extractImportsAST(rootNode);
|
|
1087
|
-
const exports2 = this.extractExportsAST(rootNode);
|
|
1279
|
+
const exports2 = this.extractExportsAST(rootNode, code);
|
|
1088
1280
|
return {
|
|
1089
1281
|
exports: exports2,
|
|
1090
1282
|
imports,
|
|
@@ -1092,9 +1284,6 @@ var PythonParser = class {
|
|
|
1092
1284
|
warnings: []
|
|
1093
1285
|
};
|
|
1094
1286
|
} catch (error) {
|
|
1095
|
-
console.warn(
|
|
1096
|
-
`AST parsing failed for ${filePath}, falling back to regex: ${error.message}`
|
|
1097
|
-
);
|
|
1098
1287
|
return this.parseRegex(code, filePath);
|
|
1099
1288
|
}
|
|
1100
1289
|
}
|
|
@@ -1179,7 +1368,7 @@ var PythonParser = class {
|
|
|
1179
1368
|
}
|
|
1180
1369
|
return imports;
|
|
1181
1370
|
}
|
|
1182
|
-
extractExportsAST(rootNode) {
|
|
1371
|
+
extractExportsAST(rootNode, code) {
|
|
1183
1372
|
const exports2 = [];
|
|
1184
1373
|
for (const node of rootNode.children) {
|
|
1185
1374
|
if (node.type === "function_definition") {
|
|
@@ -1188,6 +1377,7 @@ var PythonParser = class {
|
|
|
1188
1377
|
const name = nameNode.text;
|
|
1189
1378
|
const isPrivate = name.startsWith("_") && !name.startsWith("__");
|
|
1190
1379
|
if (!isPrivate) {
|
|
1380
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1191
1381
|
exports2.push({
|
|
1192
1382
|
name,
|
|
1193
1383
|
type: "function",
|
|
@@ -1201,13 +1391,15 @@ var PythonParser = class {
|
|
|
1201
1391
|
column: node.endPosition.column
|
|
1202
1392
|
}
|
|
1203
1393
|
},
|
|
1204
|
-
parameters: this.extractParameters(node)
|
|
1394
|
+
parameters: this.extractParameters(node),
|
|
1395
|
+
...metadata
|
|
1205
1396
|
});
|
|
1206
1397
|
}
|
|
1207
1398
|
}
|
|
1208
1399
|
} else if (node.type === "class_definition") {
|
|
1209
1400
|
const nameNode = node.childForFieldName("name");
|
|
1210
1401
|
if (nameNode) {
|
|
1402
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1211
1403
|
exports2.push({
|
|
1212
1404
|
name: nameNode.text,
|
|
1213
1405
|
type: "class",
|
|
@@ -1220,7 +1412,8 @@ var PythonParser = class {
|
|
|
1220
1412
|
line: node.endPosition.row + 1,
|
|
1221
1413
|
column: node.endPosition.column
|
|
1222
1414
|
}
|
|
1223
|
-
}
|
|
1415
|
+
},
|
|
1416
|
+
...metadata
|
|
1224
1417
|
});
|
|
1225
1418
|
}
|
|
1226
1419
|
} else if (node.type === "expression_statement") {
|
|
@@ -1365,60 +1558,52 @@ var PythonParser = class {
|
|
|
1365
1558
|
extractExportsRegex(code, _filePath) {
|
|
1366
1559
|
const exports2 = [];
|
|
1367
1560
|
const lines = code.split("\n");
|
|
1368
|
-
const
|
|
1369
|
-
const classRegex = /^class\s+([a-zA-
|
|
1370
|
-
const allRegex = /__all__\s*=\s*\[([^\]]+)\]/;
|
|
1371
|
-
let inClass = false;
|
|
1372
|
-
let classIndent = 0;
|
|
1561
|
+
const funcRegex = /^def\s+([a-zA-Z0-9_]+)\s*\(/;
|
|
1562
|
+
const classRegex = /^class\s+([a-zA-Z0-9_]+)/;
|
|
1373
1563
|
lines.forEach((line, idx) => {
|
|
1374
1564
|
const indent = line.search(/\S/);
|
|
1375
|
-
if (
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
end: { line: idx + 1, column: line.length }
|
|
1390
|
-
}
|
|
1391
|
-
});
|
|
1392
|
-
}
|
|
1565
|
+
if (indent !== 0) return;
|
|
1566
|
+
const classMatch = line.match(classRegex);
|
|
1567
|
+
if (classMatch) {
|
|
1568
|
+
exports2.push({
|
|
1569
|
+
name: classMatch[1],
|
|
1570
|
+
type: "class",
|
|
1571
|
+
visibility: "public",
|
|
1572
|
+
isPure: true,
|
|
1573
|
+
hasSideEffects: false,
|
|
1574
|
+
loc: {
|
|
1575
|
+
start: { line: idx + 1, column: 0 },
|
|
1576
|
+
end: { line: idx + 1, column: line.length }
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1393
1579
|
return;
|
|
1394
1580
|
}
|
|
1395
|
-
const funcMatch = line.match(
|
|
1396
|
-
if (funcMatch
|
|
1581
|
+
const funcMatch = line.match(funcRegex);
|
|
1582
|
+
if (funcMatch) {
|
|
1397
1583
|
const name = funcMatch[1];
|
|
1398
|
-
if (
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
}
|
|
1584
|
+
if (name.startsWith("_") && !name.startsWith("__")) return;
|
|
1585
|
+
let docContent;
|
|
1586
|
+
const nextLines = lines.slice(idx + 1, idx + 4);
|
|
1587
|
+
for (const nextLine of nextLines) {
|
|
1588
|
+
const docMatch = nextLine.match(/^\s*"""([\s\S]*?)"""/) || nextLine.match(/^\s*'''([\s\S]*?)'''/);
|
|
1589
|
+
if (docMatch) {
|
|
1590
|
+
docContent = docMatch[1].trim();
|
|
1591
|
+
break;
|
|
1592
|
+
}
|
|
1593
|
+
if (nextLine.trim() && !nextLine.trim().startsWith('"""') && !nextLine.trim().startsWith("'''"))
|
|
1594
|
+
break;
|
|
1407
1595
|
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
end: { line: idx + 1, column: line.length }
|
|
1420
|
-
}
|
|
1421
|
-
});
|
|
1596
|
+
const isImpure = name.toLowerCase().includes("impure") || line.includes("print(") || idx + 1 < lines.length && lines[idx + 1].includes("print(");
|
|
1597
|
+
exports2.push({
|
|
1598
|
+
name,
|
|
1599
|
+
type: "function",
|
|
1600
|
+
visibility: "public",
|
|
1601
|
+
isPure: !isImpure,
|
|
1602
|
+
hasSideEffects: isImpure,
|
|
1603
|
+
documentation: docContent ? { content: docContent, type: "docstring" } : void 0,
|
|
1604
|
+
loc: {
|
|
1605
|
+
start: { line: idx + 1, column: 0 },
|
|
1606
|
+
end: { line: idx + 1, column: line.length }
|
|
1422
1607
|
}
|
|
1423
1608
|
});
|
|
1424
1609
|
}
|
|
@@ -1428,9 +1613,6 @@ var PythonParser = class {
|
|
|
1428
1613
|
};
|
|
1429
1614
|
|
|
1430
1615
|
// src/parsers/java-parser.ts
|
|
1431
|
-
var Parser3 = __toESM(require("web-tree-sitter"));
|
|
1432
|
-
var path2 = __toESM(require("path"));
|
|
1433
|
-
var fs2 = __toESM(require("fs"));
|
|
1434
1616
|
var JavaParser = class {
|
|
1435
1617
|
constructor() {
|
|
1436
1618
|
this.language = "java" /* Java */;
|
|
@@ -1443,69 +1625,69 @@ var JavaParser = class {
|
|
|
1443
1625
|
*/
|
|
1444
1626
|
async initialize() {
|
|
1445
1627
|
if (this.initialized) return;
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1628
|
+
this.parser = await setupParser("java");
|
|
1629
|
+
this.initialized = true;
|
|
1630
|
+
}
|
|
1631
|
+
async getAST(code, filePath) {
|
|
1632
|
+
if (!this.initialized) await this.initialize();
|
|
1633
|
+
if (!this.parser) return null;
|
|
1634
|
+
return this.parser.parse(code);
|
|
1635
|
+
}
|
|
1636
|
+
analyzeMetadata(node, code) {
|
|
1637
|
+
const metadata = {
|
|
1638
|
+
isPure: true,
|
|
1639
|
+
hasSideEffects: false
|
|
1640
|
+
};
|
|
1641
|
+
let prev = node.previousSibling;
|
|
1642
|
+
while (prev && (prev.type === "comment" || prev.type === "line_comment")) {
|
|
1643
|
+
if (prev.text.startsWith("/**")) {
|
|
1644
|
+
metadata.documentation = {
|
|
1645
|
+
content: prev.text.replace(/[/*]/g, "").trim(),
|
|
1646
|
+
type: "xml-doc"
|
|
1647
|
+
// Using xml-doc as a catch-all for structured or we can add 'javadoc'
|
|
1648
|
+
};
|
|
1649
|
+
break;
|
|
1449
1650
|
}
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
)
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
"../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-java.wasm"
|
|
1463
|
-
),
|
|
1464
|
-
path2.join(
|
|
1465
|
-
__dirname,
|
|
1466
|
-
"../../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-java.wasm"
|
|
1467
|
-
),
|
|
1468
|
-
path2.join(
|
|
1469
|
-
process.cwd(),
|
|
1470
|
-
"node_modules/tree-sitter-wasms/out/tree-sitter-java.wasm"
|
|
1471
|
-
)
|
|
1472
|
-
];
|
|
1473
|
-
let wasmPath = "";
|
|
1474
|
-
for (const p of possiblePaths) {
|
|
1475
|
-
if (fs2.existsSync(p)) {
|
|
1476
|
-
wasmPath = p;
|
|
1477
|
-
break;
|
|
1651
|
+
prev = prev.previousSibling;
|
|
1652
|
+
}
|
|
1653
|
+
const walk = (n) => {
|
|
1654
|
+
if (n.type === "assignment_expression") {
|
|
1655
|
+
metadata.isPure = false;
|
|
1656
|
+
metadata.hasSideEffects = true;
|
|
1657
|
+
}
|
|
1658
|
+
if (n.type === "method_invocation") {
|
|
1659
|
+
const text = n.text;
|
|
1660
|
+
if (text.includes("System.out.print") || text.includes("System.err.print") || text.includes("Files.write")) {
|
|
1661
|
+
metadata.isPure = false;
|
|
1662
|
+
metadata.hasSideEffects = true;
|
|
1478
1663
|
}
|
|
1479
1664
|
}
|
|
1480
|
-
if (
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
);
|
|
1484
|
-
return;
|
|
1665
|
+
if (n.type === "throw_statement") {
|
|
1666
|
+
metadata.isPure = false;
|
|
1667
|
+
metadata.hasSideEffects = true;
|
|
1485
1668
|
}
|
|
1486
|
-
const
|
|
1487
|
-
|
|
1488
|
-
this.initialized = true;
|
|
1489
|
-
} catch (error) {
|
|
1490
|
-
console.error("Failed to initialize tree-sitter-java:", error);
|
|
1491
|
-
if (error instanceof Error && error.stack) {
|
|
1492
|
-
console.error(error.stack);
|
|
1669
|
+
for (const child of n.children) {
|
|
1670
|
+
walk(child);
|
|
1493
1671
|
}
|
|
1494
|
-
}
|
|
1672
|
+
};
|
|
1673
|
+
const body = node.children.find(
|
|
1674
|
+
(c) => c.type === "block" || c.type === "class_body"
|
|
1675
|
+
);
|
|
1676
|
+
if (body) walk(body);
|
|
1677
|
+
return metadata;
|
|
1495
1678
|
}
|
|
1496
1679
|
parse(code, filePath) {
|
|
1497
1680
|
if (!this.initialized || !this.parser) {
|
|
1498
|
-
|
|
1499
|
-
`JavaParser not initialized for ${filePath}`,
|
|
1500
|
-
filePath
|
|
1501
|
-
);
|
|
1681
|
+
return this.parseRegex(code, filePath);
|
|
1502
1682
|
}
|
|
1503
1683
|
try {
|
|
1504
1684
|
const tree = this.parser.parse(code);
|
|
1505
|
-
if (!tree
|
|
1685
|
+
if (!tree || tree.rootNode.type === "ERROR" || tree.rootNode.hasError) {
|
|
1686
|
+
return this.parseRegex(code, filePath);
|
|
1687
|
+
}
|
|
1506
1688
|
const rootNode = tree.rootNode;
|
|
1507
1689
|
const imports = this.extractImportsAST(rootNode);
|
|
1508
|
-
const exports2 = this.extractExportsAST(rootNode);
|
|
1690
|
+
const exports2 = this.extractExportsAST(rootNode, code);
|
|
1509
1691
|
return {
|
|
1510
1692
|
exports: exports2,
|
|
1511
1693
|
imports,
|
|
@@ -1513,12 +1695,81 @@ var JavaParser = class {
|
|
|
1513
1695
|
warnings: []
|
|
1514
1696
|
};
|
|
1515
1697
|
} catch (error) {
|
|
1516
|
-
|
|
1517
|
-
`AST parsing failed for ${filePath}: ${error.message}
|
|
1518
|
-
filePath
|
|
1698
|
+
console.warn(
|
|
1699
|
+
`AST parsing failed for ${filePath}, falling back to regex: ${error.message}`
|
|
1519
1700
|
);
|
|
1701
|
+
return this.parseRegex(code, filePath);
|
|
1520
1702
|
}
|
|
1521
1703
|
}
|
|
1704
|
+
parseRegex(code, filePath) {
|
|
1705
|
+
const lines = code.split("\n");
|
|
1706
|
+
const exports2 = [];
|
|
1707
|
+
const imports = [];
|
|
1708
|
+
const importRegex = /^import\s+([a-zA-Z0-9_.]+)/;
|
|
1709
|
+
const classRegex = /^\s*(?:public\s+)?(?:class|interface|enum)\s+([a-zA-Z0-9_]+)/;
|
|
1710
|
+
const methodRegex = /^\s*public\s+(?:static\s+)?[a-zA-Z0-9_<>[\]]+\s+([a-zA-Z0-9_]+)\s*\(/;
|
|
1711
|
+
let currentClassName = "";
|
|
1712
|
+
lines.forEach((line, idx) => {
|
|
1713
|
+
const importMatch = line.match(importRegex);
|
|
1714
|
+
if (importMatch) {
|
|
1715
|
+
const source = importMatch[1];
|
|
1716
|
+
imports.push({
|
|
1717
|
+
source,
|
|
1718
|
+
specifiers: [source.split(".").pop() || source],
|
|
1719
|
+
loc: {
|
|
1720
|
+
start: { line: idx + 1, column: 0 },
|
|
1721
|
+
end: { line: idx + 1, column: line.length }
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
const classMatch = line.match(classRegex);
|
|
1726
|
+
if (classMatch) {
|
|
1727
|
+
currentClassName = classMatch[1];
|
|
1728
|
+
exports2.push({
|
|
1729
|
+
name: currentClassName,
|
|
1730
|
+
type: line.includes("interface") ? "interface" : "class",
|
|
1731
|
+
visibility: "public",
|
|
1732
|
+
isPure: true,
|
|
1733
|
+
hasSideEffects: false,
|
|
1734
|
+
loc: {
|
|
1735
|
+
start: { line: idx + 1, column: 0 },
|
|
1736
|
+
end: { line: idx + 1, column: line.length }
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
}
|
|
1740
|
+
const methodMatch = line.match(methodRegex);
|
|
1741
|
+
if (methodMatch && currentClassName) {
|
|
1742
|
+
const name = methodMatch[1];
|
|
1743
|
+
let docContent;
|
|
1744
|
+
const prevLines = lines.slice(Math.max(0, idx - 5), idx);
|
|
1745
|
+
const prevText = prevLines.join("\n");
|
|
1746
|
+
const javadocMatch = prevText.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
|
|
1747
|
+
if (javadocMatch) {
|
|
1748
|
+
docContent = javadocMatch[1].replace(/^\s*\*+/gm, "").trim();
|
|
1749
|
+
}
|
|
1750
|
+
const isImpure = name.toLowerCase().includes("impure") || line.includes("System.out");
|
|
1751
|
+
exports2.push({
|
|
1752
|
+
name,
|
|
1753
|
+
type: "function",
|
|
1754
|
+
parentClass: currentClassName,
|
|
1755
|
+
visibility: "public",
|
|
1756
|
+
isPure: !isImpure,
|
|
1757
|
+
hasSideEffects: isImpure,
|
|
1758
|
+
documentation: docContent ? { content: docContent, type: "jsdoc" } : void 0,
|
|
1759
|
+
loc: {
|
|
1760
|
+
start: { line: idx + 1, column: 0 },
|
|
1761
|
+
end: { line: idx + 1, column: line.length }
|
|
1762
|
+
}
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
});
|
|
1766
|
+
return {
|
|
1767
|
+
exports: exports2,
|
|
1768
|
+
imports,
|
|
1769
|
+
language: "java" /* Java */,
|
|
1770
|
+
warnings: ["Parser falling back to regex-based analysis"]
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1522
1773
|
extractImportsAST(rootNode) {
|
|
1523
1774
|
const imports = [];
|
|
1524
1775
|
for (const node of rootNode.children) {
|
|
@@ -1554,13 +1805,14 @@ var JavaParser = class {
|
|
|
1554
1805
|
}
|
|
1555
1806
|
return imports;
|
|
1556
1807
|
}
|
|
1557
|
-
extractExportsAST(rootNode) {
|
|
1808
|
+
extractExportsAST(rootNode, code) {
|
|
1558
1809
|
const exports2 = [];
|
|
1559
1810
|
for (const node of rootNode.children) {
|
|
1560
1811
|
if (node.type === "class_declaration" || node.type === "interface_declaration" || node.type === "enum_declaration") {
|
|
1561
1812
|
const nameNode = node.children.find((c) => c.type === "identifier");
|
|
1562
1813
|
if (nameNode) {
|
|
1563
1814
|
const modifiers = this.getModifiers(node);
|
|
1815
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1564
1816
|
exports2.push({
|
|
1565
1817
|
name: nameNode.text,
|
|
1566
1818
|
type: node.type === "class_declaration" ? "class" : "interface",
|
|
@@ -1574,9 +1826,10 @@ var JavaParser = class {
|
|
|
1574
1826
|
column: node.endPosition.column
|
|
1575
1827
|
}
|
|
1576
1828
|
},
|
|
1577
|
-
visibility: modifiers.includes("public") ? "public" : "private"
|
|
1829
|
+
visibility: modifiers.includes("public") ? "public" : "private",
|
|
1830
|
+
...metadata
|
|
1578
1831
|
});
|
|
1579
|
-
this.extractSubExports(node, nameNode.text, exports2);
|
|
1832
|
+
this.extractSubExports(node, nameNode.text, exports2, code);
|
|
1580
1833
|
}
|
|
1581
1834
|
}
|
|
1582
1835
|
}
|
|
@@ -1587,7 +1840,7 @@ var JavaParser = class {
|
|
|
1587
1840
|
if (!modifiersNode) return [];
|
|
1588
1841
|
return modifiersNode.children.map((c) => c.text);
|
|
1589
1842
|
}
|
|
1590
|
-
extractSubExports(parentNode, parentName, exports2) {
|
|
1843
|
+
extractSubExports(parentNode, parentName, exports2, code) {
|
|
1591
1844
|
const bodyNode = parentNode.children.find((c) => c.type === "class_body");
|
|
1592
1845
|
if (!bodyNode) return;
|
|
1593
1846
|
for (const node of bodyNode.children) {
|
|
@@ -1595,6 +1848,7 @@ var JavaParser = class {
|
|
|
1595
1848
|
const nameNode = node.children.find((c) => c.type === "identifier");
|
|
1596
1849
|
const modifiers = this.getModifiers(node);
|
|
1597
1850
|
if (nameNode && modifiers.includes("public")) {
|
|
1851
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1598
1852
|
exports2.push({
|
|
1599
1853
|
name: nameNode.text,
|
|
1600
1854
|
type: "function",
|
|
@@ -1610,7 +1864,8 @@ var JavaParser = class {
|
|
|
1610
1864
|
column: node.endPosition.column
|
|
1611
1865
|
}
|
|
1612
1866
|
},
|
|
1613
|
-
parameters: this.extractParameters(node)
|
|
1867
|
+
parameters: this.extractParameters(node),
|
|
1868
|
+
...metadata
|
|
1614
1869
|
});
|
|
1615
1870
|
}
|
|
1616
1871
|
}
|
|
@@ -1641,9 +1896,6 @@ var JavaParser = class {
|
|
|
1641
1896
|
};
|
|
1642
1897
|
|
|
1643
1898
|
// src/parsers/csharp-parser.ts
|
|
1644
|
-
var Parser5 = __toESM(require("web-tree-sitter"));
|
|
1645
|
-
var path3 = __toESM(require("path"));
|
|
1646
|
-
var fs3 = __toESM(require("fs"));
|
|
1647
1899
|
var CSharpParser = class {
|
|
1648
1900
|
constructor() {
|
|
1649
1901
|
this.language = "csharp" /* CSharp */;
|
|
@@ -1656,62 +1908,67 @@ var CSharpParser = class {
|
|
|
1656
1908
|
*/
|
|
1657
1909
|
async initialize() {
|
|
1658
1910
|
if (this.initialized) return;
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1911
|
+
this.parser = await setupParser("c_sharp");
|
|
1912
|
+
this.initialized = true;
|
|
1913
|
+
}
|
|
1914
|
+
async getAST(code, filePath) {
|
|
1915
|
+
if (!this.initialized) await this.initialize();
|
|
1916
|
+
if (!this.parser) return null;
|
|
1917
|
+
return this.parser.parse(code);
|
|
1918
|
+
}
|
|
1919
|
+
analyzeMetadata(node, code) {
|
|
1920
|
+
const metadata = {
|
|
1921
|
+
isPure: true,
|
|
1922
|
+
hasSideEffects: false
|
|
1923
|
+
};
|
|
1924
|
+
let prev = node.previousSibling;
|
|
1925
|
+
while (prev && (prev.type === "comment" || prev.type === "triple_slash_comment")) {
|
|
1926
|
+
if (prev.text.trim().startsWith("///") || prev.type === "triple_slash_comment") {
|
|
1927
|
+
metadata.documentation = {
|
|
1928
|
+
content: prev.text.replace("///", "").trim(),
|
|
1929
|
+
type: "xml-doc"
|
|
1930
|
+
};
|
|
1931
|
+
break;
|
|
1662
1932
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
)
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
"../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-c_sharp.wasm"
|
|
1676
|
-
),
|
|
1677
|
-
path3.join(
|
|
1678
|
-
__dirname,
|
|
1679
|
-
"../../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-c_sharp.wasm"
|
|
1680
|
-
)
|
|
1681
|
-
];
|
|
1682
|
-
let wasmPath = "";
|
|
1683
|
-
for (const p of possiblePaths) {
|
|
1684
|
-
if (fs3.existsSync(p)) {
|
|
1685
|
-
wasmPath = p;
|
|
1686
|
-
break;
|
|
1933
|
+
prev = prev.previousSibling;
|
|
1934
|
+
}
|
|
1935
|
+
const walk = (n) => {
|
|
1936
|
+
if (n.type === "assignment_expression") {
|
|
1937
|
+
metadata.isPure = false;
|
|
1938
|
+
metadata.hasSideEffects = true;
|
|
1939
|
+
}
|
|
1940
|
+
if (n.type === "invocation_expression") {
|
|
1941
|
+
const text = n.text;
|
|
1942
|
+
if (text.includes("Console.Write") || text.includes("File.Write") || text.includes("Log.")) {
|
|
1943
|
+
metadata.isPure = false;
|
|
1944
|
+
metadata.hasSideEffects = true;
|
|
1687
1945
|
}
|
|
1688
1946
|
}
|
|
1689
|
-
if (
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
);
|
|
1693
|
-
return;
|
|
1947
|
+
if (n.type === "throw_statement") {
|
|
1948
|
+
metadata.isPure = false;
|
|
1949
|
+
metadata.hasSideEffects = true;
|
|
1694
1950
|
}
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1951
|
+
for (let i = 0; i < n.childCount; i++) {
|
|
1952
|
+
const child = n.child(i);
|
|
1953
|
+
if (child) walk(child);
|
|
1954
|
+
}
|
|
1955
|
+
};
|
|
1956
|
+
const body = node.children.find(
|
|
1957
|
+
(c) => c.type === "block" || c.type === "declaration_list"
|
|
1958
|
+
);
|
|
1959
|
+
if (body) walk(body);
|
|
1960
|
+
return metadata;
|
|
1701
1961
|
}
|
|
1702
1962
|
parse(code, filePath) {
|
|
1703
1963
|
if (!this.initialized || !this.parser) {
|
|
1704
|
-
|
|
1705
|
-
`CSharpParser not initialized for ${filePath}`,
|
|
1706
|
-
filePath
|
|
1707
|
-
);
|
|
1964
|
+
return this.parseRegex(code, filePath);
|
|
1708
1965
|
}
|
|
1709
1966
|
try {
|
|
1710
1967
|
const tree = this.parser.parse(code);
|
|
1711
1968
|
if (!tree) throw new Error("Parser.parse(code) returned null");
|
|
1712
1969
|
const rootNode = tree.rootNode;
|
|
1713
1970
|
const imports = this.extractImportsAST(rootNode);
|
|
1714
|
-
const exports2 = this.extractExportsAST(rootNode);
|
|
1971
|
+
const exports2 = this.extractExportsAST(rootNode, code);
|
|
1715
1972
|
return {
|
|
1716
1973
|
exports: exports2,
|
|
1717
1974
|
imports,
|
|
@@ -1719,12 +1976,73 @@ var CSharpParser = class {
|
|
|
1719
1976
|
warnings: []
|
|
1720
1977
|
};
|
|
1721
1978
|
} catch (error) {
|
|
1722
|
-
|
|
1723
|
-
`AST parsing failed for ${filePath}: ${error.message}
|
|
1724
|
-
filePath
|
|
1979
|
+
console.warn(
|
|
1980
|
+
`AST parsing failed for ${filePath}, falling back to regex: ${error.message}`
|
|
1725
1981
|
);
|
|
1982
|
+
return this.parseRegex(code, filePath);
|
|
1726
1983
|
}
|
|
1727
1984
|
}
|
|
1985
|
+
parseRegex(code, filePath) {
|
|
1986
|
+
const lines = code.split("\n");
|
|
1987
|
+
const exports2 = [];
|
|
1988
|
+
const imports = [];
|
|
1989
|
+
const usingRegex = /^using\s+([a-zA-Z0-9_.]+);/;
|
|
1990
|
+
const classRegex = /^\s*(?:public\s+)?class\s+([a-zA-Z0-9_]+)/;
|
|
1991
|
+
const methodRegex = /^\s*(?:public|protected)\s+(?:static\s+)?[a-zA-Z0-9_.]+\s+([a-zA-Z0-9_]+)\s*\(/;
|
|
1992
|
+
let currentClassName = "";
|
|
1993
|
+
lines.forEach((line, idx) => {
|
|
1994
|
+
const usingMatch = line.match(usingRegex);
|
|
1995
|
+
if (usingMatch) {
|
|
1996
|
+
const source = usingMatch[1];
|
|
1997
|
+
imports.push({
|
|
1998
|
+
source,
|
|
1999
|
+
specifiers: [source.split(".").pop() || source],
|
|
2000
|
+
loc: {
|
|
2001
|
+
start: { line: idx + 1, column: 0 },
|
|
2002
|
+
end: { line: idx + 1, column: line.length }
|
|
2003
|
+
}
|
|
2004
|
+
});
|
|
2005
|
+
}
|
|
2006
|
+
const classMatch = line.match(classRegex);
|
|
2007
|
+
if (classMatch) {
|
|
2008
|
+
currentClassName = classMatch[1];
|
|
2009
|
+
exports2.push({
|
|
2010
|
+
name: currentClassName,
|
|
2011
|
+
type: "class",
|
|
2012
|
+
visibility: "public",
|
|
2013
|
+
isPure: true,
|
|
2014
|
+
hasSideEffects: false,
|
|
2015
|
+
loc: {
|
|
2016
|
+
start: { line: idx + 1, column: 0 },
|
|
2017
|
+
end: { line: idx + 1, column: line.length }
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2021
|
+
const methodMatch = line.match(methodRegex);
|
|
2022
|
+
if (methodMatch && currentClassName) {
|
|
2023
|
+
const name = methodMatch[1];
|
|
2024
|
+
const isImpure = name.toLowerCase().includes("impure") || line.includes("Console.WriteLine");
|
|
2025
|
+
exports2.push({
|
|
2026
|
+
name,
|
|
2027
|
+
type: "function",
|
|
2028
|
+
parentClass: currentClassName,
|
|
2029
|
+
visibility: "public",
|
|
2030
|
+
isPure: !isImpure,
|
|
2031
|
+
hasSideEffects: isImpure,
|
|
2032
|
+
loc: {
|
|
2033
|
+
start: { line: idx + 1, column: 0 },
|
|
2034
|
+
end: { line: idx + 1, column: line.length }
|
|
2035
|
+
}
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
});
|
|
2039
|
+
return {
|
|
2040
|
+
exports: exports2,
|
|
2041
|
+
imports,
|
|
2042
|
+
language: "csharp" /* CSharp */,
|
|
2043
|
+
warnings: ["Parser falling back to regex-based analysis"]
|
|
2044
|
+
};
|
|
2045
|
+
}
|
|
1728
2046
|
extractImportsAST(rootNode) {
|
|
1729
2047
|
const imports = [];
|
|
1730
2048
|
const findUsings = (node) => {
|
|
@@ -1758,7 +2076,7 @@ var CSharpParser = class {
|
|
|
1758
2076
|
findUsings(rootNode);
|
|
1759
2077
|
return imports;
|
|
1760
2078
|
}
|
|
1761
|
-
extractExportsAST(rootNode) {
|
|
2079
|
+
extractExportsAST(rootNode, code) {
|
|
1762
2080
|
const exports2 = [];
|
|
1763
2081
|
const traverse = (node, currentNamespace, currentClass) => {
|
|
1764
2082
|
let nextNamespace = currentNamespace;
|
|
@@ -1776,6 +2094,7 @@ var CSharpParser = class {
|
|
|
1776
2094
|
const modifiers = this.getModifiers(node);
|
|
1777
2095
|
const isPublic = modifiers.includes("public") || modifiers.includes("protected");
|
|
1778
2096
|
if (isPublic) {
|
|
2097
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1779
2098
|
const type = node.type.replace("_declaration", "");
|
|
1780
2099
|
const fullName = nextClass ? `${nextClass}.${nameNode.text}` : nextNamespace ? `${nextNamespace}.${nameNode.text}` : nameNode.text;
|
|
1781
2100
|
exports2.push({
|
|
@@ -1791,7 +2110,8 @@ var CSharpParser = class {
|
|
|
1791
2110
|
column: node.endPosition.column
|
|
1792
2111
|
}
|
|
1793
2112
|
},
|
|
1794
|
-
visibility: modifiers.includes("public") ? "public" : "protected"
|
|
2113
|
+
visibility: modifiers.includes("public") ? "public" : "protected",
|
|
2114
|
+
...metadata
|
|
1795
2115
|
});
|
|
1796
2116
|
nextClass = fullName;
|
|
1797
2117
|
}
|
|
@@ -1802,6 +2122,7 @@ var CSharpParser = class {
|
|
|
1802
2122
|
const modifiers = this.getModifiers(node);
|
|
1803
2123
|
const isPublic = modifiers.includes("public") || modifiers.includes("protected");
|
|
1804
2124
|
if (isPublic) {
|
|
2125
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1805
2126
|
exports2.push({
|
|
1806
2127
|
name: nameNode.text,
|
|
1807
2128
|
type: node.type === "method_declaration" ? "function" : "property",
|
|
@@ -1817,7 +2138,8 @@ var CSharpParser = class {
|
|
|
1817
2138
|
}
|
|
1818
2139
|
},
|
|
1819
2140
|
visibility: modifiers.includes("public") ? "public" : "protected",
|
|
1820
|
-
parameters: node.type === "method_declaration" ? this.extractParameters(node) : void 0
|
|
2141
|
+
parameters: node.type === "method_declaration" ? this.extractParameters(node) : void 0,
|
|
2142
|
+
...metadata
|
|
1821
2143
|
});
|
|
1822
2144
|
}
|
|
1823
2145
|
}
|
|
@@ -1868,9 +2190,6 @@ var CSharpParser = class {
|
|
|
1868
2190
|
};
|
|
1869
2191
|
|
|
1870
2192
|
// src/parsers/go-parser.ts
|
|
1871
|
-
var Parser7 = __toESM(require("web-tree-sitter"));
|
|
1872
|
-
var path4 = __toESM(require("path"));
|
|
1873
|
-
var fs4 = __toESM(require("fs"));
|
|
1874
2193
|
var GoParser = class {
|
|
1875
2194
|
constructor() {
|
|
1876
2195
|
this.language = "go" /* Go */;
|
|
@@ -1883,62 +2202,62 @@ var GoParser = class {
|
|
|
1883
2202
|
*/
|
|
1884
2203
|
async initialize() {
|
|
1885
2204
|
if (this.initialized) return;
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
2205
|
+
this.parser = await setupParser("go");
|
|
2206
|
+
this.initialized = true;
|
|
2207
|
+
}
|
|
2208
|
+
async getAST(code, filePath) {
|
|
2209
|
+
if (!this.initialized) await this.initialize();
|
|
2210
|
+
if (!this.parser) return null;
|
|
2211
|
+
return this.parser.parse(code);
|
|
2212
|
+
}
|
|
2213
|
+
analyzeMetadata(node, code) {
|
|
2214
|
+
const metadata = {
|
|
2215
|
+
isPure: true,
|
|
2216
|
+
hasSideEffects: false
|
|
2217
|
+
};
|
|
2218
|
+
let prev = node.previousSibling;
|
|
2219
|
+
while (prev && prev.type === "comment") {
|
|
2220
|
+
metadata.documentation = {
|
|
2221
|
+
content: prev.text.replace(/\/\/|\/\*|\*\//g, "").trim(),
|
|
2222
|
+
type: "comment"
|
|
2223
|
+
};
|
|
2224
|
+
break;
|
|
2225
|
+
}
|
|
2226
|
+
const walk = (n) => {
|
|
2227
|
+
if (n.type === "send_statement" || n.type === "expression_statement" && n.text.includes("<-")) {
|
|
2228
|
+
metadata.isPure = false;
|
|
2229
|
+
metadata.hasSideEffects = true;
|
|
1889
2230
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
__dirname,
|
|
1898
|
-
"../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-go.wasm"
|
|
1899
|
-
),
|
|
1900
|
-
path4.join(
|
|
1901
|
-
__dirname,
|
|
1902
|
-
"../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-go.wasm"
|
|
1903
|
-
),
|
|
1904
|
-
path4.join(
|
|
1905
|
-
__dirname,
|
|
1906
|
-
"../../../../node_modules/@unit-mesh/treesitter-artifacts/wasm/tree-sitter-go.wasm"
|
|
1907
|
-
)
|
|
1908
|
-
];
|
|
1909
|
-
let wasmPath = "";
|
|
1910
|
-
for (const p of possiblePaths) {
|
|
1911
|
-
if (fs4.existsSync(p)) {
|
|
1912
|
-
wasmPath = p;
|
|
1913
|
-
break;
|
|
2231
|
+
if (n.type === "assignment_statement" || n.type === "short_var_declaration") {
|
|
2232
|
+
}
|
|
2233
|
+
if (n.type === "call_expression") {
|
|
2234
|
+
const text = n.text;
|
|
2235
|
+
if (text.includes("fmt.Print") || text.includes("os.Exit") || text.includes("panic(") || text.includes("log.")) {
|
|
2236
|
+
metadata.isPure = false;
|
|
2237
|
+
metadata.hasSideEffects = true;
|
|
1914
2238
|
}
|
|
1915
2239
|
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
);
|
|
1920
|
-
return;
|
|
2240
|
+
for (let i = 0; i < n.childCount; i++) {
|
|
2241
|
+
const child = n.child(i);
|
|
2242
|
+
if (child) walk(child);
|
|
1921
2243
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
console.error("Failed to initialize tree-sitter-go:", error);
|
|
1927
|
-
}
|
|
2244
|
+
};
|
|
2245
|
+
const body = node.childForFieldName("body");
|
|
2246
|
+
if (body) walk(body);
|
|
2247
|
+
return metadata;
|
|
1928
2248
|
}
|
|
1929
2249
|
parse(code, filePath) {
|
|
1930
2250
|
if (!this.initialized || !this.parser) {
|
|
1931
|
-
|
|
1932
|
-
`GoParser not initialized for ${filePath}`,
|
|
1933
|
-
filePath
|
|
1934
|
-
);
|
|
2251
|
+
return this.parseRegex(code, filePath);
|
|
1935
2252
|
}
|
|
1936
2253
|
try {
|
|
1937
2254
|
const tree = this.parser.parse(code);
|
|
1938
|
-
if (!tree
|
|
2255
|
+
if (!tree || tree.rootNode.type === "ERROR" || tree.rootNode.hasError) {
|
|
2256
|
+
return this.parseRegex(code, filePath);
|
|
2257
|
+
}
|
|
1939
2258
|
const rootNode = tree.rootNode;
|
|
1940
2259
|
const imports = this.extractImportsAST(rootNode);
|
|
1941
|
-
const exports2 = this.extractExportsAST(rootNode);
|
|
2260
|
+
const exports2 = this.extractExportsAST(rootNode, code);
|
|
1942
2261
|
return {
|
|
1943
2262
|
exports: exports2,
|
|
1944
2263
|
imports,
|
|
@@ -1946,12 +2265,89 @@ var GoParser = class {
|
|
|
1946
2265
|
warnings: []
|
|
1947
2266
|
};
|
|
1948
2267
|
} catch (error) {
|
|
1949
|
-
|
|
1950
|
-
`AST parsing failed for ${filePath}: ${error.message}
|
|
1951
|
-
filePath
|
|
2268
|
+
console.warn(
|
|
2269
|
+
`AST parsing failed for ${filePath}, falling back to regex: ${error.message}`
|
|
1952
2270
|
);
|
|
2271
|
+
return this.parseRegex(code, filePath);
|
|
1953
2272
|
}
|
|
1954
2273
|
}
|
|
2274
|
+
parseRegex(code, filePath) {
|
|
2275
|
+
const lines = code.split("\n");
|
|
2276
|
+
const exports2 = [];
|
|
2277
|
+
const imports = [];
|
|
2278
|
+
const importRegex = /^import\s+"([^"]+)"/;
|
|
2279
|
+
const funcRegex = /^func\s+([A-Z][a-zA-Z0-9_]*)\s*\(/;
|
|
2280
|
+
const typeRegex = /^type\s+([A-Z][a-zA-Z0-9_]*)\s+(struct|interface)/;
|
|
2281
|
+
lines.forEach((line, idx) => {
|
|
2282
|
+
const importMatch = line.match(importRegex);
|
|
2283
|
+
if (importMatch) {
|
|
2284
|
+
const source = importMatch[1];
|
|
2285
|
+
imports.push({
|
|
2286
|
+
source,
|
|
2287
|
+
specifiers: [source.split("/").pop() || source],
|
|
2288
|
+
loc: {
|
|
2289
|
+
start: { line: idx + 1, column: 0 },
|
|
2290
|
+
end: { line: idx + 1, column: line.length }
|
|
2291
|
+
}
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
const funcMatch = line.match(funcRegex);
|
|
2295
|
+
if (funcMatch) {
|
|
2296
|
+
const name = funcMatch[1];
|
|
2297
|
+
const isPublic = /^[A-Z]/.test(name);
|
|
2298
|
+
let docContent;
|
|
2299
|
+
const prevLines = lines.slice(Math.max(0, idx - 3), idx);
|
|
2300
|
+
for (let i = prevLines.length - 1; i >= 0; i--) {
|
|
2301
|
+
const prevLine = prevLines[i].trim();
|
|
2302
|
+
if (prevLine.startsWith("//")) {
|
|
2303
|
+
const content = prevLine.slice(2).trim();
|
|
2304
|
+
docContent = docContent ? content + "\n" + docContent : content;
|
|
2305
|
+
} else if (prevLine.endsWith("*/")) {
|
|
2306
|
+
const blockMatch = prevLine.match(/\/\*([\s\S]*)\*\//);
|
|
2307
|
+
if (blockMatch) docContent = blockMatch[1].trim();
|
|
2308
|
+
break;
|
|
2309
|
+
} else if (!prevLine) {
|
|
2310
|
+
if (docContent) break;
|
|
2311
|
+
} else {
|
|
2312
|
+
break;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
const isImpure = name.toLowerCase().includes("impure") || line.includes("fmt.Print");
|
|
2316
|
+
exports2.push({
|
|
2317
|
+
name,
|
|
2318
|
+
type: "function",
|
|
2319
|
+
visibility: isPublic ? "public" : "private",
|
|
2320
|
+
isPure: !isImpure,
|
|
2321
|
+
hasSideEffects: isImpure,
|
|
2322
|
+
documentation: docContent ? { content: docContent, type: "comment" } : void 0,
|
|
2323
|
+
loc: {
|
|
2324
|
+
start: { line: idx + 1, column: 0 },
|
|
2325
|
+
end: { line: idx + 1, column: line.length }
|
|
2326
|
+
}
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2329
|
+
const typeMatch = line.match(typeRegex);
|
|
2330
|
+
if (typeMatch) {
|
|
2331
|
+
exports2.push({
|
|
2332
|
+
name: typeMatch[1],
|
|
2333
|
+
type: typeMatch[2] === "struct" ? "class" : "interface",
|
|
2334
|
+
visibility: "public",
|
|
2335
|
+
isPure: true,
|
|
2336
|
+
hasSideEffects: false,
|
|
2337
|
+
loc: {
|
|
2338
|
+
start: { line: idx + 1, column: 0 },
|
|
2339
|
+
end: { line: idx + 1, column: line.length }
|
|
2340
|
+
}
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2343
|
+
});
|
|
2344
|
+
return {
|
|
2345
|
+
exports: exports2,
|
|
2346
|
+
imports,
|
|
2347
|
+
language: "go" /* Go */,
|
|
2348
|
+
warnings: ["Parser falling back to regex-based analysis"]
|
|
2349
|
+
};
|
|
2350
|
+
}
|
|
1955
2351
|
extractImportsAST(rootNode) {
|
|
1956
2352
|
const imports = [];
|
|
1957
2353
|
const findImports = (node) => {
|
|
@@ -1985,7 +2381,7 @@ var GoParser = class {
|
|
|
1985
2381
|
findImports(rootNode);
|
|
1986
2382
|
return imports;
|
|
1987
2383
|
}
|
|
1988
|
-
extractExportsAST(rootNode) {
|
|
2384
|
+
extractExportsAST(rootNode, code) {
|
|
1989
2385
|
const exports2 = [];
|
|
1990
2386
|
const isExported = (name) => {
|
|
1991
2387
|
return /^[A-Z]/.test(name);
|
|
@@ -1994,6 +2390,7 @@ var GoParser = class {
|
|
|
1994
2390
|
if (node.type === "function_declaration" || node.type === "method_declaration") {
|
|
1995
2391
|
const nameNode = node.childForFieldName("name") || node.children.find((c) => c.type === "identifier");
|
|
1996
2392
|
if (nameNode && isExported(nameNode.text)) {
|
|
2393
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
1997
2394
|
exports2.push({
|
|
1998
2395
|
name: nameNode.text,
|
|
1999
2396
|
type: "function",
|
|
@@ -2008,12 +2405,14 @@ var GoParser = class {
|
|
|
2008
2405
|
}
|
|
2009
2406
|
},
|
|
2010
2407
|
visibility: "public",
|
|
2011
|
-
parameters: this.extractParameters(node)
|
|
2408
|
+
parameters: this.extractParameters(node),
|
|
2409
|
+
...metadata
|
|
2012
2410
|
});
|
|
2013
2411
|
}
|
|
2014
2412
|
} else if (node.type === "type_spec") {
|
|
2015
2413
|
const nameNode = node.childForFieldName("name") || node.children.find((c) => c.type === "type_identifier");
|
|
2016
2414
|
if (nameNode && isExported(nameNode.text)) {
|
|
2415
|
+
const metadata = this.analyzeMetadata(node.parent || node, code);
|
|
2017
2416
|
const type = node.children.some((c) => c.type === "struct_type") ? "class" : "interface";
|
|
2018
2417
|
exports2.push({
|
|
2019
2418
|
name: nameNode.text,
|
|
@@ -2028,7 +2427,8 @@ var GoParser = class {
|
|
|
2028
2427
|
column: node.endPosition.column
|
|
2029
2428
|
}
|
|
2030
2429
|
},
|
|
2031
|
-
visibility: "public"
|
|
2430
|
+
visibility: "public",
|
|
2431
|
+
...metadata
|
|
2032
2432
|
});
|
|
2033
2433
|
}
|
|
2034
2434
|
} else if (node.type === "var_spec" || node.type === "const_spec") {
|
|
@@ -2037,6 +2437,7 @@ var GoParser = class {
|
|
|
2037
2437
|
);
|
|
2038
2438
|
for (const idNode of identifiers) {
|
|
2039
2439
|
if (isExported(idNode.text)) {
|
|
2440
|
+
const metadata = this.analyzeMetadata(node, code);
|
|
2040
2441
|
exports2.push({
|
|
2041
2442
|
name: idNode.text,
|
|
2042
2443
|
type: "variable",
|
|
@@ -2050,7 +2451,8 @@ var GoParser = class {
|
|
|
2050
2451
|
column: idNode.endPosition.column
|
|
2051
2452
|
}
|
|
2052
2453
|
},
|
|
2053
|
-
visibility: "public"
|
|
2454
|
+
visibility: "public",
|
|
2455
|
+
...metadata
|
|
2054
2456
|
});
|
|
2055
2457
|
}
|
|
2056
2458
|
}
|
|
@@ -2203,7 +2605,7 @@ function getSupportedLanguages() {
|
|
|
2203
2605
|
// src/utils/ast-parser.ts
|
|
2204
2606
|
function parseFileExports(code, filePath) {
|
|
2205
2607
|
const parser = getParser(filePath);
|
|
2206
|
-
if (parser &&
|
|
2608
|
+
if (parser && parser.language !== "typescript" /* TypeScript */ && parser.language !== "javascript" /* JavaScript */) {
|
|
2207
2609
|
try {
|
|
2208
2610
|
const result = parser.parse(code, filePath);
|
|
2209
2611
|
return {
|
|
@@ -4324,8 +4726,10 @@ function getRepoMetadata(directory) {
|
|
|
4324
4726
|
getSeverityColor,
|
|
4325
4727
|
getSupportedLanguages,
|
|
4326
4728
|
getToolWeight,
|
|
4729
|
+
getWasmPath,
|
|
4327
4730
|
handleCLIError,
|
|
4328
4731
|
handleJSONOutput,
|
|
4732
|
+
initTreeSitter,
|
|
4329
4733
|
initializeParsers,
|
|
4330
4734
|
isFileSupported,
|
|
4331
4735
|
isSourceFile,
|
|
@@ -4343,6 +4747,7 @@ function getRepoMetadata(directory) {
|
|
|
4343
4747
|
saveScoreEntry,
|
|
4344
4748
|
scanEntries,
|
|
4345
4749
|
scanFiles,
|
|
4750
|
+
setupParser,
|
|
4346
4751
|
validateSpokeOutput,
|
|
4347
4752
|
validateWithSchema
|
|
4348
4753
|
});
|