@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.mjs
CHANGED
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
// src/types/language.ts
|
|
2
|
+
var Language = /* @__PURE__ */ ((Language3) => {
|
|
3
|
+
Language3["TypeScript"] = "typescript";
|
|
4
|
+
Language3["JavaScript"] = "javascript";
|
|
5
|
+
Language3["Python"] = "python";
|
|
6
|
+
Language3["Java"] = "java";
|
|
7
|
+
Language3["Go"] = "go";
|
|
8
|
+
Language3["Rust"] = "rust";
|
|
9
|
+
Language3["CSharp"] = "csharp";
|
|
10
|
+
return Language3;
|
|
11
|
+
})(Language || {});
|
|
12
|
+
var LANGUAGE_EXTENSIONS = {
|
|
13
|
+
".ts": "typescript" /* TypeScript */,
|
|
14
|
+
".tsx": "typescript" /* TypeScript */,
|
|
15
|
+
".js": "javascript" /* JavaScript */,
|
|
16
|
+
".jsx": "javascript" /* JavaScript */,
|
|
17
|
+
".py": "python" /* Python */,
|
|
18
|
+
".java": "java" /* Java */,
|
|
19
|
+
".go": "go" /* Go */,
|
|
20
|
+
".rs": "rust" /* Rust */,
|
|
21
|
+
".cs": "csharp" /* CSharp */
|
|
22
|
+
};
|
|
23
|
+
var ParseError = class extends Error {
|
|
24
|
+
constructor(message, filePath, loc) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.filePath = filePath;
|
|
27
|
+
this.loc = loc;
|
|
28
|
+
this.name = "ParseError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
1
32
|
// src/utils/file-scanner.ts
|
|
2
33
|
import { glob } from "glob";
|
|
3
34
|
import { readFile } from "fs/promises";
|
|
@@ -51,8 +82,8 @@ var DEFAULT_EXCLUDE = [
|
|
|
51
82
|
async function scanFiles(options) {
|
|
52
83
|
const {
|
|
53
84
|
rootDir,
|
|
54
|
-
include = ["**/*.{ts,tsx,js,jsx,py,java}"],
|
|
55
|
-
//
|
|
85
|
+
include = ["**/*.{ts,tsx,js,jsx,py,java,go,rs,cs}"],
|
|
86
|
+
// Multi-language support
|
|
56
87
|
exclude
|
|
57
88
|
} = options;
|
|
58
89
|
const ignoreFilePath = join(rootDir || ".", ".aireadyignore");
|
|
@@ -522,10 +553,496 @@ function formatToolScore(output) {
|
|
|
522
553
|
}
|
|
523
554
|
return result;
|
|
524
555
|
}
|
|
556
|
+
|
|
557
|
+
// src/parsers/typescript-parser.ts
|
|
558
|
+
import { parse as parse2 } from "@typescript-eslint/typescript-estree";
|
|
559
|
+
var TypeScriptParser = class {
|
|
560
|
+
constructor() {
|
|
561
|
+
this.language = "typescript" /* TypeScript */;
|
|
562
|
+
this.extensions = [".ts", ".tsx", ".js", ".jsx"];
|
|
563
|
+
}
|
|
564
|
+
parse(code, filePath) {
|
|
565
|
+
try {
|
|
566
|
+
const isJavaScript = filePath.match(/\.jsx?$/i);
|
|
567
|
+
const ast = parse2(code, {
|
|
568
|
+
loc: true,
|
|
569
|
+
range: true,
|
|
570
|
+
jsx: filePath.match(/\.[jt]sx$/i) !== null,
|
|
571
|
+
filePath,
|
|
572
|
+
sourceType: "module",
|
|
573
|
+
ecmaVersion: "latest"
|
|
574
|
+
});
|
|
575
|
+
const imports = this.extractImports(ast);
|
|
576
|
+
const exports = this.extractExports(ast, imports);
|
|
577
|
+
return {
|
|
578
|
+
exports,
|
|
579
|
+
imports,
|
|
580
|
+
language: isJavaScript ? "javascript" /* JavaScript */ : "typescript" /* TypeScript */,
|
|
581
|
+
warnings: []
|
|
582
|
+
};
|
|
583
|
+
} catch (error) {
|
|
584
|
+
const err = error;
|
|
585
|
+
throw new ParseError(
|
|
586
|
+
`Failed to parse ${filePath}: ${err.message}`,
|
|
587
|
+
filePath
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
getNamingConventions() {
|
|
592
|
+
return {
|
|
593
|
+
// camelCase for variables and functions
|
|
594
|
+
variablePattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
595
|
+
functionPattern: /^[a-z][a-zA-Z0-9]*$/,
|
|
596
|
+
// PascalCase for classes
|
|
597
|
+
classPattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
598
|
+
// UPPER_CASE for constants
|
|
599
|
+
constantPattern: /^[A-Z][A-Z0-9_]*$/,
|
|
600
|
+
// Common exceptions (React hooks, etc.)
|
|
601
|
+
exceptions: ["__filename", "__dirname", "__esModule"]
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
canHandle(filePath) {
|
|
605
|
+
return this.extensions.some((ext) => filePath.toLowerCase().endsWith(ext));
|
|
606
|
+
}
|
|
607
|
+
extractImports(ast) {
|
|
608
|
+
const imports = [];
|
|
609
|
+
for (const node of ast.body) {
|
|
610
|
+
if (node.type === "ImportDeclaration") {
|
|
611
|
+
const specifiers = [];
|
|
612
|
+
let isTypeOnly = false;
|
|
613
|
+
if (node.importKind === "type") {
|
|
614
|
+
isTypeOnly = true;
|
|
615
|
+
}
|
|
616
|
+
for (const spec of node.specifiers) {
|
|
617
|
+
if (spec.type === "ImportSpecifier") {
|
|
618
|
+
const imported = spec.imported;
|
|
619
|
+
const name = imported.type === "Identifier" ? imported.name : imported.value;
|
|
620
|
+
specifiers.push(name);
|
|
621
|
+
} else if (spec.type === "ImportDefaultSpecifier") {
|
|
622
|
+
specifiers.push("default");
|
|
623
|
+
} else if (spec.type === "ImportNamespaceSpecifier") {
|
|
624
|
+
specifiers.push("*");
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
imports.push({
|
|
628
|
+
source: node.source.value,
|
|
629
|
+
specifiers,
|
|
630
|
+
isTypeOnly,
|
|
631
|
+
loc: node.loc ? {
|
|
632
|
+
start: { line: node.loc.start.line, column: node.loc.start.column },
|
|
633
|
+
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
634
|
+
} : void 0
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return imports;
|
|
639
|
+
}
|
|
640
|
+
extractExports(ast, imports) {
|
|
641
|
+
const exports = [];
|
|
642
|
+
const importedNames = new Set(
|
|
643
|
+
imports.flatMap((imp) => imp.specifiers.filter((s) => s !== "*" && s !== "default"))
|
|
644
|
+
);
|
|
645
|
+
for (const node of ast.body) {
|
|
646
|
+
if (node.type === "ExportNamedDeclaration" && node.declaration) {
|
|
647
|
+
const extracted = this.extractFromDeclaration(node.declaration, importedNames);
|
|
648
|
+
exports.push(...extracted);
|
|
649
|
+
} else if (node.type === "ExportDefaultDeclaration") {
|
|
650
|
+
let name = "default";
|
|
651
|
+
let type = "default";
|
|
652
|
+
if (node.declaration.type === "FunctionDeclaration" && node.declaration.id) {
|
|
653
|
+
name = node.declaration.id.name;
|
|
654
|
+
type = "function";
|
|
655
|
+
} else if (node.declaration.type === "ClassDeclaration" && node.declaration.id) {
|
|
656
|
+
name = node.declaration.id.name;
|
|
657
|
+
type = "class";
|
|
658
|
+
}
|
|
659
|
+
exports.push({
|
|
660
|
+
name,
|
|
661
|
+
type,
|
|
662
|
+
loc: node.loc ? {
|
|
663
|
+
start: { line: node.loc.start.line, column: node.loc.start.column },
|
|
664
|
+
end: { line: node.loc.end.line, column: node.loc.end.column }
|
|
665
|
+
} : void 0
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return exports;
|
|
670
|
+
}
|
|
671
|
+
extractFromDeclaration(declaration, importedNames) {
|
|
672
|
+
const exports = [];
|
|
673
|
+
if (declaration.type === "FunctionDeclaration" && declaration.id) {
|
|
674
|
+
exports.push({
|
|
675
|
+
name: declaration.id.name,
|
|
676
|
+
type: "function",
|
|
677
|
+
parameters: declaration.params.map(
|
|
678
|
+
(p) => p.type === "Identifier" ? p.name : "unknown"
|
|
679
|
+
),
|
|
680
|
+
loc: declaration.loc ? {
|
|
681
|
+
start: {
|
|
682
|
+
line: declaration.loc.start.line,
|
|
683
|
+
column: declaration.loc.start.column
|
|
684
|
+
},
|
|
685
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
686
|
+
} : void 0
|
|
687
|
+
});
|
|
688
|
+
} else if (declaration.type === "ClassDeclaration" && declaration.id) {
|
|
689
|
+
exports.push({
|
|
690
|
+
name: declaration.id.name,
|
|
691
|
+
type: "class",
|
|
692
|
+
loc: declaration.loc ? {
|
|
693
|
+
start: {
|
|
694
|
+
line: declaration.loc.start.line,
|
|
695
|
+
column: declaration.loc.start.column
|
|
696
|
+
},
|
|
697
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
698
|
+
} : void 0
|
|
699
|
+
});
|
|
700
|
+
} else if (declaration.type === "VariableDeclaration") {
|
|
701
|
+
for (const declarator of declaration.declarations) {
|
|
702
|
+
if (declarator.id.type === "Identifier") {
|
|
703
|
+
exports.push({
|
|
704
|
+
name: declarator.id.name,
|
|
705
|
+
type: "const",
|
|
706
|
+
loc: declarator.loc ? {
|
|
707
|
+
start: {
|
|
708
|
+
line: declarator.loc.start.line,
|
|
709
|
+
column: declarator.loc.start.column
|
|
710
|
+
},
|
|
711
|
+
end: {
|
|
712
|
+
line: declarator.loc.end.line,
|
|
713
|
+
column: declarator.loc.end.column
|
|
714
|
+
}
|
|
715
|
+
} : void 0
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
} else if (declaration.type === "TSTypeAliasDeclaration") {
|
|
720
|
+
exports.push({
|
|
721
|
+
name: declaration.id.name,
|
|
722
|
+
type: "type",
|
|
723
|
+
loc: declaration.loc ? {
|
|
724
|
+
start: {
|
|
725
|
+
line: declaration.loc.start.line,
|
|
726
|
+
column: declaration.loc.start.column
|
|
727
|
+
},
|
|
728
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
729
|
+
} : void 0
|
|
730
|
+
});
|
|
731
|
+
} else if (declaration.type === "TSInterfaceDeclaration") {
|
|
732
|
+
exports.push({
|
|
733
|
+
name: declaration.id.name,
|
|
734
|
+
type: "interface",
|
|
735
|
+
loc: declaration.loc ? {
|
|
736
|
+
start: {
|
|
737
|
+
line: declaration.loc.start.line,
|
|
738
|
+
column: declaration.loc.start.column
|
|
739
|
+
},
|
|
740
|
+
end: { line: declaration.loc.end.line, column: declaration.loc.end.column }
|
|
741
|
+
} : void 0
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
return exports;
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
|
|
748
|
+
// src/parsers/python-parser.ts
|
|
749
|
+
var PythonParser = class {
|
|
750
|
+
constructor() {
|
|
751
|
+
this.language = "python" /* Python */;
|
|
752
|
+
this.extensions = [".py"];
|
|
753
|
+
this.parser = null;
|
|
754
|
+
this.initialized = false;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Initialize the tree-sitter parser
|
|
758
|
+
* This is async because tree-sitter WASM needs to be loaded
|
|
759
|
+
*/
|
|
760
|
+
async initialize() {
|
|
761
|
+
if (this.initialized) return;
|
|
762
|
+
try {
|
|
763
|
+
this.initialized = true;
|
|
764
|
+
} catch (error) {
|
|
765
|
+
throw new Error(`Failed to initialize Python parser: ${error.message}`);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
parse(code, filePath) {
|
|
769
|
+
try {
|
|
770
|
+
const imports = this.extractImportsRegex(code, filePath);
|
|
771
|
+
const exports = this.extractExportsRegex(code, filePath);
|
|
772
|
+
return {
|
|
773
|
+
exports,
|
|
774
|
+
imports,
|
|
775
|
+
language: "python" /* Python */,
|
|
776
|
+
warnings: ["Python parsing is currently using regex-based extraction. Tree-sitter support coming soon."]
|
|
777
|
+
};
|
|
778
|
+
} catch (error) {
|
|
779
|
+
throw new ParseError(
|
|
780
|
+
`Failed to parse Python file ${filePath}: ${error.message}`,
|
|
781
|
+
filePath
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
getNamingConventions() {
|
|
786
|
+
return {
|
|
787
|
+
// snake_case for variables and functions
|
|
788
|
+
variablePattern: /^[a-z_][a-z0-9_]*$/,
|
|
789
|
+
functionPattern: /^[a-z_][a-z0-9_]*$/,
|
|
790
|
+
// PascalCase for classes
|
|
791
|
+
classPattern: /^[A-Z][a-zA-Z0-9]*$/,
|
|
792
|
+
// UPPER_CASE for constants
|
|
793
|
+
constantPattern: /^[A-Z][A-Z0-9_]*$/,
|
|
794
|
+
// Python special methods and common exceptions
|
|
795
|
+
exceptions: [
|
|
796
|
+
"__init__",
|
|
797
|
+
"__str__",
|
|
798
|
+
"__repr__",
|
|
799
|
+
"__name__",
|
|
800
|
+
"__main__",
|
|
801
|
+
"__file__",
|
|
802
|
+
"__doc__",
|
|
803
|
+
"__all__",
|
|
804
|
+
"__version__",
|
|
805
|
+
"__author__",
|
|
806
|
+
"__dict__",
|
|
807
|
+
"__class__",
|
|
808
|
+
"__module__",
|
|
809
|
+
"__bases__"
|
|
810
|
+
]
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
canHandle(filePath) {
|
|
814
|
+
return filePath.toLowerCase().endsWith(".py");
|
|
815
|
+
}
|
|
816
|
+
/**
|
|
817
|
+
* Regex-based import extraction (temporary implementation)
|
|
818
|
+
*/
|
|
819
|
+
extractImportsRegex(code, filePath) {
|
|
820
|
+
const imports = [];
|
|
821
|
+
const lines = code.split("\n");
|
|
822
|
+
const importRegex = /^\s*import\s+([a-zA-Z0-9_., ]+)/;
|
|
823
|
+
const fromImportRegex = /^\s*from\s+([a-zA-Z0-9_.]+)\s+import\s+(.+)/;
|
|
824
|
+
lines.forEach((line, idx) => {
|
|
825
|
+
if (line.trim().startsWith("#")) return;
|
|
826
|
+
const importMatch = line.match(importRegex);
|
|
827
|
+
if (importMatch) {
|
|
828
|
+
const modules = importMatch[1].split(",").map((m) => m.trim().split(" as ")[0]);
|
|
829
|
+
modules.forEach((module) => {
|
|
830
|
+
imports.push({
|
|
831
|
+
source: module,
|
|
832
|
+
specifiers: [module],
|
|
833
|
+
loc: {
|
|
834
|
+
start: { line: idx + 1, column: 0 },
|
|
835
|
+
end: { line: idx + 1, column: line.length }
|
|
836
|
+
}
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const fromMatch = line.match(fromImportRegex);
|
|
842
|
+
if (fromMatch) {
|
|
843
|
+
const module = fromMatch[1];
|
|
844
|
+
const imports_str = fromMatch[2];
|
|
845
|
+
if (imports_str.trim() === "*") {
|
|
846
|
+
imports.push({
|
|
847
|
+
source: module,
|
|
848
|
+
specifiers: ["*"],
|
|
849
|
+
loc: {
|
|
850
|
+
start: { line: idx + 1, column: 0 },
|
|
851
|
+
end: { line: idx + 1, column: line.length }
|
|
852
|
+
}
|
|
853
|
+
});
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
const specifiers = imports_str.split(",").map((s) => s.trim().split(" as ")[0]);
|
|
857
|
+
imports.push({
|
|
858
|
+
source: module,
|
|
859
|
+
specifiers,
|
|
860
|
+
loc: {
|
|
861
|
+
start: { line: idx + 1, column: 0 },
|
|
862
|
+
end: { line: idx + 1, column: line.length }
|
|
863
|
+
}
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
return imports;
|
|
868
|
+
}
|
|
869
|
+
/**
|
|
870
|
+
* Regex-based export extraction (temporary implementation)
|
|
871
|
+
*
|
|
872
|
+
* Python doesn't have explicit exports like JavaScript.
|
|
873
|
+
* We extract:
|
|
874
|
+
* - Functions defined at module level (def)
|
|
875
|
+
* - Classes defined at module level (class)
|
|
876
|
+
* - Variables in __all__ list
|
|
877
|
+
*/
|
|
878
|
+
extractExportsRegex(code, filePath) {
|
|
879
|
+
const exports = [];
|
|
880
|
+
const lines = code.split("\n");
|
|
881
|
+
const functionRegex = /^def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/;
|
|
882
|
+
const classRegex = /^class\s+([a-zA-Z_][a-zA-Z0-9_]*)/;
|
|
883
|
+
const allRegex = /__all__\s*=\s*\[([^\]]+)\]/;
|
|
884
|
+
let inClass = false;
|
|
885
|
+
let classIndent = 0;
|
|
886
|
+
lines.forEach((line, idx) => {
|
|
887
|
+
const indent = line.search(/\S/);
|
|
888
|
+
if (line.match(classRegex)) {
|
|
889
|
+
inClass = true;
|
|
890
|
+
classIndent = indent;
|
|
891
|
+
} else if (inClass && indent <= classIndent && line.trim()) {
|
|
892
|
+
inClass = false;
|
|
893
|
+
}
|
|
894
|
+
if (inClass) {
|
|
895
|
+
const classMatch = line.match(classRegex);
|
|
896
|
+
if (classMatch) {
|
|
897
|
+
exports.push({
|
|
898
|
+
name: classMatch[1],
|
|
899
|
+
type: "class",
|
|
900
|
+
loc: {
|
|
901
|
+
start: { line: idx + 1, column: indent },
|
|
902
|
+
end: { line: idx + 1, column: line.length }
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
return;
|
|
907
|
+
}
|
|
908
|
+
const funcMatch = line.match(functionRegex);
|
|
909
|
+
if (funcMatch && indent === 0) {
|
|
910
|
+
const name = funcMatch[1];
|
|
911
|
+
if (!name.startsWith("_") || name.startsWith("__")) {
|
|
912
|
+
exports.push({
|
|
913
|
+
name,
|
|
914
|
+
type: "function",
|
|
915
|
+
loc: {
|
|
916
|
+
start: { line: idx + 1, column: 0 },
|
|
917
|
+
end: { line: idx + 1, column: line.length }
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
const allMatch = line.match(allRegex);
|
|
923
|
+
if (allMatch) {
|
|
924
|
+
const names = allMatch[1].split(",").map((n) => n.trim().replace(/['"]/g, ""));
|
|
925
|
+
names.forEach((name) => {
|
|
926
|
+
if (name && !exports.find((e) => e.name === name)) {
|
|
927
|
+
exports.push({
|
|
928
|
+
name,
|
|
929
|
+
type: "variable",
|
|
930
|
+
loc: {
|
|
931
|
+
start: { line: idx + 1, column: 0 },
|
|
932
|
+
end: { line: idx + 1, column: line.length }
|
|
933
|
+
}
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
return exports;
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
|
|
943
|
+
// src/parsers/parser-factory.ts
|
|
944
|
+
var ParserFactory = class _ParserFactory {
|
|
945
|
+
constructor() {
|
|
946
|
+
this.parsers = /* @__PURE__ */ new Map();
|
|
947
|
+
this.extensionMap = new Map(
|
|
948
|
+
Object.entries(LANGUAGE_EXTENSIONS).map(([ext, lang]) => [ext, lang])
|
|
949
|
+
);
|
|
950
|
+
this.registerParser(new TypeScriptParser());
|
|
951
|
+
this.registerParser(new PythonParser());
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Get singleton instance
|
|
955
|
+
*/
|
|
956
|
+
static getInstance() {
|
|
957
|
+
if (!_ParserFactory.instance) {
|
|
958
|
+
_ParserFactory.instance = new _ParserFactory();
|
|
959
|
+
}
|
|
960
|
+
return _ParserFactory.instance;
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Register a language parser
|
|
964
|
+
*/
|
|
965
|
+
registerParser(parser) {
|
|
966
|
+
this.parsers.set(parser.language, parser);
|
|
967
|
+
parser.extensions.forEach((ext) => {
|
|
968
|
+
this.extensionMap.set(ext, parser.language);
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Get parser for a specific language
|
|
973
|
+
*/
|
|
974
|
+
getParserForLanguage(language) {
|
|
975
|
+
return this.parsers.get(language) || null;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Get parser for a file based on its extension
|
|
979
|
+
*/
|
|
980
|
+
getParserForFile(filePath) {
|
|
981
|
+
const ext = this.getFileExtension(filePath);
|
|
982
|
+
const language = this.extensionMap.get(ext);
|
|
983
|
+
if (!language) {
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
return this.parsers.get(language) || null;
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Check if a file is supported
|
|
990
|
+
*/
|
|
991
|
+
isSupported(filePath) {
|
|
992
|
+
return this.getParserForFile(filePath) !== null;
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Get all registered languages
|
|
996
|
+
*/
|
|
997
|
+
getSupportedLanguages() {
|
|
998
|
+
return Array.from(this.parsers.keys());
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Get all supported file extensions
|
|
1002
|
+
*/
|
|
1003
|
+
getSupportedExtensions() {
|
|
1004
|
+
return Array.from(this.extensionMap.keys());
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Get language for a file
|
|
1008
|
+
*/
|
|
1009
|
+
getLanguageForFile(filePath) {
|
|
1010
|
+
const ext = this.getFileExtension(filePath);
|
|
1011
|
+
return this.extensionMap.get(ext) || null;
|
|
1012
|
+
}
|
|
1013
|
+
/**
|
|
1014
|
+
* Extract file extension (with dot)
|
|
1015
|
+
*/
|
|
1016
|
+
getFileExtension(filePath) {
|
|
1017
|
+
const match = filePath.match(/\.[^.]+$/);
|
|
1018
|
+
return match ? match[0].toLowerCase() : "";
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Reset factory (useful for testing)
|
|
1022
|
+
*/
|
|
1023
|
+
static reset() {
|
|
1024
|
+
_ParserFactory.instance = new _ParserFactory();
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
function getParser(filePath) {
|
|
1028
|
+
return ParserFactory.getInstance().getParserForFile(filePath);
|
|
1029
|
+
}
|
|
1030
|
+
function isFileSupported(filePath) {
|
|
1031
|
+
return ParserFactory.getInstance().isSupported(filePath);
|
|
1032
|
+
}
|
|
1033
|
+
function getSupportedLanguages() {
|
|
1034
|
+
return ParserFactory.getInstance().getSupportedLanguages();
|
|
1035
|
+
}
|
|
525
1036
|
export {
|
|
526
1037
|
DEFAULT_EXCLUDE,
|
|
527
1038
|
DEFAULT_TOOL_WEIGHTS,
|
|
1039
|
+
LANGUAGE_EXTENSIONS,
|
|
1040
|
+
Language,
|
|
1041
|
+
ParseError,
|
|
1042
|
+
ParserFactory,
|
|
1043
|
+
PythonParser,
|
|
528
1044
|
TOOL_NAME_MAP,
|
|
1045
|
+
TypeScriptParser,
|
|
529
1046
|
calculateImportSimilarity,
|
|
530
1047
|
calculateOverallScore,
|
|
531
1048
|
estimateTokens,
|
|
@@ -535,11 +1052,14 @@ export {
|
|
|
535
1052
|
formatToolScore,
|
|
536
1053
|
getElapsedTime,
|
|
537
1054
|
getFileExtension,
|
|
1055
|
+
getParser,
|
|
538
1056
|
getRating,
|
|
539
1057
|
getRatingDisplay,
|
|
1058
|
+
getSupportedLanguages,
|
|
540
1059
|
getToolWeight,
|
|
541
1060
|
handleCLIError,
|
|
542
1061
|
handleJSONOutput,
|
|
1062
|
+
isFileSupported,
|
|
543
1063
|
isSourceFile,
|
|
544
1064
|
loadConfig,
|
|
545
1065
|
loadMergedConfig,
|