@aiready/core 0.7.13 → 0.8.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/dist/index.d.mts +292 -4
- package/dist/index.d.ts +292 -4
- package/dist/index.js +531 -2
- package/dist/index.mjs +522 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22,7 +22,13 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
DEFAULT_EXCLUDE: () => DEFAULT_EXCLUDE,
|
|
24
24
|
DEFAULT_TOOL_WEIGHTS: () => DEFAULT_TOOL_WEIGHTS,
|
|
25
|
+
LANGUAGE_EXTENSIONS: () => LANGUAGE_EXTENSIONS,
|
|
26
|
+
Language: () => Language,
|
|
27
|
+
ParseError: () => ParseError,
|
|
28
|
+
ParserFactory: () => ParserFactory,
|
|
29
|
+
PythonParser: () => PythonParser,
|
|
25
30
|
TOOL_NAME_MAP: () => TOOL_NAME_MAP,
|
|
31
|
+
TypeScriptParser: () => TypeScriptParser,
|
|
26
32
|
calculateImportSimilarity: () => calculateImportSimilarity,
|
|
27
33
|
calculateOverallScore: () => calculateOverallScore,
|
|
28
34
|
estimateTokens: () => estimateTokens,
|
|
@@ -32,11 +38,14 @@ __export(index_exports, {
|
|
|
32
38
|
formatToolScore: () => formatToolScore,
|
|
33
39
|
getElapsedTime: () => getElapsedTime,
|
|
34
40
|
getFileExtension: () => getFileExtension,
|
|
41
|
+
getParser: () => getParser,
|
|
35
42
|
getRating: () => getRating,
|
|
36
43
|
getRatingDisplay: () => getRatingDisplay,
|
|
44
|
+
getSupportedLanguages: () => getSupportedLanguages,
|
|
37
45
|
getToolWeight: () => getToolWeight,
|
|
38
46
|
handleCLIError: () => handleCLIError,
|
|
39
47
|
handleJSONOutput: () => handleJSONOutput,
|
|
48
|
+
isFileSupported: () => isFileSupported,
|
|
40
49
|
isSourceFile: () => isSourceFile,
|
|
41
50
|
loadConfig: () => loadConfig,
|
|
42
51
|
loadMergedConfig: () => loadMergedConfig,
|
|
@@ -51,6 +60,37 @@ __export(index_exports, {
|
|
|
51
60
|
});
|
|
52
61
|
module.exports = __toCommonJS(index_exports);
|
|
53
62
|
|
|
63
|
+
// src/types/language.ts
|
|
64
|
+
var Language = /* @__PURE__ */ ((Language3) => {
|
|
65
|
+
Language3["TypeScript"] = "typescript";
|
|
66
|
+
Language3["JavaScript"] = "javascript";
|
|
67
|
+
Language3["Python"] = "python";
|
|
68
|
+
Language3["Java"] = "java";
|
|
69
|
+
Language3["Go"] = "go";
|
|
70
|
+
Language3["Rust"] = "rust";
|
|
71
|
+
Language3["CSharp"] = "csharp";
|
|
72
|
+
return Language3;
|
|
73
|
+
})(Language || {});
|
|
74
|
+
var LANGUAGE_EXTENSIONS = {
|
|
75
|
+
".ts": "typescript" /* TypeScript */,
|
|
76
|
+
".tsx": "typescript" /* TypeScript */,
|
|
77
|
+
".js": "javascript" /* JavaScript */,
|
|
78
|
+
".jsx": "javascript" /* JavaScript */,
|
|
79
|
+
".py": "python" /* Python */,
|
|
80
|
+
".java": "java" /* Java */,
|
|
81
|
+
".go": "go" /* Go */,
|
|
82
|
+
".rs": "rust" /* Rust */,
|
|
83
|
+
".cs": "csharp" /* CSharp */
|
|
84
|
+
};
|
|
85
|
+
var ParseError = class extends Error {
|
|
86
|
+
constructor(message, filePath, loc) {
|
|
87
|
+
super(message);
|
|
88
|
+
this.filePath = filePath;
|
|
89
|
+
this.loc = loc;
|
|
90
|
+
this.name = "ParseError";
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
54
94
|
// src/utils/file-scanner.ts
|
|
55
95
|
var import_glob = require("glob");
|
|
56
96
|
var import_promises = require("fs/promises");
|
|
@@ -104,8 +144,8 @@ var DEFAULT_EXCLUDE = [
|
|
|
104
144
|
async function scanFiles(options) {
|
|
105
145
|
const {
|
|
106
146
|
rootDir,
|
|
107
|
-
include = ["**/*.{ts,tsx,js,jsx,py,java}"],
|
|
108
|
-
//
|
|
147
|
+
include = ["**/*.{ts,tsx,js,jsx,py,java,go,rs,cs}"],
|
|
148
|
+
// Multi-language support
|
|
109
149
|
exclude
|
|
110
150
|
} = options;
|
|
111
151
|
const ignoreFilePath = (0, import_path.join)(rootDir || ".", ".aireadyignore");
|
|
@@ -575,11 +615,497 @@ function formatToolScore(output) {
|
|
|
575
615
|
}
|
|
576
616
|
return result;
|
|
577
617
|
}
|
|
618
|
+
|
|
619
|
+
// src/parsers/typescript-parser.ts
|
|
620
|
+
var import_typescript_estree2 = require("@typescript-eslint/typescript-estree");
|
|
621
|
+
var TypeScriptParser = class {
|
|
622
|
+
constructor() {
|
|
623
|
+
this.language = "typescript" /* TypeScript */;
|
|
624
|
+
this.extensions = [".ts", ".tsx", ".js", ".jsx"];
|
|
625
|
+
}
|
|
626
|
+
parse(code, filePath) {
|
|
627
|
+
try {
|
|
628
|
+
const isJavaScript = filePath.match(/\.jsx?$/i);
|
|
629
|
+
const ast = (0, import_typescript_estree2.parse)(code, {
|
|
630
|
+
loc: true,
|
|
631
|
+
range: true,
|
|
632
|
+
jsx: filePath.match(/\.[jt]sx$/i) !== null,
|
|
633
|
+
filePath,
|
|
634
|
+
sourceType: "module",
|
|
635
|
+
ecmaVersion: "latest"
|
|
636
|
+
});
|
|
637
|
+
const imports = this.extractImports(ast);
|
|
638
|
+
const exports2 = this.extractExports(ast, imports);
|
|
639
|
+
return {
|
|
640
|
+
exports: exports2,
|
|
641
|
+
imports,
|
|
642
|
+
language: isJavaScript ? "javascript" /* JavaScript */ : "typescript" /* TypeScript */,
|
|
643
|
+
warnings: []
|
|
644
|
+
};
|
|
645
|
+
} catch (error) {
|
|
646
|
+
const err = error;
|
|
647
|
+
throw new ParseError(
|
|
648
|
+
`Failed to parse ${filePath}: ${err.message}`,
|
|
649
|
+
filePath
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
getNamingConventions() {
|
|
654
|
+
return {
|
|
655
|
+
// camelCase for variables and functions
|
|
656
|
+
variablePattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
657
|
+
functionPattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
658
|
+
// PascalCase for classes
|
|
659
|
+
classPattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
660
|
+
// UPPER_CASE for constants
|
|
661
|
+
constantPattern: /^[A-Z][A-Z0-9_]*$/,
|
|
662
|
+
// Common exceptions (React hooks, etc.)
|
|
663
|
+
exceptions: ["__filename", "__dirname", "__esModule"]
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
canHandle(filePath) {
|
|
667
|
+
return this.extensions.some((ext) => filePath.toLowerCase().endsWith(ext));
|
|
668
|
+
}
|
|
669
|
+
extractImports(ast) {
|
|
670
|
+
const imports = [];
|
|
671
|
+
for (const node of ast.body) {
|
|
672
|
+
if (node.type === "ImportDeclaration") {
|
|
673
|
+
const specifiers = [];
|
|
674
|
+
let isTypeOnly = false;
|
|
675
|
+
if (node.importKind === "type") {
|
|
676
|
+
isTypeOnly = true;
|
|
677
|
+
}
|
|
678
|
+
for (const spec of node.specifiers) {
|
|
679
|
+
if (spec.type === "ImportSpecifier") {
|
|
680
|
+
const imported = spec.imported;
|
|
681
|
+
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
682
|
+
specifiers.push(name);
|
|
683
|
+
} else if (spec.type === "ImportDefaultSpecifier") {
|
|
684
|
+
specifiers.push("default");
|
|
685
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
686
|
+
specifiers.push("*");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
imports.push({
|
|
690
|
+
source: node.source.value,
|
|
691
|
+
specifiers,
|
|
692
|
+
isTypeOnly,
|
|
693
|
+
loc: node.loc ? {
|
|
694
|
+
start: { line: node.loc.start.line, column: node.loc.start.column },
|
|
695
|
+
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
696
|
+
} : void 0
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return imports;
|
|
701
|
+
}
|
|
702
|
+
extractExports(ast, imports) {
|
|
703
|
+
const exports2 = [];
|
|
704
|
+
const importedNames = new Set(
|
|
705
|
+
imports.flatMap((imp) => imp.specifiers.filter((s) => s !== "*" && s !== "default"))
|
|
706
|
+
);
|
|
707
|
+
for (const node of ast.body) {
|
|
708
|
+
if (node.type === "ExportNamedDeclaration" && node.declaration) {
|
|
709
|
+
const extracted = this.extractFromDeclaration(node.declaration, importedNames);
|
|
710
|
+
exports2.push(...extracted);
|
|
711
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
712
|
+
let name = "default";
|
|
713
|
+
let type = "default";
|
|
714
|
+
if (node.declaration.type === "FunctionDeclaration" && node.declaration.id) {
|
|
715
|
+
name = node.declaration.id.name;
|
|
716
|
+
type = "function";
|
|
717
|
+
} else if (node.declaration.type === "ClassDeclaration" && node.declaration.id) {
|
|
718
|
+
name = node.declaration.id.name;
|
|
719
|
+
type = "class";
|
|
720
|
+
}
|
|
721
|
+
exports2.push({
|
|
722
|
+
name,
|
|
723
|
+
type,
|
|
724
|
+
loc: node.loc ? {
|
|
725
|
+
start: { line: node.loc.start.line, column: node.loc.start.column },
|
|
726
|
+
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
727
|
+
} : void 0
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
return exports2;
|
|
732
|
+
}
|
|
733
|
+
extractFromDeclaration(declaration, importedNames) {
|
|
734
|
+
const exports2 = [];
|
|
735
|
+
if (declaration.type === "FunctionDeclaration" && declaration.id) {
|
|
736
|
+
exports2.push({
|
|
737
|
+
name: declaration.id.name,
|
|
738
|
+
type: "function",
|
|
739
|
+
parameters: declaration.params.map(
|
|
740
|
+
(p) => p.type === "Identifier" ? p.name : "unknown"
|
|
741
|
+
),
|
|
742
|
+
loc: declaration.loc ? {
|
|
743
|
+
start: {
|
|
744
|
+
line: declaration.loc.start.line,
|
|
745
|
+
column: declaration.loc.start.column
|
|
746
|
+
},
|
|
747
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
748
|
+
} : void 0
|
|
749
|
+
});
|
|
750
|
+
} else if (declaration.type === "ClassDeclaration" && declaration.id) {
|
|
751
|
+
exports2.push({
|
|
752
|
+
name: declaration.id.name,
|
|
753
|
+
type: "class",
|
|
754
|
+
loc: declaration.loc ? {
|
|
755
|
+
start: {
|
|
756
|
+
line: declaration.loc.start.line,
|
|
757
|
+
column: declaration.loc.start.column
|
|
758
|
+
},
|
|
759
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
760
|
+
} : void 0
|
|
761
|
+
});
|
|
762
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
763
|
+
for (const declarator of declaration.declarations) {
|
|
764
|
+
if (declarator.id.type === "Identifier") {
|
|
765
|
+
exports2.push({
|
|
766
|
+
name: declarator.id.name,
|
|
767
|
+
type: "const",
|
|
768
|
+
loc: declarator.loc ? {
|
|
769
|
+
start: {
|
|
770
|
+
line: declarator.loc.start.line,
|
|
771
|
+
column: declarator.loc.start.column
|
|
772
|
+
},
|
|
773
|
+
end: {
|
|
774
|
+
line: declarator.loc.end.line,
|
|
775
|
+
column: declarator.loc.end.column
|
|
776
|
+
}
|
|
777
|
+
} : void 0
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
} else if (declaration.type === "TSTypeAliasDeclaration") {
|
|
782
|
+
exports2.push({
|
|
783
|
+
name: declaration.id.name,
|
|
784
|
+
type: "type",
|
|
785
|
+
loc: declaration.loc ? {
|
|
786
|
+
start: {
|
|
787
|
+
line: declaration.loc.start.line,
|
|
788
|
+
column: declaration.loc.start.column
|
|
789
|
+
},
|
|
790
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
791
|
+
} : void 0
|
|
792
|
+
});
|
|
793
|
+
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
794
|
+
exports2.push({
|
|
795
|
+
name: declaration.id.name,
|
|
796
|
+
type: "interface",
|
|
797
|
+
loc: declaration.loc ? {
|
|
798
|
+
start: {
|
|
799
|
+
line: declaration.loc.start.line,
|
|
800
|
+
column: declaration.loc.start.column
|
|
801
|
+
},
|
|
802
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
803
|
+
} : void 0
|
|
804
|
+
});
|
|
805
|
+
}
|
|
806
|
+
return exports2;
|
|
807
|
+
}
|
|
808
|
+
};
|
|
809
|
+
|
|
810
|
+
// src/parsers/python-parser.ts
|
|
811
|
+
var PythonParser = class {
|
|
812
|
+
constructor() {
|
|
813
|
+
this.language = "python" /* Python */;
|
|
814
|
+
this.extensions = [".py"];
|
|
815
|
+
this.parser = null;
|
|
816
|
+
this.initialized = false;
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Initialize the tree-sitter parser
|
|
820
|
+
* This is async because tree-sitter WASM needs to be loaded
|
|
821
|
+
*/
|
|
822
|
+
async initialize() {
|
|
823
|
+
if (this.initialized) return;
|
|
824
|
+
try {
|
|
825
|
+
this.initialized = true;
|
|
826
|
+
} catch (error) {
|
|
827
|
+
throw new Error(`Failed to initialize Python parser: ${error.message}`);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
parse(code, filePath) {
|
|
831
|
+
try {
|
|
832
|
+
const imports = this.extractImportsRegex(code, filePath);
|
|
833
|
+
const exports2 = this.extractExportsRegex(code, filePath);
|
|
834
|
+
return {
|
|
835
|
+
exports: exports2,
|
|
836
|
+
imports,
|
|
837
|
+
language: "python" /* Python */,
|
|
838
|
+
warnings: ["Python parsing is currently using regex-based extraction. Tree-sitter support coming soon."]
|
|
839
|
+
};
|
|
840
|
+
} catch (error) {
|
|
841
|
+
throw new ParseError(
|
|
842
|
+
`Failed to parse Python file ${filePath}: ${error.message}`,
|
|
843
|
+
filePath
|
|
844
|
+
);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
getNamingConventions() {
|
|
848
|
+
return {
|
|
849
|
+
// snake_case for variables and functions
|
|
850
|
+
variablePattern: /^[a-z_][a-z0-9_]*$/,
|
|
851
|
+
functionPattern: /^[a-z_][a-z0-9_]*$/,
|
|
852
|
+
// PascalCase for classes
|
|
853
|
+
classPattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
854
|
+
// UPPER_CASE for constants
|
|
855
|
+
constantPattern: /^[A-Z][A-Z0-9_]*$/,
|
|
856
|
+
// Python special methods and common exceptions
|
|
857
|
+
exceptions: [
|
|
858
|
+
"__init__",
|
|
859
|
+
"__str__",
|
|
860
|
+
"__repr__",
|
|
861
|
+
"__name__",
|
|
862
|
+
"__main__",
|
|
863
|
+
"__file__",
|
|
864
|
+
"__doc__",
|
|
865
|
+
"__all__",
|
|
866
|
+
"__version__",
|
|
867
|
+
"__author__",
|
|
868
|
+
"__dict__",
|
|
869
|
+
"__class__",
|
|
870
|
+
"__module__",
|
|
871
|
+
"__bases__"
|
|
872
|
+
]
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
canHandle(filePath) {
|
|
876
|
+
return filePath.toLowerCase().endsWith(".py");
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Regex-based import extraction (temporary implementation)
|
|
880
|
+
*/
|
|
881
|
+
extractImportsRegex(code, filePath) {
|
|
882
|
+
const imports = [];
|
|
883
|
+
const lines = code.split("\n");
|
|
884
|
+
const importRegex = /^\s*import\s+([a-zA-Z0-9_., ]+)/;
|
|
885
|
+
const fromImportRegex = /^\s*from\s+([a-zA-Z0-9_.]+)\s+import\s+(.+)/;
|
|
886
|
+
lines.forEach((line, idx) => {
|
|
887
|
+
if (line.trim().startsWith("#")) return;
|
|
888
|
+
const importMatch = line.match(importRegex);
|
|
889
|
+
if (importMatch) {
|
|
890
|
+
const modules = importMatch[1].split(",").map((m) => m.trim().split(" as ")[0]);
|
|
891
|
+
modules.forEach((module2) => {
|
|
892
|
+
imports.push({
|
|
893
|
+
source: module2,
|
|
894
|
+
specifiers: [module2],
|
|
895
|
+
loc: {
|
|
896
|
+
start: { line: idx + 1, column: 0 },
|
|
897
|
+
end: { line: idx + 1, column: line.length }
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
});
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
const fromMatch = line.match(fromImportRegex);
|
|
904
|
+
if (fromMatch) {
|
|
905
|
+
const module2 = fromMatch[1];
|
|
906
|
+
const imports_str = fromMatch[2];
|
|
907
|
+
if (imports_str.trim() === "*") {
|
|
908
|
+
imports.push({
|
|
909
|
+
source: module2,
|
|
910
|
+
specifiers: ["*"],
|
|
911
|
+
loc: {
|
|
912
|
+
start: { line: idx + 1, column: 0 },
|
|
913
|
+
end: { line: idx + 1, column: line.length }
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
const specifiers = imports_str.split(",").map((s) => s.trim().split(" as ")[0]);
|
|
919
|
+
imports.push({
|
|
920
|
+
source: module2,
|
|
921
|
+
specifiers,
|
|
922
|
+
loc: {
|
|
923
|
+
start: { line: idx + 1, column: 0 },
|
|
924
|
+
end: { line: idx + 1, column: line.length }
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
return imports;
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Regex-based export extraction (temporary implementation)
|
|
933
|
+
*
|
|
934
|
+
* Python doesn't have explicit exports like JavaScript.
|
|
935
|
+
* We extract:
|
|
936
|
+
* - Functions defined at module level (def)
|
|
937
|
+
* - Classes defined at module level (class)
|
|
938
|
+
* - Variables in __all__ list
|
|
939
|
+
*/
|
|
940
|
+
extractExportsRegex(code, filePath) {
|
|
941
|
+
const exports2 = [];
|
|
942
|
+
const lines = code.split("\n");
|
|
943
|
+
const functionRegex = /^def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/;
|
|
944
|
+
const classRegex = /^class\s+([a-zA-Z_][a-zA-Z0-9_]*)/;
|
|
945
|
+
const allRegex = /__all__\s*=\s*\[([^\]]+)\]/;
|
|
946
|
+
let inClass = false;
|
|
947
|
+
let classIndent = 0;
|
|
948
|
+
lines.forEach((line, idx) => {
|
|
949
|
+
const indent = line.search(/\S/);
|
|
950
|
+
if (line.match(classRegex)) {
|
|
951
|
+
inClass = true;
|
|
952
|
+
classIndent = indent;
|
|
953
|
+
} else if (inClass && indent <= classIndent && line.trim()) {
|
|
954
|
+
inClass = false;
|
|
955
|
+
}
|
|
956
|
+
if (inClass) {
|
|
957
|
+
const classMatch = line.match(classRegex);
|
|
958
|
+
if (classMatch) {
|
|
959
|
+
exports2.push({
|
|
960
|
+
name: classMatch[1],
|
|
961
|
+
type: "class",
|
|
962
|
+
loc: {
|
|
963
|
+
start: { line: idx + 1, column: indent },
|
|
964
|
+
end: { line: idx + 1, column: line.length }
|
|
965
|
+
}
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const funcMatch = line.match(functionRegex);
|
|
971
|
+
if (funcMatch && indent === 0) {
|
|
972
|
+
const name = funcMatch[1];
|
|
973
|
+
if (!name.startsWith("_") || name.startsWith("__")) {
|
|
974
|
+
exports2.push({
|
|
975
|
+
name,
|
|
976
|
+
type: "function",
|
|
977
|
+
loc: {
|
|
978
|
+
start: { line: idx + 1, column: 0 },
|
|
979
|
+
end: { line: idx + 1, column: line.length }
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
const allMatch = line.match(allRegex);
|
|
985
|
+
if (allMatch) {
|
|
986
|
+
const names = allMatch[1].split(",").map((n) => n.trim().replace(/['"]/g, ""));
|
|
987
|
+
names.forEach((name) => {
|
|
988
|
+
if (name && !exports2.find((e) => e.name === name)) {
|
|
989
|
+
exports2.push({
|
|
990
|
+
name,
|
|
991
|
+
type: "variable",
|
|
992
|
+
loc: {
|
|
993
|
+
start: { line: idx + 1, column: 0 },
|
|
994
|
+
end: { line: idx + 1, column: line.length }
|
|
995
|
+
}
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
});
|
|
1001
|
+
return exports2;
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
// src/parsers/parser-factory.ts
|
|
1006
|
+
var ParserFactory = class _ParserFactory {
|
|
1007
|
+
constructor() {
|
|
1008
|
+
this.parsers = /* @__PURE__ */ new Map();
|
|
1009
|
+
this.extensionMap = new Map(
|
|
1010
|
+
Object.entries(LANGUAGE_EXTENSIONS).map(([ext, lang]) => [ext, lang])
|
|
1011
|
+
);
|
|
1012
|
+
this.registerParser(new TypeScriptParser());
|
|
1013
|
+
this.registerParser(new PythonParser());
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Get singleton instance
|
|
1017
|
+
*/
|
|
1018
|
+
static getInstance() {
|
|
1019
|
+
if (!_ParserFactory.instance) {
|
|
1020
|
+
_ParserFactory.instance = new _ParserFactory();
|
|
1021
|
+
}
|
|
1022
|
+
return _ParserFactory.instance;
|
|
1023
|
+
}
|
|
1024
|
+
/**
|
|
1025
|
+
* Register a language parser
|
|
1026
|
+
*/
|
|
1027
|
+
registerParser(parser) {
|
|
1028
|
+
this.parsers.set(parser.language, parser);
|
|
1029
|
+
parser.extensions.forEach((ext) => {
|
|
1030
|
+
this.extensionMap.set(ext, parser.language);
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Get parser for a specific language
|
|
1035
|
+
*/
|
|
1036
|
+
getParserForLanguage(language) {
|
|
1037
|
+
return this.parsers.get(language) || null;
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Get parser for a file based on its extension
|
|
1041
|
+
*/
|
|
1042
|
+
getParserForFile(filePath) {
|
|
1043
|
+
const ext = this.getFileExtension(filePath);
|
|
1044
|
+
const language = this.extensionMap.get(ext);
|
|
1045
|
+
if (!language) {
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
return this.parsers.get(language) || null;
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Check if a file is supported
|
|
1052
|
+
*/
|
|
1053
|
+
isSupported(filePath) {
|
|
1054
|
+
return this.getParserForFile(filePath) !== null;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Get all registered languages
|
|
1058
|
+
*/
|
|
1059
|
+
getSupportedLanguages() {
|
|
1060
|
+
return Array.from(this.parsers.keys());
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Get all supported file extensions
|
|
1064
|
+
*/
|
|
1065
|
+
getSupportedExtensions() {
|
|
1066
|
+
return Array.from(this.extensionMap.keys());
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Get language for a file
|
|
1070
|
+
*/
|
|
1071
|
+
getLanguageForFile(filePath) {
|
|
1072
|
+
const ext = this.getFileExtension(filePath);
|
|
1073
|
+
return this.extensionMap.get(ext) || null;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Extract file extension (with dot)
|
|
1077
|
+
*/
|
|
1078
|
+
getFileExtension(filePath) {
|
|
1079
|
+
const match = filePath.match(/\.[^.]+$/);
|
|
1080
|
+
return match ? match[0].toLowerCase() : "";
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Reset factory (useful for testing)
|
|
1084
|
+
*/
|
|
1085
|
+
static reset() {
|
|
1086
|
+
_ParserFactory.instance = new _ParserFactory();
|
|
1087
|
+
}
|
|
1088
|
+
};
|
|
1089
|
+
function getParser(filePath) {
|
|
1090
|
+
return ParserFactory.getInstance().getParserForFile(filePath);
|
|
1091
|
+
}
|
|
1092
|
+
function isFileSupported(filePath) {
|
|
1093
|
+
return ParserFactory.getInstance().isSupported(filePath);
|
|
1094
|
+
}
|
|
1095
|
+
function getSupportedLanguages() {
|
|
1096
|
+
return ParserFactory.getInstance().getSupportedLanguages();
|
|
1097
|
+
}
|
|
578
1098
|
// Annotate the CommonJS export names for ESM import in node:
|
|
579
1099
|
0 && (module.exports = {
|
|
580
1100
|
DEFAULT_EXCLUDE,
|
|
581
1101
|
DEFAULT_TOOL_WEIGHTS,
|
|
1102
|
+
LANGUAGE_EXTENSIONS,
|
|
1103
|
+
Language,
|
|
1104
|
+
ParseError,
|
|
1105
|
+
ParserFactory,
|
|
1106
|
+
PythonParser,
|
|
582
1107
|
TOOL_NAME_MAP,
|
|
1108
|
+
TypeScriptParser,
|
|
583
1109
|
calculateImportSimilarity,
|
|
584
1110
|
calculateOverallScore,
|
|
585
1111
|
estimateTokens,
|
|
@@ -589,11 +1115,14 @@ function formatToolScore(output) {
|
|
|
589
1115
|
formatToolScore,
|
|
590
1116
|
getElapsedTime,
|
|
591
1117
|
getFileExtension,
|
|
1118
|
+
getParser,
|
|
592
1119
|
getRating,
|
|
593
1120
|
getRatingDisplay,
|
|
1121
|
+
getSupportedLanguages,
|
|
594
1122
|
getToolWeight,
|
|
595
1123
|
handleCLIError,
|
|
596
1124
|
handleJSONOutput,
|
|
1125
|
+
isFileSupported,
|
|
597
1126
|
isSourceFile,
|
|
598
1127
|
loadConfig,
|
|
599
1128
|
loadMergedConfig,
|