linguclaw 0.4.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/LICENSE +21 -0
- package/README.md +161 -0
- package/dist/agent-system.d.ts +196 -0
- package/dist/agent-system.d.ts.map +1 -0
- package/dist/agent-system.js +738 -0
- package/dist/agent-system.js.map +1 -0
- package/dist/alphabeta.d.ts +54 -0
- package/dist/alphabeta.d.ts.map +1 -0
- package/dist/alphabeta.js +193 -0
- package/dist/alphabeta.js.map +1 -0
- package/dist/browser.d.ts +62 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +224 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +565 -0
- package/dist/cli.js.map +1 -0
- package/dist/code-parser.d.ts +39 -0
- package/dist/code-parser.d.ts.map +1 -0
- package/dist/code-parser.js +385 -0
- package/dist/code-parser.js.map +1 -0
- package/dist/config.d.ts +66 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +232 -0
- package/dist/config.js.map +1 -0
- package/dist/core/engine.d.ts +359 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +127 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/daemon.d.ts +29 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +212 -0
- package/dist/daemon.js.map +1 -0
- package/dist/email-receiver.d.ts +63 -0
- package/dist/email-receiver.d.ts.map +1 -0
- package/dist/email-receiver.js +553 -0
- package/dist/email-receiver.js.map +1 -0
- package/dist/git-integration.d.ts +180 -0
- package/dist/git-integration.d.ts.map +1 -0
- package/dist/git-integration.js +850 -0
- package/dist/git-integration.js.map +1 -0
- package/dist/inbox.d.ts +84 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +198 -0
- package/dist/inbox.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/languages/cpp.d.ts +51 -0
- package/dist/languages/cpp.d.ts.map +1 -0
- package/dist/languages/cpp.js +930 -0
- package/dist/languages/cpp.js.map +1 -0
- package/dist/languages/csharp.d.ts +79 -0
- package/dist/languages/csharp.d.ts.map +1 -0
- package/dist/languages/csharp.js +1776 -0
- package/dist/languages/csharp.js.map +1 -0
- package/dist/languages/go.d.ts +50 -0
- package/dist/languages/go.d.ts.map +1 -0
- package/dist/languages/go.js +882 -0
- package/dist/languages/go.js.map +1 -0
- package/dist/languages/java.d.ts +47 -0
- package/dist/languages/java.d.ts.map +1 -0
- package/dist/languages/java.js +649 -0
- package/dist/languages/java.js.map +1 -0
- package/dist/languages/python.d.ts +47 -0
- package/dist/languages/python.d.ts.map +1 -0
- package/dist/languages/python.js +655 -0
- package/dist/languages/python.js.map +1 -0
- package/dist/languages/rust.d.ts +61 -0
- package/dist/languages/rust.d.ts.map +1 -0
- package/dist/languages/rust.js +1064 -0
- package/dist/languages/rust.js.map +1 -0
- package/dist/logger.d.ts +20 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +133 -0
- package/dist/logger.js.map +1 -0
- package/dist/longterm-memory.d.ts +47 -0
- package/dist/longterm-memory.d.ts.map +1 -0
- package/dist/longterm-memory.js +300 -0
- package/dist/longterm-memory.js.map +1 -0
- package/dist/memory.d.ts +42 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +274 -0
- package/dist/memory.js.map +1 -0
- package/dist/messaging.d.ts +103 -0
- package/dist/messaging.d.ts.map +1 -0
- package/dist/messaging.js +645 -0
- package/dist/messaging.js.map +1 -0
- package/dist/multi-provider.d.ts +69 -0
- package/dist/multi-provider.d.ts.map +1 -0
- package/dist/multi-provider.js +484 -0
- package/dist/multi-provider.js.map +1 -0
- package/dist/orchestrator.d.ts +65 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +441 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/plugins.d.ts +52 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +215 -0
- package/dist/plugins.js.map +1 -0
- package/dist/prism-orchestrator.d.ts +26 -0
- package/dist/prism-orchestrator.d.ts.map +1 -0
- package/dist/prism-orchestrator.js +191 -0
- package/dist/prism-orchestrator.js.map +1 -0
- package/dist/prism.d.ts +46 -0
- package/dist/prism.d.ts.map +1 -0
- package/dist/prism.js +188 -0
- package/dist/prism.js.map +1 -0
- package/dist/privacy.d.ts +23 -0
- package/dist/privacy.d.ts.map +1 -0
- package/dist/privacy.js +220 -0
- package/dist/privacy.js.map +1 -0
- package/dist/proactive.d.ts +30 -0
- package/dist/proactive.d.ts.map +1 -0
- package/dist/proactive.js +260 -0
- package/dist/proactive.js.map +1 -0
- package/dist/refactoring-engine.d.ts +100 -0
- package/dist/refactoring-engine.d.ts.map +1 -0
- package/dist/refactoring-engine.js +717 -0
- package/dist/refactoring-engine.js.map +1 -0
- package/dist/resilience.d.ts +43 -0
- package/dist/resilience.d.ts.map +1 -0
- package/dist/resilience.js +200 -0
- package/dist/resilience.js.map +1 -0
- package/dist/safety.d.ts +40 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +133 -0
- package/dist/safety.js.map +1 -0
- package/dist/sandbox.d.ts +33 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +173 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/scheduler.d.ts +72 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +374 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/semantic-memory.d.ts +70 -0
- package/dist/semantic-memory.d.ts.map +1 -0
- package/dist/semantic-memory.js +430 -0
- package/dist/semantic-memory.js.map +1 -0
- package/dist/skills.d.ts +97 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +575 -0
- package/dist/skills.js.map +1 -0
- package/dist/static/dashboard.html +853 -0
- package/dist/static/hub.html +772 -0
- package/dist/static/index.html +818 -0
- package/dist/static/logo.svg +24 -0
- package/dist/static/workflow-editor.html +913 -0
- package/dist/tools.d.ts +67 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +303 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +295 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +90 -0
- package/dist/types.js.map +1 -0
- package/dist/web.d.ts +76 -0
- package/dist/web.d.ts.map +1 -0
- package/dist/web.js +2139 -0
- package/dist/web.js.map +1 -0
- package/dist/workflow-engine.d.ts +114 -0
- package/dist/workflow-engine.d.ts.map +1 -0
- package/dist/workflow-engine.js +855 -0
- package/dist/workflow-engine.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,717 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Code Refactoring Engine for LinguClaw
|
|
4
|
+
* Automated code transformations and improvements
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.RefactoringEngine = void 0;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const logger_1 = require("./logger");
|
|
43
|
+
const logger = (0, logger_1.getLogger)();
|
|
44
|
+
// ============================================
|
|
45
|
+
// REFACTORING ENGINE
|
|
46
|
+
// ============================================
|
|
47
|
+
class RefactoringEngine {
|
|
48
|
+
operations = new Map();
|
|
49
|
+
appliedRefactorings = [];
|
|
50
|
+
constructor() {
|
|
51
|
+
this.registerDefaultOperations();
|
|
52
|
+
}
|
|
53
|
+
registerDefaultOperations() {
|
|
54
|
+
// Simplification refactorings
|
|
55
|
+
this.register({
|
|
56
|
+
id: 'remove-unused-imports',
|
|
57
|
+
name: 'Remove Unused Imports',
|
|
58
|
+
description: 'Removes import statements that are not used in the code',
|
|
59
|
+
category: 'simplification',
|
|
60
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'go', 'rust', 'csharp'],
|
|
61
|
+
canApply: (node) => this.hasUnusedImports(node),
|
|
62
|
+
apply: (node, source) => this.removeUnusedImports(node, source),
|
|
63
|
+
safety: 'safe',
|
|
64
|
+
breaking: false,
|
|
65
|
+
});
|
|
66
|
+
this.register({
|
|
67
|
+
id: 'simplify-boolean-expressions',
|
|
68
|
+
name: 'Simplify Boolean Expressions',
|
|
69
|
+
description: 'Simplifies redundant boolean expressions like `x == true` to `x`',
|
|
70
|
+
category: 'simplification',
|
|
71
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'csharp'],
|
|
72
|
+
canApply: (node) => this.hasRedundantBooleanExpressions(node),
|
|
73
|
+
apply: (node, source) => this.simplifyBooleanExpressions(node, source),
|
|
74
|
+
safety: 'safe',
|
|
75
|
+
breaking: false,
|
|
76
|
+
});
|
|
77
|
+
this.register({
|
|
78
|
+
id: 'remove-dead-code',
|
|
79
|
+
name: 'Remove Dead Code',
|
|
80
|
+
description: 'Removes unreachable code and unused variables',
|
|
81
|
+
category: 'simplification',
|
|
82
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'go', 'rust', 'csharp'],
|
|
83
|
+
canApply: (node) => this.hasDeadCode(node),
|
|
84
|
+
apply: (node, source) => this.removeDeadCode(node, source),
|
|
85
|
+
safety: 'requires-review',
|
|
86
|
+
breaking: false,
|
|
87
|
+
});
|
|
88
|
+
// Extraction refactorings
|
|
89
|
+
this.register({
|
|
90
|
+
id: 'extract-method',
|
|
91
|
+
name: 'Extract Method',
|
|
92
|
+
description: 'Extracts a block of code into a separate method/function',
|
|
93
|
+
category: 'extraction',
|
|
94
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'csharp'],
|
|
95
|
+
canApply: (node) => this.canExtractMethod(node),
|
|
96
|
+
apply: (node, source) => this.extractMethod(node, source),
|
|
97
|
+
safety: 'safe',
|
|
98
|
+
breaking: false,
|
|
99
|
+
});
|
|
100
|
+
this.register({
|
|
101
|
+
id: 'extract-variable',
|
|
102
|
+
name: 'Extract Variable',
|
|
103
|
+
description: 'Extracts a complex expression into a named variable',
|
|
104
|
+
category: 'extraction',
|
|
105
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'go', 'rust', 'csharp'],
|
|
106
|
+
canApply: (node) => this.canExtractVariable(node),
|
|
107
|
+
apply: (node, source) => this.extractVariable(node, source),
|
|
108
|
+
safety: 'safe',
|
|
109
|
+
breaking: false,
|
|
110
|
+
});
|
|
111
|
+
this.register({
|
|
112
|
+
id: 'extract-interface',
|
|
113
|
+
name: 'Extract Interface',
|
|
114
|
+
description: 'Creates an interface from a class public API',
|
|
115
|
+
category: 'extraction',
|
|
116
|
+
appliesTo: ['typescript', 'java', 'csharp'],
|
|
117
|
+
canApply: (node) => this.canExtractInterface(node),
|
|
118
|
+
apply: (node, source) => this.extractInterface(node, source),
|
|
119
|
+
safety: 'safe',
|
|
120
|
+
breaking: false,
|
|
121
|
+
});
|
|
122
|
+
// Modernization refactorings
|
|
123
|
+
this.register({
|
|
124
|
+
id: 'convert-to-arrow-functions',
|
|
125
|
+
name: 'Convert to Arrow Functions',
|
|
126
|
+
description: 'Converts traditional functions to arrow functions where appropriate',
|
|
127
|
+
category: 'modernization',
|
|
128
|
+
appliesTo: ['typescript', 'javascript'],
|
|
129
|
+
canApply: (node) => this.canConvertToArrowFunction(node),
|
|
130
|
+
apply: (node, source) => this.convertToArrowFunction(node, source),
|
|
131
|
+
safety: 'safe',
|
|
132
|
+
breaking: false,
|
|
133
|
+
});
|
|
134
|
+
this.register({
|
|
135
|
+
id: 'convert-to-template-literals',
|
|
136
|
+
name: 'Convert to Template Literals',
|
|
137
|
+
description: 'Converts string concatenation to template literals',
|
|
138
|
+
category: 'modernization',
|
|
139
|
+
appliesTo: ['typescript', 'javascript'],
|
|
140
|
+
canApply: (node) => this.hasStringConcatenation(node),
|
|
141
|
+
apply: (node, source) => this.convertToTemplateLiterals(node, source),
|
|
142
|
+
safety: 'safe',
|
|
143
|
+
breaking: false,
|
|
144
|
+
});
|
|
145
|
+
this.register({
|
|
146
|
+
id: 'convert-to-async-await',
|
|
147
|
+
name: 'Convert to Async/Await',
|
|
148
|
+
description: 'Converts Promise chains to async/await syntax',
|
|
149
|
+
category: 'modernization',
|
|
150
|
+
appliesTo: ['typescript', 'javascript', 'csharp'],
|
|
151
|
+
canApply: (node) => this.hasPromiseChains(node),
|
|
152
|
+
apply: (node, source) => this.convertToAsyncAwait(node, source),
|
|
153
|
+
safety: 'requires-review',
|
|
154
|
+
breaking: false,
|
|
155
|
+
});
|
|
156
|
+
this.register({
|
|
157
|
+
id: 'convert-to-optional-chaining',
|
|
158
|
+
name: 'Convert to Optional Chaining',
|
|
159
|
+
description: 'Converts nested property checks to optional chaining',
|
|
160
|
+
category: 'modernization',
|
|
161
|
+
appliesTo: ['typescript', 'javascript'],
|
|
162
|
+
canApply: (node) => this.hasNestedPropertyChecks(node),
|
|
163
|
+
apply: (node, source) => this.convertToOptionalChaining(node, source),
|
|
164
|
+
safety: 'safe',
|
|
165
|
+
breaking: false,
|
|
166
|
+
});
|
|
167
|
+
// Performance refactorings
|
|
168
|
+
this.register({
|
|
169
|
+
id: 'optimize-string-concatenation',
|
|
170
|
+
name: 'Optimize String Concatenation',
|
|
171
|
+
description: 'Uses StringBuilder/StringBuffer for concatenation in loops',
|
|
172
|
+
category: 'performance',
|
|
173
|
+
appliesTo: ['java', 'csharp', 'typescript', 'javascript'],
|
|
174
|
+
canApply: (node) => this.hasStringConcatInLoop(node),
|
|
175
|
+
apply: (node, source) => this.optimizeStringConcatenation(node, source),
|
|
176
|
+
safety: 'safe',
|
|
177
|
+
breaking: false,
|
|
178
|
+
});
|
|
179
|
+
this.register({
|
|
180
|
+
id: 'convert-to-linq',
|
|
181
|
+
name: 'Convert to LINQ/Stream',
|
|
182
|
+
description: 'Converts imperative loops to LINQ (C#) or Stream (Java)',
|
|
183
|
+
category: 'performance',
|
|
184
|
+
appliesTo: ['csharp', 'java'],
|
|
185
|
+
canApply: (node) => this.canConvertToLinq(node),
|
|
186
|
+
apply: (node, source) => this.convertToLinq(node, source),
|
|
187
|
+
safety: 'requires-review',
|
|
188
|
+
breaking: false,
|
|
189
|
+
});
|
|
190
|
+
// Readability refactorings
|
|
191
|
+
this.register({
|
|
192
|
+
id: 'rename-variable',
|
|
193
|
+
name: 'Rename Variable',
|
|
194
|
+
description: 'Renames variables to be more descriptive',
|
|
195
|
+
category: 'readability',
|
|
196
|
+
appliesTo: ['typescript', 'javascript', 'python', 'java', 'go', 'rust', 'csharp'],
|
|
197
|
+
canApply: (node) => this.hasPoorlyNamedVariables(node),
|
|
198
|
+
apply: (node, source) => this.renameVariables(node, source),
|
|
199
|
+
safety: 'requires-review',
|
|
200
|
+
breaking: false,
|
|
201
|
+
});
|
|
202
|
+
this.register({
|
|
203
|
+
id: 'add-type-annotations',
|
|
204
|
+
name: 'Add Type Annotations',
|
|
205
|
+
description: 'Adds explicit type annotations where they improve readability',
|
|
206
|
+
category: 'readability',
|
|
207
|
+
appliesTo: ['typescript', 'python', 'go', 'rust'],
|
|
208
|
+
canApply: (node) => this.missingTypeAnnotations(node),
|
|
209
|
+
apply: (node, source) => this.addTypeAnnotations(node, source),
|
|
210
|
+
safety: 'safe',
|
|
211
|
+
breaking: false,
|
|
212
|
+
});
|
|
213
|
+
this.register({
|
|
214
|
+
id: 'reorganize-class-members',
|
|
215
|
+
name: 'Reorganize Class Members',
|
|
216
|
+
description: 'Reorders class members by visibility and type',
|
|
217
|
+
category: 'reorganization',
|
|
218
|
+
appliesTo: ['typescript', 'java', 'csharp', 'python'],
|
|
219
|
+
canApply: (node) => this.hasUnorganizedMembers(node),
|
|
220
|
+
apply: (node, source) => this.reorganizeClassMembers(node, source),
|
|
221
|
+
safety: 'safe',
|
|
222
|
+
breaking: false,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
register(operation) {
|
|
226
|
+
this.operations.set(operation.id, operation);
|
|
227
|
+
}
|
|
228
|
+
getAvailableOperations(language) {
|
|
229
|
+
return Array.from(this.operations.values())
|
|
230
|
+
.filter(op => op.appliesTo.includes(language));
|
|
231
|
+
}
|
|
232
|
+
analyzeForRefactoring(ast, language, source) {
|
|
233
|
+
const suggestions = [];
|
|
234
|
+
const operations = this.getAvailableOperations(language);
|
|
235
|
+
for (const op of operations) {
|
|
236
|
+
if (op.canApply(ast)) {
|
|
237
|
+
const result = op.apply(ast, source);
|
|
238
|
+
if (result.success && result.changes.length > 0) {
|
|
239
|
+
suggestions.push({
|
|
240
|
+
operation: op,
|
|
241
|
+
preview: result,
|
|
242
|
+
impact: this.calculateImpact(result),
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return suggestions.sort((a, b) => b.impact - a.impact);
|
|
248
|
+
}
|
|
249
|
+
calculateImpact(result) {
|
|
250
|
+
let impact = 0;
|
|
251
|
+
// More changes = higher impact
|
|
252
|
+
impact += result.changes.length * 5;
|
|
253
|
+
// Fewer warnings = higher confidence
|
|
254
|
+
impact -= result.warnings.length * 2;
|
|
255
|
+
// No errors = good
|
|
256
|
+
if (result.errors.length === 0)
|
|
257
|
+
impact += 10;
|
|
258
|
+
return Math.max(0, impact);
|
|
259
|
+
}
|
|
260
|
+
async applyRefactoring(filePath, operationId, ast, dryRun = false) {
|
|
261
|
+
const operation = this.operations.get(operationId);
|
|
262
|
+
if (!operation) {
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
original: '',
|
|
266
|
+
transformed: '',
|
|
267
|
+
changes: [],
|
|
268
|
+
warnings: [],
|
|
269
|
+
errors: [`Operation ${operationId} not found`],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const source = fs.readFileSync(filePath, 'utf-8');
|
|
273
|
+
if (!operation.canApply(ast)) {
|
|
274
|
+
return {
|
|
275
|
+
success: false,
|
|
276
|
+
original: source,
|
|
277
|
+
transformed: source,
|
|
278
|
+
changes: [],
|
|
279
|
+
warnings: [],
|
|
280
|
+
errors: [`Operation ${operationId} cannot be applied to this code`],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
const result = operation.apply(ast, source);
|
|
284
|
+
if (!dryRun && result.success) {
|
|
285
|
+
fs.writeFileSync(filePath, result.transformed);
|
|
286
|
+
this.appliedRefactorings.push(result);
|
|
287
|
+
logger.info(`Applied refactoring: ${operation.name} to ${filePath}`);
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
// ============================================
|
|
292
|
+
// REFACTORING IMPLEMENTATIONS
|
|
293
|
+
// ============================================
|
|
294
|
+
hasUnusedImports(node) {
|
|
295
|
+
// Simplified check - would need full symbol analysis
|
|
296
|
+
return node.children.some(c => c.type === 'ImportDeclaration');
|
|
297
|
+
}
|
|
298
|
+
removeUnusedImports(node, source) {
|
|
299
|
+
const changes = [];
|
|
300
|
+
const lines = source.split('\n');
|
|
301
|
+
const unusedImports = this.findUnusedImports(node, source);
|
|
302
|
+
for (const imp of unusedImports) {
|
|
303
|
+
const lineIndex = imp.location.startLine - 1;
|
|
304
|
+
changes.push({
|
|
305
|
+
type: 'delete',
|
|
306
|
+
startLine: imp.location.startLine,
|
|
307
|
+
startColumn: 0,
|
|
308
|
+
endLine: imp.location.endLine,
|
|
309
|
+
endColumn: lines[lineIndex]?.length || 0,
|
|
310
|
+
originalText: lines[lineIndex] || '',
|
|
311
|
+
newText: '',
|
|
312
|
+
description: 'Remove unused import',
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
return {
|
|
316
|
+
success: true,
|
|
317
|
+
original: source,
|
|
318
|
+
transformed: this.applyChanges(source, changes),
|
|
319
|
+
changes,
|
|
320
|
+
warnings: [],
|
|
321
|
+
errors: [],
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
findUnusedImports(node, source) {
|
|
325
|
+
const imports = node.children.filter(c => c.type === 'ImportDeclaration');
|
|
326
|
+
return imports.filter(imp => {
|
|
327
|
+
const names = imp.metadata.names || [];
|
|
328
|
+
return names.some((name) => !source.includes(name) || source.indexOf(name) === source.lastIndexOf(name));
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
hasRedundantBooleanExpressions(node) {
|
|
332
|
+
// Check for patterns like `x == true` or `x == false`
|
|
333
|
+
return /==\s*(true|false)|===\s*(true|false)/.test(JSON.stringify(node));
|
|
334
|
+
}
|
|
335
|
+
simplifyBooleanExpressions(node, source) {
|
|
336
|
+
const changes = [];
|
|
337
|
+
// Find all redundant boolean comparisons
|
|
338
|
+
const patterns = [
|
|
339
|
+
{ regex: /([\w.]+)\s*===?\s*true/g, replacement: '$1', desc: 'Simplify `x === true` to `x`' },
|
|
340
|
+
{ regex: /([\w.]+)\s*===?\s*false/g, replacement: '!$1', desc: 'Simplify `x === false` to `!x`' },
|
|
341
|
+
];
|
|
342
|
+
const lines = source.split('\n');
|
|
343
|
+
for (let i = 0; i < lines.length; i++) {
|
|
344
|
+
for (const pattern of patterns) {
|
|
345
|
+
if (pattern.regex.test(lines[i])) {
|
|
346
|
+
const original = lines[i];
|
|
347
|
+
const transformed = lines[i].replace(pattern.regex, pattern.replacement);
|
|
348
|
+
if (original !== transformed) {
|
|
349
|
+
changes.push({
|
|
350
|
+
type: 'replace',
|
|
351
|
+
startLine: i + 1,
|
|
352
|
+
startColumn: 0,
|
|
353
|
+
endLine: i + 1,
|
|
354
|
+
endColumn: original.length,
|
|
355
|
+
originalText: original,
|
|
356
|
+
newText: transformed,
|
|
357
|
+
description: pattern.desc,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
success: true,
|
|
365
|
+
original: source,
|
|
366
|
+
transformed: this.applyChanges(source, changes),
|
|
367
|
+
changes,
|
|
368
|
+
warnings: [],
|
|
369
|
+
errors: [],
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
hasDeadCode(node) {
|
|
373
|
+
// Check for unreachable code or unused variables
|
|
374
|
+
return node.children.some(c => c.type === 'VariableDeclaration' && !c.metadata.isUsed ||
|
|
375
|
+
c.type === 'FunctionDeclaration' && !c.metadata.isCalled);
|
|
376
|
+
}
|
|
377
|
+
removeDeadCode(node, source) {
|
|
378
|
+
// Implementation would require full data flow analysis
|
|
379
|
+
return {
|
|
380
|
+
success: false,
|
|
381
|
+
original: source,
|
|
382
|
+
transformed: source,
|
|
383
|
+
changes: [],
|
|
384
|
+
warnings: ['Dead code removal requires comprehensive analysis'],
|
|
385
|
+
errors: [],
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
canExtractMethod(node) {
|
|
389
|
+
// Check if there's a code block that can be extracted
|
|
390
|
+
return node.children.some(c => c.type === 'BlockStatement' ||
|
|
391
|
+
c.type === 'MethodDeclaration' ||
|
|
392
|
+
c.type === 'FunctionDeclaration');
|
|
393
|
+
}
|
|
394
|
+
extractMethod(node, source) {
|
|
395
|
+
// Complex refactoring - would need full analysis
|
|
396
|
+
return {
|
|
397
|
+
success: false,
|
|
398
|
+
original: source,
|
|
399
|
+
transformed: source,
|
|
400
|
+
changes: [],
|
|
401
|
+
warnings: ['Method extraction requires selection of code block'],
|
|
402
|
+
errors: [],
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
canExtractVariable(node) {
|
|
406
|
+
// Check for complex expressions
|
|
407
|
+
return node.children.some(c => c.type === 'BinaryExpression' ||
|
|
408
|
+
c.type === 'CallExpression' ||
|
|
409
|
+
c.type === 'MemberExpression');
|
|
410
|
+
}
|
|
411
|
+
extractVariable(node, source) {
|
|
412
|
+
// Would need selection of specific expression
|
|
413
|
+
return {
|
|
414
|
+
success: false,
|
|
415
|
+
original: source,
|
|
416
|
+
transformed: source,
|
|
417
|
+
changes: [],
|
|
418
|
+
warnings: ['Variable extraction requires selection of expression'],
|
|
419
|
+
errors: [],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
canExtractInterface(node) {
|
|
423
|
+
return node.type === 'ClassDeclaration' || node.type === 'ClassDefinition';
|
|
424
|
+
}
|
|
425
|
+
extractInterface(node, source) {
|
|
426
|
+
// Generate interface from class public methods
|
|
427
|
+
const className = node.metadata.name || 'Unknown';
|
|
428
|
+
const methods = node.children.filter(c => c.type === 'MethodDeclaration' &&
|
|
429
|
+
(c.metadata.isPublic || !c.metadata.isPrivate));
|
|
430
|
+
let interfaceCode = `interface I${className} {\n`;
|
|
431
|
+
for (const method of methods) {
|
|
432
|
+
const params = (method.metadata.parameters || []).join(', ');
|
|
433
|
+
interfaceCode += ` ${method.metadata.name}(${params}): ${method.metadata.returnType || 'void'};\n`;
|
|
434
|
+
}
|
|
435
|
+
interfaceCode += '}';
|
|
436
|
+
return {
|
|
437
|
+
success: true,
|
|
438
|
+
original: source,
|
|
439
|
+
transformed: source + '\n\n' + interfaceCode,
|
|
440
|
+
changes: [{
|
|
441
|
+
type: 'insert',
|
|
442
|
+
startLine: source.split('\n').length + 1,
|
|
443
|
+
startColumn: 0,
|
|
444
|
+
endLine: source.split('\n').length + 1,
|
|
445
|
+
endColumn: 0,
|
|
446
|
+
originalText: '',
|
|
447
|
+
newText: interfaceCode,
|
|
448
|
+
description: `Extract interface I${className}`,
|
|
449
|
+
}],
|
|
450
|
+
warnings: [],
|
|
451
|
+
errors: [],
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
canConvertToArrowFunction(node) {
|
|
455
|
+
return node.children.some(c => c.type === 'FunctionDeclaration' &&
|
|
456
|
+
!c.metadata.isGenerator &&
|
|
457
|
+
!c.metadata.isConstructor);
|
|
458
|
+
}
|
|
459
|
+
convertToArrowFunction(node, source) {
|
|
460
|
+
const changes = [];
|
|
461
|
+
const lines = source.split('\n');
|
|
462
|
+
for (const child of node.children) {
|
|
463
|
+
if (child.type === 'FunctionDeclaration' && child.metadata.name) {
|
|
464
|
+
const startLine = child.location.startLine - 1;
|
|
465
|
+
const original = lines[startLine];
|
|
466
|
+
// Simple transformation for demo
|
|
467
|
+
const arrowVersion = `const ${child.metadata.name} = ${original.replace('function ', '').replace(child.metadata.name, '')}`;
|
|
468
|
+
changes.push({
|
|
469
|
+
type: 'replace',
|
|
470
|
+
startLine: child.location.startLine,
|
|
471
|
+
startColumn: 0,
|
|
472
|
+
endLine: child.location.startLine,
|
|
473
|
+
endColumn: original.length,
|
|
474
|
+
originalText: original,
|
|
475
|
+
newText: arrowVersion,
|
|
476
|
+
description: 'Convert function to arrow function',
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return {
|
|
481
|
+
success: changes.length > 0,
|
|
482
|
+
original: source,
|
|
483
|
+
transformed: this.applyChanges(source, changes),
|
|
484
|
+
changes,
|
|
485
|
+
warnings: [],
|
|
486
|
+
errors: [],
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
hasStringConcatenation(node) {
|
|
490
|
+
return /\+\s*['"]/.test(JSON.stringify(node)) || /['"]\s*\+/.test(JSON.stringify(node));
|
|
491
|
+
}
|
|
492
|
+
convertToTemplateLiterals(node, source) {
|
|
493
|
+
const changes = [];
|
|
494
|
+
const lines = source.split('\n');
|
|
495
|
+
for (let i = 0; i < lines.length; i++) {
|
|
496
|
+
const line = lines[i];
|
|
497
|
+
// Find string concatenation patterns
|
|
498
|
+
const concatPattern = /['"]([^'"]*)['"]\s*\+\s*(\w+)\s*\+\s*['"]([^'"]*)['"]/g;
|
|
499
|
+
if (concatPattern.test(line)) {
|
|
500
|
+
const transformed = line.replace(/['"]([^'"]*)['"]\s*\+\s*(\w+)\s*\+\s*['"]([^'"]*)['"]/g, '`$1${$2}$3`');
|
|
501
|
+
if (line !== transformed) {
|
|
502
|
+
changes.push({
|
|
503
|
+
type: 'replace',
|
|
504
|
+
startLine: i + 1,
|
|
505
|
+
startColumn: 0,
|
|
506
|
+
endLine: i + 1,
|
|
507
|
+
endColumn: line.length,
|
|
508
|
+
originalText: line,
|
|
509
|
+
newText: transformed,
|
|
510
|
+
description: 'Convert string concatenation to template literal',
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return {
|
|
516
|
+
success: changes.length > 0,
|
|
517
|
+
original: source,
|
|
518
|
+
transformed: this.applyChanges(source, changes),
|
|
519
|
+
changes,
|
|
520
|
+
warnings: [],
|
|
521
|
+
errors: [],
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
hasPromiseChains(node) {
|
|
525
|
+
const str = JSON.stringify(node);
|
|
526
|
+
return new RegExp('\\.then\\s*\\(').test(str) || new RegExp('\\.catch\\s*\\(').test(str);
|
|
527
|
+
}
|
|
528
|
+
convertToAsyncAwait(node, source) {
|
|
529
|
+
// Complex transformation requiring full AST manipulation
|
|
530
|
+
return {
|
|
531
|
+
success: false,
|
|
532
|
+
original: source,
|
|
533
|
+
transformed: source,
|
|
534
|
+
changes: [],
|
|
535
|
+
warnings: ['Promise to async/await conversion requires full AST transformation'],
|
|
536
|
+
errors: [],
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
hasNestedPropertyChecks(node) {
|
|
540
|
+
return /&&\s*[\w.]+\s*!==\s*null/.test(JSON.stringify(node)) ||
|
|
541
|
+
/&&\s*[\w.]+\s*!==\s*undefined/.test(JSON.stringify(node));
|
|
542
|
+
}
|
|
543
|
+
convertToOptionalChaining(node, source) {
|
|
544
|
+
const changes = [];
|
|
545
|
+
const lines = source.split('\n');
|
|
546
|
+
for (let i = 0; i < lines.length; i++) {
|
|
547
|
+
const line = lines[i];
|
|
548
|
+
// Pattern: obj && obj.prop && obj.prop.nested
|
|
549
|
+
const pattern = /(\w+)\s*&&\s*\1\.(\w+)/g;
|
|
550
|
+
if (pattern.test(line)) {
|
|
551
|
+
const transformed = line.replace(/(\w+)\s*&&\s*\1\.(\w+)/g, '$1?.$2');
|
|
552
|
+
if (line !== transformed) {
|
|
553
|
+
changes.push({
|
|
554
|
+
type: 'replace',
|
|
555
|
+
startLine: i + 1,
|
|
556
|
+
startColumn: 0,
|
|
557
|
+
endLine: i + 1,
|
|
558
|
+
endColumn: line.length,
|
|
559
|
+
originalText: line,
|
|
560
|
+
newText: transformed,
|
|
561
|
+
description: 'Convert to optional chaining',
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
success: changes.length > 0,
|
|
568
|
+
original: source,
|
|
569
|
+
transformed: this.applyChanges(source, changes),
|
|
570
|
+
changes,
|
|
571
|
+
warnings: [],
|
|
572
|
+
errors: [],
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
hasStringConcatInLoop(node) {
|
|
576
|
+
return /for|while/.test(JSON.stringify(node)) && /\+\s*['"]/.test(JSON.stringify(node));
|
|
577
|
+
}
|
|
578
|
+
optimizeStringConcatenation(node, source) {
|
|
579
|
+
return {
|
|
580
|
+
success: false,
|
|
581
|
+
original: source,
|
|
582
|
+
transformed: source,
|
|
583
|
+
changes: [],
|
|
584
|
+
warnings: ['String concatenation optimization requires context analysis'],
|
|
585
|
+
errors: [],
|
|
586
|
+
};
|
|
587
|
+
}
|
|
588
|
+
canConvertToLinq(node) {
|
|
589
|
+
return /for\s*\([^)]+\)\s*\{/.test(JSON.stringify(node)) &&
|
|
590
|
+
/Add|add/.test(JSON.stringify(node));
|
|
591
|
+
}
|
|
592
|
+
convertToLinq(node, source) {
|
|
593
|
+
return {
|
|
594
|
+
success: false,
|
|
595
|
+
original: source,
|
|
596
|
+
transformed: source,
|
|
597
|
+
changes: [],
|
|
598
|
+
warnings: ['LINQ conversion requires pattern matching on specific loop types'],
|
|
599
|
+
errors: [],
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
hasPoorlyNamedVariables(node) {
|
|
603
|
+
const badNames = ['x', 'y', 'z', 'a', 'b', 'c', 'i', 'j', 'k', 'temp', 'tmp', 'val', 'num'];
|
|
604
|
+
return node.children.some(c => badNames.includes(c.metadata.name) ||
|
|
605
|
+
c.metadata.name?.length === 1);
|
|
606
|
+
}
|
|
607
|
+
renameVariables(node, source) {
|
|
608
|
+
return {
|
|
609
|
+
success: false,
|
|
610
|
+
original: source,
|
|
611
|
+
transformed: source,
|
|
612
|
+
changes: [],
|
|
613
|
+
warnings: ['Variable renaming requires semantic analysis to suggest meaningful names'],
|
|
614
|
+
errors: [],
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
missingTypeAnnotations(node) {
|
|
618
|
+
return node.children.some(c => (c.type === 'VariableDeclaration' || c.type === 'FunctionDeclaration') &&
|
|
619
|
+
!c.metadata.type);
|
|
620
|
+
}
|
|
621
|
+
addTypeAnnotations(node, source) {
|
|
622
|
+
return {
|
|
623
|
+
success: false,
|
|
624
|
+
original: source,
|
|
625
|
+
transformed: source,
|
|
626
|
+
changes: [],
|
|
627
|
+
warnings: ['Type annotation addition requires type inference analysis'],
|
|
628
|
+
errors: [],
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
hasUnorganizedMembers(node) {
|
|
632
|
+
return node.type === 'ClassDeclaration' || node.type === 'ClassDefinition';
|
|
633
|
+
}
|
|
634
|
+
reorganizeClassMembers(node, source) {
|
|
635
|
+
return {
|
|
636
|
+
success: false,
|
|
637
|
+
original: source,
|
|
638
|
+
transformed: source,
|
|
639
|
+
changes: [],
|
|
640
|
+
warnings: ['Member reorganization requires full class structure analysis'],
|
|
641
|
+
errors: [],
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
applyChanges(source, changes) {
|
|
645
|
+
const lines = source.split('\n');
|
|
646
|
+
// Sort changes by line number (descending) to avoid index shifting
|
|
647
|
+
changes.sort((a, b) => b.startLine - a.startLine);
|
|
648
|
+
for (const change of changes) {
|
|
649
|
+
const lineIndex = change.startLine - 1;
|
|
650
|
+
if (change.type === 'delete') {
|
|
651
|
+
lines.splice(lineIndex, 1);
|
|
652
|
+
}
|
|
653
|
+
else if (change.type === 'replace') {
|
|
654
|
+
lines[lineIndex] = change.newText;
|
|
655
|
+
}
|
|
656
|
+
else if (change.type === 'insert') {
|
|
657
|
+
lines.splice(lineIndex, 0, change.newText);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return lines.join('\n');
|
|
661
|
+
}
|
|
662
|
+
// ============================================
|
|
663
|
+
// BATCH OPERATIONS
|
|
664
|
+
// ============================================
|
|
665
|
+
async batchRefactor(files, operationIds, dryRun = true) {
|
|
666
|
+
const results = [];
|
|
667
|
+
let totalChanges = 0;
|
|
668
|
+
let successCount = 0;
|
|
669
|
+
for (const file of files) {
|
|
670
|
+
const fileResults = [];
|
|
671
|
+
for (const opId of operationIds) {
|
|
672
|
+
// Parse file (simplified - would need actual parser)
|
|
673
|
+
const source = fs.readFileSync(file, 'utf-8');
|
|
674
|
+
const mockAST = {
|
|
675
|
+
type: 'Program',
|
|
676
|
+
id: file,
|
|
677
|
+
location: { file, startLine: 1, startColumn: 0, endLine: source.split('\n').length, endColumn: 0, byteOffset: 0 },
|
|
678
|
+
children: [],
|
|
679
|
+
metadata: {},
|
|
680
|
+
};
|
|
681
|
+
const result = await this.applyRefactoring(file, opId, mockAST, dryRun);
|
|
682
|
+
fileResults.push(result);
|
|
683
|
+
if (result.success) {
|
|
684
|
+
totalChanges += result.changes.length;
|
|
685
|
+
successCount++;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
results.push({
|
|
689
|
+
file,
|
|
690
|
+
results: fileResults,
|
|
691
|
+
totalChanges: fileResults.reduce((sum, r) => sum + r.changes.length, 0),
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
files: results,
|
|
696
|
+
totalFiles: files.length,
|
|
697
|
+
successfulRefactorings: successCount,
|
|
698
|
+
totalChanges,
|
|
699
|
+
dryRun,
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
getAppliedRefactorings() {
|
|
703
|
+
return this.appliedRefactorings;
|
|
704
|
+
}
|
|
705
|
+
undoLastRefactoring() {
|
|
706
|
+
const last = this.appliedRefactorings.pop();
|
|
707
|
+
if (last) {
|
|
708
|
+
// Would need to track original file states
|
|
709
|
+
logger.info('Undo functionality requires file state tracking');
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
return false;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
exports.RefactoringEngine = RefactoringEngine;
|
|
716
|
+
exports.default = RefactoringEngine;
|
|
717
|
+
//# sourceMappingURL=refactoring-engine.js.map
|