@nahisaho/musubix-pattern-mcp 1.0.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/compression/index.d.ts +7 -0
- package/dist/compression/index.d.ts.map +1 -0
- package/dist/compression/index.js +7 -0
- package/dist/compression/index.js.map +1 -0
- package/dist/compression/pattern-compressor.d.ts +111 -0
- package/dist/compression/pattern-compressor.d.ts.map +1 -0
- package/dist/compression/pattern-compressor.js +307 -0
- package/dist/compression/pattern-compressor.js.map +1 -0
- package/dist/compression/quality-evaluator.d.ts +97 -0
- package/dist/compression/quality-evaluator.d.ts.map +1 -0
- package/dist/compression/quality-evaluator.js +210 -0
- package/dist/compression/quality-evaluator.js.map +1 -0
- package/dist/extractor/anti-unifier.d.ts +63 -0
- package/dist/extractor/anti-unifier.d.ts.map +1 -0
- package/dist/extractor/anti-unifier.js +167 -0
- package/dist/extractor/anti-unifier.js.map +1 -0
- package/dist/extractor/index.d.ts +9 -0
- package/dist/extractor/index.d.ts.map +1 -0
- package/dist/extractor/index.js +9 -0
- package/dist/extractor/index.js.map +1 -0
- package/dist/extractor/pattern-extractor.d.ts +58 -0
- package/dist/extractor/pattern-extractor.d.ts.map +1 -0
- package/dist/extractor/pattern-extractor.js +201 -0
- package/dist/extractor/pattern-extractor.js.map +1 -0
- package/dist/extractor/subtree-finder.d.ts +81 -0
- package/dist/extractor/subtree-finder.d.ts.map +1 -0
- package/dist/extractor/subtree-finder.js +155 -0
- package/dist/extractor/subtree-finder.js.map +1 -0
- package/dist/extractor/typescript-parser.d.ts +91 -0
- package/dist/extractor/typescript-parser.d.ts.map +1 -0
- package/dist/extractor/typescript-parser.js +219 -0
- package/dist/extractor/typescript-parser.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/learning/index.d.ts +6 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +6 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/wake-sleep.d.ts +144 -0
- package/dist/learning/wake-sleep.d.ts.map +1 -0
- package/dist/learning/wake-sleep.js +312 -0
- package/dist/learning/wake-sleep.js.map +1 -0
- package/dist/library/index.d.ts +6 -0
- package/dist/library/index.d.ts.map +1 -0
- package/dist/library/index.js +6 -0
- package/dist/library/index.js.map +1 -0
- package/dist/library/pattern-library.d.ts +59 -0
- package/dist/library/pattern-library.d.ts.map +1 -0
- package/dist/library/pattern-library.js +139 -0
- package/dist/library/pattern-library.js.map +1 -0
- package/dist/privacy/index.d.ts +6 -0
- package/dist/privacy/index.d.ts.map +1 -0
- package/dist/privacy/index.js +6 -0
- package/dist/privacy/index.js.map +1 -0
- package/dist/privacy/privacy-filter.d.ts +46 -0
- package/dist/privacy/privacy-filter.d.ts.map +1 -0
- package/dist/privacy/privacy-filter.js +105 -0
- package/dist/privacy/privacy-filter.js.map +1 -0
- package/dist/types.d.ts +89 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview AST-based pattern extraction
|
|
3
|
+
* @traceability TSK-PATTERN-001, REQ-PATTERN-001-F001
|
|
4
|
+
*/
|
|
5
|
+
import { TypeScriptParser } from './typescript-parser.js';
|
|
6
|
+
import { SubtreeFinder } from './subtree-finder.js';
|
|
7
|
+
import { AntiUnifier } from './anti-unifier.js';
|
|
8
|
+
/**
|
|
9
|
+
* Pattern extractor using AST analysis
|
|
10
|
+
*
|
|
11
|
+
* @description
|
|
12
|
+
* Extracts recurring patterns from source code by:
|
|
13
|
+
* 1. Parsing code into AST using TypeScript Compiler API
|
|
14
|
+
* 2. Detecting repeated subtrees via structural hashing
|
|
15
|
+
* 3. Abstracting common structures via anti-unification
|
|
16
|
+
*/
|
|
17
|
+
export class PatternExtractor {
|
|
18
|
+
options;
|
|
19
|
+
parser;
|
|
20
|
+
finder;
|
|
21
|
+
antiUnifier;
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.options = {
|
|
24
|
+
language: options.language ?? 'typescript',
|
|
25
|
+
minFrequency: options.minFrequency ?? 2,
|
|
26
|
+
maxDepth: options.maxDepth ?? 10,
|
|
27
|
+
};
|
|
28
|
+
this.parser = new TypeScriptParser({ maxDepth: this.options.maxDepth });
|
|
29
|
+
this.finder = new SubtreeFinder({
|
|
30
|
+
minFrequency: this.options.minFrequency,
|
|
31
|
+
maxDepth: this.options.maxDepth,
|
|
32
|
+
});
|
|
33
|
+
this.antiUnifier = new AntiUnifier();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract patterns from source code
|
|
37
|
+
* @param source - Source code string
|
|
38
|
+
* @returns Extracted patterns
|
|
39
|
+
*/
|
|
40
|
+
async extract(source) {
|
|
41
|
+
// Phase 1: Parse to AST
|
|
42
|
+
const ast = this.parser.parse(source);
|
|
43
|
+
// Phase 2: Find repeated subtrees
|
|
44
|
+
const candidates = this.finder.find(ast);
|
|
45
|
+
// Phase 3: Convert to patterns
|
|
46
|
+
const patterns = candidates.map(c => this.createPattern(c));
|
|
47
|
+
return patterns;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Extract patterns from multiple source files
|
|
51
|
+
*/
|
|
52
|
+
async extractFromMultiple(sources) {
|
|
53
|
+
// Parse all sources
|
|
54
|
+
const asts = sources.map(s => this.parser.parse(s));
|
|
55
|
+
// Find patterns in combined AST space
|
|
56
|
+
const allPatterns = [];
|
|
57
|
+
const patternMap = new Map();
|
|
58
|
+
for (const ast of asts) {
|
|
59
|
+
const candidates = this.finder.find(ast);
|
|
60
|
+
for (const candidate of candidates) {
|
|
61
|
+
const existing = patternMap.get(candidate.hash);
|
|
62
|
+
if (existing) {
|
|
63
|
+
existing.frequency += candidate.frequency;
|
|
64
|
+
existing.locations.push(...candidate.locations);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
patternMap.set(candidate.hash, { ...candidate });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Filter by global frequency
|
|
72
|
+
const filtered = Array.from(patternMap.values())
|
|
73
|
+
.filter(c => c.frequency >= this.options.minFrequency);
|
|
74
|
+
// Abstract similar patterns
|
|
75
|
+
const abstractedPatterns = this.abstractSimilarPatterns(filtered);
|
|
76
|
+
for (const candidate of abstractedPatterns) {
|
|
77
|
+
allPatterns.push(this.createPattern(candidate));
|
|
78
|
+
}
|
|
79
|
+
return allPatterns;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Abstract similar patterns using anti-unification
|
|
83
|
+
*/
|
|
84
|
+
abstractSimilarPatterns(candidates) {
|
|
85
|
+
if (candidates.length < 2)
|
|
86
|
+
return candidates;
|
|
87
|
+
// Group by similar structure
|
|
88
|
+
const groups = [];
|
|
89
|
+
const processed = new Set();
|
|
90
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
91
|
+
if (processed.has(i))
|
|
92
|
+
continue;
|
|
93
|
+
const group = [candidates[i]];
|
|
94
|
+
processed.add(i);
|
|
95
|
+
for (let j = i + 1; j < candidates.length; j++) {
|
|
96
|
+
if (processed.has(j))
|
|
97
|
+
continue;
|
|
98
|
+
const similarity = this.antiUnifier.calculateSimilarity(candidates[i].ast, candidates[j].ast);
|
|
99
|
+
if (similarity > 0.7) {
|
|
100
|
+
group.push(candidates[j]);
|
|
101
|
+
processed.add(j);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
groups.push(group);
|
|
105
|
+
}
|
|
106
|
+
// Abstract each group
|
|
107
|
+
const result = [];
|
|
108
|
+
for (const group of groups) {
|
|
109
|
+
if (group.length === 1) {
|
|
110
|
+
result.push(group[0]);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Anti-unify the group
|
|
114
|
+
const asts = group.map(c => c.ast);
|
|
115
|
+
const unified = this.antiUnifier.antiUnifyAll(asts);
|
|
116
|
+
result.push({
|
|
117
|
+
ast: unified.pattern,
|
|
118
|
+
hash: `abstract-${Date.now()}`,
|
|
119
|
+
frequency: group.reduce((sum, c) => sum + c.frequency, 0),
|
|
120
|
+
depth: Math.max(...group.map(c => c.depth)),
|
|
121
|
+
locations: group.flatMap(c => c.locations),
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Create pattern from candidate
|
|
129
|
+
*/
|
|
130
|
+
createPattern(candidate) {
|
|
131
|
+
const id = `PAT-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
132
|
+
const now = new Date().toISOString();
|
|
133
|
+
// Extract holes from AST if it was anti-unified
|
|
134
|
+
const holes = this.extractHoles(candidate.ast);
|
|
135
|
+
return {
|
|
136
|
+
id,
|
|
137
|
+
name: this.generatePatternName(candidate.ast),
|
|
138
|
+
language: this.options.language,
|
|
139
|
+
ast: candidate.ast,
|
|
140
|
+
holes,
|
|
141
|
+
frequency: candidate.frequency,
|
|
142
|
+
createdAt: now,
|
|
143
|
+
updatedAt: now,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Generate a descriptive pattern name
|
|
148
|
+
*/
|
|
149
|
+
generatePatternName(ast) {
|
|
150
|
+
const typeNames = {
|
|
151
|
+
'FunctionDeclaration': 'function_pattern',
|
|
152
|
+
'MethodDeclaration': 'method_pattern',
|
|
153
|
+
'ClassDeclaration': 'class_pattern',
|
|
154
|
+
'IfStatement': 'conditional_pattern',
|
|
155
|
+
'ForStatement': 'loop_pattern',
|
|
156
|
+
'ForOfStatement': 'iteration_pattern',
|
|
157
|
+
'ForInStatement': 'enumeration_pattern',
|
|
158
|
+
'WhileStatement': 'while_loop_pattern',
|
|
159
|
+
'TryStatement': 'error_handling_pattern',
|
|
160
|
+
'SwitchStatement': 'switch_pattern',
|
|
161
|
+
'ArrowFunction': 'lambda_pattern',
|
|
162
|
+
'CallExpression': 'call_pattern',
|
|
163
|
+
'VariableDeclaration': 'variable_pattern',
|
|
164
|
+
'PropertyDeclaration': 'property_pattern',
|
|
165
|
+
};
|
|
166
|
+
const baseName = typeNames[ast.type] ?? `${ast.type.toLowerCase()}_pattern`;
|
|
167
|
+
return `${baseName}_${Math.random().toString(36).slice(2, 6)}`;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Extract holes from anti-unified AST
|
|
171
|
+
*/
|
|
172
|
+
extractHoles(ast) {
|
|
173
|
+
const holes = [];
|
|
174
|
+
const traverse = (node) => {
|
|
175
|
+
if (node.type === 'Hole' && node.value) {
|
|
176
|
+
holes.push({
|
|
177
|
+
id: node.value,
|
|
178
|
+
type: 'any',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
for (const child of node.children) {
|
|
182
|
+
traverse(child);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
traverse(ast);
|
|
186
|
+
return holes;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get parser for direct AST access
|
|
190
|
+
*/
|
|
191
|
+
getParser() {
|
|
192
|
+
return this.parser;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get anti-unifier for direct access
|
|
196
|
+
*/
|
|
197
|
+
getAntiUnifier() {
|
|
198
|
+
return this.antiUnifier;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=pattern-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-extractor.js","sourceRoot":"","sources":["../../src/extractor/pattern-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Repeated subtree detection in AST
|
|
3
|
+
* @traceability TSK-PATTERN-001, REQ-PATTERN-001-F002
|
|
4
|
+
*/
|
|
5
|
+
import type { ASTNode } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Subtree candidate with frequency information
|
|
8
|
+
*/
|
|
9
|
+
export interface SubtreeCandidate {
|
|
10
|
+
ast: ASTNode;
|
|
11
|
+
hash: string;
|
|
12
|
+
frequency: number;
|
|
13
|
+
depth: number;
|
|
14
|
+
locations: SubtreeLocation[];
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Location of a subtree in source
|
|
18
|
+
*/
|
|
19
|
+
export interface SubtreeLocation {
|
|
20
|
+
startRow: number;
|
|
21
|
+
startColumn: number;
|
|
22
|
+
endRow: number;
|
|
23
|
+
endColumn: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Subtree finder options
|
|
27
|
+
*/
|
|
28
|
+
export interface SubtreeFinderOptions {
|
|
29
|
+
/** Minimum frequency to be considered a pattern */
|
|
30
|
+
minFrequency: number;
|
|
31
|
+
/** Minimum subtree depth to consider */
|
|
32
|
+
minDepth: number;
|
|
33
|
+
/** Maximum subtree depth to consider */
|
|
34
|
+
maxDepth: number;
|
|
35
|
+
/** Node types to ignore */
|
|
36
|
+
ignoreTypes: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Finds repeated subtrees in an AST
|
|
40
|
+
*
|
|
41
|
+
* @description
|
|
42
|
+
* Uses structural hashing to identify repeated code patterns.
|
|
43
|
+
* Implements anti-unification to find common structures.
|
|
44
|
+
*/
|
|
45
|
+
export declare class SubtreeFinder {
|
|
46
|
+
private options;
|
|
47
|
+
constructor(options?: Partial<SubtreeFinderOptions>);
|
|
48
|
+
/**
|
|
49
|
+
* Find all repeated subtrees in AST
|
|
50
|
+
*/
|
|
51
|
+
find(ast: ASTNode): SubtreeCandidate[];
|
|
52
|
+
/**
|
|
53
|
+
* Traverse AST and collect subtree hashes
|
|
54
|
+
*/
|
|
55
|
+
private traverse;
|
|
56
|
+
/**
|
|
57
|
+
* Hash a leaf node
|
|
58
|
+
*/
|
|
59
|
+
private hashLeaf;
|
|
60
|
+
/**
|
|
61
|
+
* Hash a subtree
|
|
62
|
+
*/
|
|
63
|
+
private hashSubtree;
|
|
64
|
+
/**
|
|
65
|
+
* Remove subsumed patterns (patterns contained in larger patterns)
|
|
66
|
+
*/
|
|
67
|
+
private removeSubsumed;
|
|
68
|
+
/**
|
|
69
|
+
* Check if candidate is subsumed by any existing pattern
|
|
70
|
+
*/
|
|
71
|
+
private isSubsumedByAny;
|
|
72
|
+
/**
|
|
73
|
+
* Check if AST contains a subtree with given hash
|
|
74
|
+
*/
|
|
75
|
+
private containsHash;
|
|
76
|
+
/**
|
|
77
|
+
* Compute hash for AST node (for containment check)
|
|
78
|
+
*/
|
|
79
|
+
private computeHash;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=subtree-finder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subtree-finder.d.ts","sourceRoot":"","sources":["../../src/extractor/subtree-finder.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAuB;gBAE1B,OAAO,GAAE,OAAO,CAAC,oBAAoB,CAAM;IAgBvD;;OAEG;IACH,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,EAAE;IAgBtC;;OAEG;IACH,OAAO,CAAC,QAAQ;IAsDhB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAKhB;;OAEG;IACH,OAAO,CAAC,WAAW;IAKnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,WAAW;CAIpB"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Repeated subtree detection in AST
|
|
3
|
+
* @traceability TSK-PATTERN-001, REQ-PATTERN-001-F002
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Finds repeated subtrees in an AST
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* Uses structural hashing to identify repeated code patterns.
|
|
10
|
+
* Implements anti-unification to find common structures.
|
|
11
|
+
*/
|
|
12
|
+
export class SubtreeFinder {
|
|
13
|
+
options;
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = {
|
|
16
|
+
minFrequency: options.minFrequency ?? 2,
|
|
17
|
+
minDepth: options.minDepth ?? 2,
|
|
18
|
+
maxDepth: options.maxDepth ?? 10,
|
|
19
|
+
ignoreTypes: options.ignoreTypes ?? [
|
|
20
|
+
'EndOfFileToken',
|
|
21
|
+
'SemicolonToken',
|
|
22
|
+
'OpenBraceToken',
|
|
23
|
+
'CloseBraceToken',
|
|
24
|
+
'OpenParenToken',
|
|
25
|
+
'CloseParenToken',
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Find all repeated subtrees in AST
|
|
31
|
+
*/
|
|
32
|
+
find(ast) {
|
|
33
|
+
const subtreeMap = new Map();
|
|
34
|
+
this.traverse(ast, subtreeMap, 0);
|
|
35
|
+
// Filter by minimum frequency and depth
|
|
36
|
+
const candidates = Array.from(subtreeMap.values())
|
|
37
|
+
.filter(c => c.frequency >= this.options.minFrequency &&
|
|
38
|
+
c.depth >= this.options.minDepth);
|
|
39
|
+
// Remove subsumed patterns (smaller patterns contained in larger ones)
|
|
40
|
+
return this.removeSubsumed(candidates);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Traverse AST and collect subtree hashes
|
|
44
|
+
*/
|
|
45
|
+
traverse(node, subtreeMap, depth) {
|
|
46
|
+
// Skip ignored node types
|
|
47
|
+
if (this.options.ignoreTypes.includes(node.type)) {
|
|
48
|
+
return { hash: '', depth: 0 };
|
|
49
|
+
}
|
|
50
|
+
// Skip if max depth exceeded
|
|
51
|
+
if (depth > this.options.maxDepth) {
|
|
52
|
+
return { hash: this.hashLeaf(node), depth: 1 };
|
|
53
|
+
}
|
|
54
|
+
// Calculate children hashes
|
|
55
|
+
const childResults = node.children.map(child => this.traverse(child, subtreeMap, depth + 1));
|
|
56
|
+
// Build hash for this subtree
|
|
57
|
+
const hash = this.hashSubtree(node, childResults.map(r => r.hash));
|
|
58
|
+
const subtreeDepth = 1 + Math.max(0, ...childResults.map(r => r.depth));
|
|
59
|
+
// Skip trivial subtrees
|
|
60
|
+
if (subtreeDepth < this.options.minDepth) {
|
|
61
|
+
return { hash, depth: subtreeDepth };
|
|
62
|
+
}
|
|
63
|
+
// Register or update in map
|
|
64
|
+
const location = {
|
|
65
|
+
startRow: node.startPosition.row,
|
|
66
|
+
startColumn: node.startPosition.column,
|
|
67
|
+
endRow: node.endPosition.row,
|
|
68
|
+
endColumn: node.endPosition.column,
|
|
69
|
+
};
|
|
70
|
+
const existing = subtreeMap.get(hash);
|
|
71
|
+
if (existing) {
|
|
72
|
+
existing.frequency++;
|
|
73
|
+
existing.locations.push(location);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
subtreeMap.set(hash, {
|
|
77
|
+
ast: node,
|
|
78
|
+
hash,
|
|
79
|
+
frequency: 1,
|
|
80
|
+
depth: subtreeDepth,
|
|
81
|
+
locations: [location],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return { hash, depth: subtreeDepth };
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Hash a leaf node
|
|
88
|
+
*/
|
|
89
|
+
hashLeaf(node) {
|
|
90
|
+
// Include type and optionally value for identifiers
|
|
91
|
+
return `L:${node.type}`;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Hash a subtree
|
|
95
|
+
*/
|
|
96
|
+
hashSubtree(node, childHashes) {
|
|
97
|
+
const childPart = childHashes.filter(h => h).join(',');
|
|
98
|
+
return `N:${node.type}[${childPart}]`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Remove subsumed patterns (patterns contained in larger patterns)
|
|
102
|
+
*/
|
|
103
|
+
removeSubsumed(candidates) {
|
|
104
|
+
// Sort by depth (largest first)
|
|
105
|
+
const sorted = [...candidates].sort((a, b) => b.depth - a.depth);
|
|
106
|
+
const result = [];
|
|
107
|
+
const seenHashes = new Set();
|
|
108
|
+
for (const candidate of sorted) {
|
|
109
|
+
// Check if this subtree's locations are all covered by a larger pattern
|
|
110
|
+
const isSubsumed = this.isSubsumedByAny(candidate, result);
|
|
111
|
+
if (!isSubsumed && !seenHashes.has(candidate.hash)) {
|
|
112
|
+
result.push(candidate);
|
|
113
|
+
seenHashes.add(candidate.hash);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check if candidate is subsumed by any existing pattern
|
|
120
|
+
*/
|
|
121
|
+
isSubsumedByAny(candidate, existing) {
|
|
122
|
+
for (const pattern of existing) {
|
|
123
|
+
// Skip if same or smaller depth
|
|
124
|
+
if (pattern.depth <= candidate.depth)
|
|
125
|
+
continue;
|
|
126
|
+
// Check if candidate's hash appears in pattern's AST
|
|
127
|
+
if (this.containsHash(pattern.ast, candidate.hash)) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Check if AST contains a subtree with given hash
|
|
135
|
+
*/
|
|
136
|
+
containsHash(ast, targetHash) {
|
|
137
|
+
const currentHash = this.computeHash(ast);
|
|
138
|
+
if (currentHash === targetHash)
|
|
139
|
+
return true;
|
|
140
|
+
for (const child of ast.children) {
|
|
141
|
+
if (this.containsHash(child, targetHash)) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Compute hash for AST node (for containment check)
|
|
149
|
+
*/
|
|
150
|
+
computeHash(node) {
|
|
151
|
+
const childHashes = node.children.map(c => this.computeHash(c));
|
|
152
|
+
return this.hashSubtree(node, childHashes);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=subtree-finder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subtree-finder.js","sourceRoot":"","sources":["../../src/extractor/subtree-finder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TypeScript AST parser using TypeScript Compiler API
|
|
3
|
+
* @traceability TSK-PATTERN-001, REQ-PATTERN-001-F001
|
|
4
|
+
*/
|
|
5
|
+
import type { ASTNode } from '../types.js';
|
|
6
|
+
/**
|
|
7
|
+
* TypeScript parser options
|
|
8
|
+
*/
|
|
9
|
+
export interface TypeScriptParserOptions {
|
|
10
|
+
/** Include position information */
|
|
11
|
+
includePositions: boolean;
|
|
12
|
+
/** Include node values (identifiers, literals) */
|
|
13
|
+
includeValues: boolean;
|
|
14
|
+
/** Maximum depth to parse */
|
|
15
|
+
maxDepth: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* TypeScript AST parser
|
|
19
|
+
*
|
|
20
|
+
* @description
|
|
21
|
+
* Parses TypeScript/JavaScript source code into a normalized AST
|
|
22
|
+
* using the TypeScript Compiler API.
|
|
23
|
+
*/
|
|
24
|
+
export declare class TypeScriptParser {
|
|
25
|
+
private options;
|
|
26
|
+
constructor(options?: Partial<TypeScriptParserOptions>);
|
|
27
|
+
/**
|
|
28
|
+
* Parse TypeScript/JavaScript source code to AST
|
|
29
|
+
*/
|
|
30
|
+
parse(source: string, fileName?: string): ASTNode;
|
|
31
|
+
/**
|
|
32
|
+
* Convert TypeScript AST node to normalized ASTNode
|
|
33
|
+
*/
|
|
34
|
+
private convertNode;
|
|
35
|
+
/**
|
|
36
|
+
* Get human-readable node type name
|
|
37
|
+
*/
|
|
38
|
+
private getNodeTypeName;
|
|
39
|
+
/**
|
|
40
|
+
* Extract value from node (for identifiers, literals)
|
|
41
|
+
*/
|
|
42
|
+
private extractValue;
|
|
43
|
+
/**
|
|
44
|
+
* Convert position offset to row/column
|
|
45
|
+
*/
|
|
46
|
+
private getPosition;
|
|
47
|
+
/**
|
|
48
|
+
* Get all function declarations in source
|
|
49
|
+
*/
|
|
50
|
+
getFunctions(source: string): FunctionInfo[];
|
|
51
|
+
/**
|
|
52
|
+
* Get all class declarations in source
|
|
53
|
+
*/
|
|
54
|
+
getClasses(source: string): ClassInfo[];
|
|
55
|
+
/**
|
|
56
|
+
* Get imports from source
|
|
57
|
+
*/
|
|
58
|
+
getImports(source: string): ImportInfo[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Function information extracted from AST
|
|
62
|
+
*/
|
|
63
|
+
export interface FunctionInfo {
|
|
64
|
+
name: string;
|
|
65
|
+
parameters: {
|
|
66
|
+
name: string;
|
|
67
|
+
type: string;
|
|
68
|
+
}[];
|
|
69
|
+
returnType: string;
|
|
70
|
+
startLine: number;
|
|
71
|
+
endLine: number;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Class information extracted from AST
|
|
75
|
+
*/
|
|
76
|
+
export interface ClassInfo {
|
|
77
|
+
name: string;
|
|
78
|
+
methods: string[];
|
|
79
|
+
properties: string[];
|
|
80
|
+
startLine: number;
|
|
81
|
+
endLine: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Import information extracted from AST
|
|
85
|
+
*/
|
|
86
|
+
export interface ImportInfo {
|
|
87
|
+
module: string;
|
|
88
|
+
namedImports: string[];
|
|
89
|
+
defaultImport?: string;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=typescript-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typescript-parser.d.ts","sourceRoot":"","sources":["../../src/extractor/typescript-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAY,MAAM,aAAa,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,mCAAmC;IACnC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kDAAkD;IAClD,aAAa,EAAE,OAAO,CAAC;IACvB,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,OAAO,CAA0B;gBAE7B,OAAO,GAAE,OAAO,CAAC,uBAAuB,CAAM;IAQ1D;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,OAAO;IAYtD;;OAEG;IACH,OAAO,CAAC,WAAW;IA2BnB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;IACH,OAAO,CAAC,WAAW;IAkBnB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE;IA+D5C;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE;IAyCvC;;OAEG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE;CA6CzC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
|