vue-hook-optimizer 0.0.83 → 0.0.85
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.cjs +409 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -4
- package/dist/index.d.ts +19 -4
- package/dist/index.js +409 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -20,6 +20,19 @@ declare enum NodeType {
|
|
|
20
20
|
}
|
|
21
21
|
type RelationType = 'get' | 'set' | 'call';
|
|
22
22
|
//#endregion
|
|
23
|
+
//#region src/analyze/hook.d.ts
|
|
24
|
+
declare function analyzeHook(content: string, lineOffset?: number, framework?: 'vue' | 'react'): {
|
|
25
|
+
graph: {
|
|
26
|
+
nodes: Set<TypedNode>;
|
|
27
|
+
edges: Map<TypedNode, Set<{
|
|
28
|
+
node: TypedNode;
|
|
29
|
+
type: RelationType;
|
|
30
|
+
}>>;
|
|
31
|
+
};
|
|
32
|
+
nodesUsedInReturn: Set<string>;
|
|
33
|
+
hookName: string;
|
|
34
|
+
}[];
|
|
35
|
+
//#endregion
|
|
23
36
|
//#region src/analyze/options.d.ts
|
|
24
37
|
declare function analyze(content: string, lineOffset?: number, jsx?: boolean): {
|
|
25
38
|
graph: {
|
|
@@ -120,8 +133,10 @@ interface DetectCommunitiesOptions {
|
|
|
120
133
|
*/
|
|
121
134
|
semanticWeight?: number;
|
|
122
135
|
/**
|
|
123
|
-
* Minimum semantic similarity threshold
|
|
124
|
-
* Only node pairs with similarity above this threshold
|
|
136
|
+
* Minimum semantic similarity threshold for enhancing existing edges (0-1).
|
|
137
|
+
* Only structurally connected node pairs with similarity above this threshold
|
|
138
|
+
* will have their edge weight enhanced by semantic similarity.
|
|
139
|
+
* Note: Semantic similarity alone does not create new edges.
|
|
125
140
|
* Default: 0.3
|
|
126
141
|
*/
|
|
127
142
|
similarityThreshold?: number;
|
|
@@ -170,10 +185,10 @@ declare function getVisData(graph: {
|
|
|
170
185
|
node: TypedNode;
|
|
171
186
|
type: RelationType;
|
|
172
187
|
}>>;
|
|
173
|
-
}, nodesUsedInTemplate: Set<string>, nodesUsedInStyle?: Set<string
|
|
188
|
+
}, nodesUsedInTemplate: Set<string>, nodesUsedInStyle?: Set<string>, usedLabel?: string): {
|
|
174
189
|
nodes: CustomNode[];
|
|
175
190
|
edges: Edge[];
|
|
176
191
|
};
|
|
177
192
|
//#endregion
|
|
178
|
-
export { type Community, type CommunityResult, type NodeType, type RelationType, Suggestion, SuggestionType, type TypedNode, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
193
|
+
export { type Community, type CommunityResult, type NodeType, type RelationType, Suggestion, SuggestionType, type TypedNode, analyzeHook, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
179
194
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,19 @@ declare enum NodeType {
|
|
|
20
20
|
}
|
|
21
21
|
type RelationType = 'get' | 'set' | 'call';
|
|
22
22
|
//#endregion
|
|
23
|
+
//#region src/analyze/hook.d.ts
|
|
24
|
+
declare function analyzeHook(content: string, lineOffset?: number, framework?: 'vue' | 'react'): {
|
|
25
|
+
graph: {
|
|
26
|
+
nodes: Set<TypedNode>;
|
|
27
|
+
edges: Map<TypedNode, Set<{
|
|
28
|
+
node: TypedNode;
|
|
29
|
+
type: RelationType;
|
|
30
|
+
}>>;
|
|
31
|
+
};
|
|
32
|
+
nodesUsedInReturn: Set<string>;
|
|
33
|
+
hookName: string;
|
|
34
|
+
}[];
|
|
35
|
+
//#endregion
|
|
23
36
|
//#region src/analyze/options.d.ts
|
|
24
37
|
declare function analyze(content: string, lineOffset?: number, jsx?: boolean): {
|
|
25
38
|
graph: {
|
|
@@ -120,8 +133,10 @@ interface DetectCommunitiesOptions {
|
|
|
120
133
|
*/
|
|
121
134
|
semanticWeight?: number;
|
|
122
135
|
/**
|
|
123
|
-
* Minimum semantic similarity threshold
|
|
124
|
-
* Only node pairs with similarity above this threshold
|
|
136
|
+
* Minimum semantic similarity threshold for enhancing existing edges (0-1).
|
|
137
|
+
* Only structurally connected node pairs with similarity above this threshold
|
|
138
|
+
* will have their edge weight enhanced by semantic similarity.
|
|
139
|
+
* Note: Semantic similarity alone does not create new edges.
|
|
125
140
|
* Default: 0.3
|
|
126
141
|
*/
|
|
127
142
|
similarityThreshold?: number;
|
|
@@ -170,10 +185,10 @@ declare function getVisData(graph: {
|
|
|
170
185
|
node: TypedNode;
|
|
171
186
|
type: RelationType;
|
|
172
187
|
}>>;
|
|
173
|
-
}, nodesUsedInTemplate: Set<string>, nodesUsedInStyle?: Set<string
|
|
188
|
+
}, nodesUsedInTemplate: Set<string>, nodesUsedInStyle?: Set<string>, usedLabel?: string): {
|
|
174
189
|
nodes: CustomNode[];
|
|
175
190
|
edges: Edge[];
|
|
176
191
|
};
|
|
177
192
|
//#endregion
|
|
178
|
-
export { type Community, type CommunityResult, type NodeType, type RelationType, Suggestion, SuggestionType, type TypedNode, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
193
|
+
export { type Community, type CommunityResult, type NodeType, type RelationType, Suggestion, SuggestionType, type TypedNode, analyzeHook, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
179
194
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -119,6 +119,408 @@ function getRelationType(path) {
|
|
|
119
119
|
return "get";
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/analyze/hook.ts
|
|
124
|
+
const traverse$4 = _traverse.default?.default || _traverse.default || _traverse;
|
|
125
|
+
const watchHooks$1 = [
|
|
126
|
+
"watch",
|
|
127
|
+
"watchArray",
|
|
128
|
+
"watchAtMost",
|
|
129
|
+
"watchDebounced",
|
|
130
|
+
"watchDeep",
|
|
131
|
+
"watchIgnorable",
|
|
132
|
+
"watchImmediate",
|
|
133
|
+
"watchOnce",
|
|
134
|
+
"watchPausable",
|
|
135
|
+
"watchThrottled",
|
|
136
|
+
"watchTriggerable",
|
|
137
|
+
"watchWithFilter"
|
|
138
|
+
];
|
|
139
|
+
const reactEffects = [
|
|
140
|
+
"useEffect",
|
|
141
|
+
"useLayoutEffect",
|
|
142
|
+
"useInsertionEffect",
|
|
143
|
+
"useMemo",
|
|
144
|
+
"useCallback"
|
|
145
|
+
];
|
|
146
|
+
const allEffectHooks = [
|
|
147
|
+
...watchHooks$1,
|
|
148
|
+
"watchEffect",
|
|
149
|
+
...reactEffects
|
|
150
|
+
];
|
|
151
|
+
function processHookFunction(functionPath, lineOffset = 0, externalHookName = "", framework = "vue") {
|
|
152
|
+
const nodeCollection = new NodeCollection(lineOffset);
|
|
153
|
+
const nodesUsedInReturn = /* @__PURE__ */ new Set();
|
|
154
|
+
const graph = {
|
|
155
|
+
nodes: /* @__PURE__ */ new Set(),
|
|
156
|
+
edges: /* @__PURE__ */ new Map()
|
|
157
|
+
};
|
|
158
|
+
const functionNode = functionPath.node;
|
|
159
|
+
const hookName = externalHookName || (functionNode.type === "FunctionDeclaration" && functionNode.id ? functionNode.id.name : "");
|
|
160
|
+
const bodyNode = functionNode.body;
|
|
161
|
+
if (bodyNode.type !== "BlockStatement") return {
|
|
162
|
+
graph,
|
|
163
|
+
nodeCollection,
|
|
164
|
+
nodesUsedInReturn,
|
|
165
|
+
hookName
|
|
166
|
+
};
|
|
167
|
+
const functionScope = functionPath.scope;
|
|
168
|
+
if (functionNode.params) functionNode.params.forEach((param) => {
|
|
169
|
+
if (param.type === "Identifier") {
|
|
170
|
+
graph.nodes.add(param.name);
|
|
171
|
+
nodeCollection.addNode(param.name, param, { comment: "" });
|
|
172
|
+
if (!graph.edges.get(param.name)) graph.edges.set(param.name, /* @__PURE__ */ new Set());
|
|
173
|
+
} else if (param.type === "AssignmentPattern" && param.left.type === "Identifier") {
|
|
174
|
+
graph.nodes.add(param.left.name);
|
|
175
|
+
nodeCollection.addNode(param.left.name, param.left, { comment: "" });
|
|
176
|
+
if (!graph.edges.get(param.left.name)) graph.edges.set(param.left.name, /* @__PURE__ */ new Set());
|
|
177
|
+
} else if (param.type === "ObjectPattern") param.properties.forEach((prop) => {
|
|
178
|
+
if (prop.type === "ObjectProperty" && prop.value.type === "Identifier") {
|
|
179
|
+
graph.nodes.add(prop.value.name);
|
|
180
|
+
nodeCollection.addNode(prop.value.name, prop.value, { comment: "" });
|
|
181
|
+
if (!graph.edges.get(prop.value.name)) graph.edges.set(prop.value.name, /* @__PURE__ */ new Set());
|
|
182
|
+
} else if (prop.type === "RestElement" && prop.argument.type === "Identifier") {
|
|
183
|
+
graph.nodes.add(prop.argument.name);
|
|
184
|
+
nodeCollection.addNode(prop.argument.name, prop.argument, { comment: "" });
|
|
185
|
+
if (!graph.edges.get(prop.argument.name)) graph.edges.set(prop.argument.name, /* @__PURE__ */ new Set());
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
else if (param.type === "ArrayPattern") param.elements.forEach((element) => {
|
|
189
|
+
if (element?.type === "Identifier") {
|
|
190
|
+
graph.nodes.add(element.name);
|
|
191
|
+
nodeCollection.addNode(element.name, element, { comment: "" });
|
|
192
|
+
if (!graph.edges.get(element.name)) graph.edges.set(element.name, /* @__PURE__ */ new Set());
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
traverse$4(bodyNode, {
|
|
197
|
+
VariableDeclaration(path) {
|
|
198
|
+
path.node.declarations.forEach((declaration) => {
|
|
199
|
+
if (declaration.id.type === "Identifier") {
|
|
200
|
+
const name = declaration.id.name;
|
|
201
|
+
const binding = path.scope.getBinding(name);
|
|
202
|
+
if (binding && binding.scope === functionScope) {
|
|
203
|
+
graph.nodes.add(name);
|
|
204
|
+
nodeCollection.addNode(name, declaration, { comment: getComment(path.node) });
|
|
205
|
+
if (!graph.edges.get(name)) graph.edges.set(name, /* @__PURE__ */ new Set());
|
|
206
|
+
}
|
|
207
|
+
} else if (declaration.id.type === "ObjectPattern") declaration.id.properties.forEach((property) => {
|
|
208
|
+
if (property.type === "ObjectProperty" && property.value.type === "Identifier") {
|
|
209
|
+
const name = property.value.name;
|
|
210
|
+
const binding = path.scope.getBinding(name);
|
|
211
|
+
if (binding && binding.scope === functionScope) {
|
|
212
|
+
graph.nodes.add(name);
|
|
213
|
+
nodeCollection.addNode(name, property.value, { comment: getComment(property) });
|
|
214
|
+
if (!graph.edges.get(name)) graph.edges.set(name, /* @__PURE__ */ new Set());
|
|
215
|
+
}
|
|
216
|
+
} else if (property.type === "RestElement" && property.argument.type === "Identifier") {
|
|
217
|
+
const name = property.argument.name;
|
|
218
|
+
const binding = path.scope.getBinding(name);
|
|
219
|
+
if (binding && binding.scope === functionScope) {
|
|
220
|
+
graph.nodes.add(name);
|
|
221
|
+
nodeCollection.addNode(name, property.argument, { comment: getComment(property) });
|
|
222
|
+
if (!graph.edges.get(name)) graph.edges.set(name, /* @__PURE__ */ new Set());
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
else if (declaration.id.type === "ArrayPattern") declaration.id.elements.forEach((element) => {
|
|
227
|
+
if (element?.type === "Identifier") {
|
|
228
|
+
const name = element.name;
|
|
229
|
+
const binding = path.scope.getBinding(name);
|
|
230
|
+
if (binding && binding.scope === functionScope) {
|
|
231
|
+
graph.nodes.add(name);
|
|
232
|
+
nodeCollection.addNode(name, element, { comment: getComment(path.node) });
|
|
233
|
+
if (!graph.edges.get(name)) graph.edges.set(name, /* @__PURE__ */ new Set());
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
},
|
|
239
|
+
FunctionDeclaration(path) {
|
|
240
|
+
const name = path.node.id?.name;
|
|
241
|
+
if (name) {
|
|
242
|
+
const binding = path.scope.getBinding(name);
|
|
243
|
+
if (binding && binding.scope === functionScope) {
|
|
244
|
+
graph.nodes.add(name);
|
|
245
|
+
nodeCollection.addNode(name, path.node.id, {
|
|
246
|
+
isMethod: true,
|
|
247
|
+
comment: getComment(path.node)
|
|
248
|
+
});
|
|
249
|
+
if (!graph.edges.get(name)) graph.edges.set(name, /* @__PURE__ */ new Set());
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}, functionScope, functionPath);
|
|
254
|
+
function traverseHooks(node, parentScope) {
|
|
255
|
+
if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.type === "Identifier" || node.type === "CallExpression" && node.callee.type === "Identifier") {
|
|
256
|
+
const hookName$1 = (() => {
|
|
257
|
+
if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.type === "Identifier") return node.expression.callee.name;
|
|
258
|
+
if (node.type === "CallExpression" && node.callee.type === "Identifier") return node.callee.name;
|
|
259
|
+
})() || "";
|
|
260
|
+
if (!hookName$1) return;
|
|
261
|
+
const hookBinding = parentScope.getBinding(hookName$1);
|
|
262
|
+
if (!(hookBinding === void 0 || hookBinding?.scope === functionScope)) return;
|
|
263
|
+
const expression = node.type === "ExpressionStatement" ? node.expression : node;
|
|
264
|
+
const watchArgs = /* @__PURE__ */ new Set();
|
|
265
|
+
if (watchHooks$1.includes(hookName$1)) {
|
|
266
|
+
if (expression.arguments[0]?.type === "Identifier") {
|
|
267
|
+
const binding = parentScope.getBinding(expression.arguments[0].name);
|
|
268
|
+
if (binding && graph.nodes.has(expression.arguments[0].name) && binding.scope === functionScope) watchArgs.add(expression.arguments[0]);
|
|
269
|
+
} else if (expression.arguments[0]) traverse$4(expression.arguments[0], { Identifier(path1) {
|
|
270
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
271
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) watchArgs.add(path1.node);
|
|
272
|
+
} }, parentScope, node);
|
|
273
|
+
}
|
|
274
|
+
expression.arguments.forEach((argNode, index) => {
|
|
275
|
+
if (watchHooks$1.includes(hookName$1) && index === 0 && argNode.type === "Identifier") {
|
|
276
|
+
const _node = nodeCollection.getNode(argNode.name);
|
|
277
|
+
if (_node?.info?.used) _node?.info?.used?.add(hookName$1);
|
|
278
|
+
else if (_node) _node.info = {
|
|
279
|
+
..._node?.info,
|
|
280
|
+
used: new Set([hookName$1])
|
|
281
|
+
};
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (argNode.type === "Identifier") {
|
|
285
|
+
const binding = parentScope.getBinding(argNode.name);
|
|
286
|
+
if (binding && graph.nodes.has(argNode.name) && binding.scope === functionScope) {
|
|
287
|
+
const _node = nodeCollection.getNode(argNode.name);
|
|
288
|
+
if (_node?.info?.used) _node?.info?.used?.add(hookName$1);
|
|
289
|
+
else if (_node) _node.info = {
|
|
290
|
+
..._node?.info,
|
|
291
|
+
used: new Set([hookName$1])
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
} else traverse$4(argNode, { Identifier(path1) {
|
|
295
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
296
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) {
|
|
297
|
+
if ([...watchHooks$1].includes(hookName$1) && watchArgs.size > 0) {
|
|
298
|
+
const watchArgsNames = Array.from(watchArgs).map((arg) => arg.name);
|
|
299
|
+
watchArgs.forEach((watchArg) => {
|
|
300
|
+
if (!watchArgsNames.includes(path1.node.name)) graph.edges.get(watchArg.name)?.add({
|
|
301
|
+
label: path1.node.name,
|
|
302
|
+
type: getRelationType(path1)
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
const _node = nodeCollection.getNode(path1.node.name);
|
|
307
|
+
if (_node?.info?.used) _node?.info?.used?.add(hookName$1);
|
|
308
|
+
else if (_node) _node.info = {
|
|
309
|
+
..._node?.info,
|
|
310
|
+
used: new Set([hookName$1])
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
} }, parentScope, node);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
traverse$4(bodyNode, {
|
|
318
|
+
FunctionDeclaration(path) {
|
|
319
|
+
const name = path.node.id?.name;
|
|
320
|
+
if (name && graph.nodes.has(name) && path.scope.getBinding(name)?.scope === functionScope) traverse$4(path.node.body, { Identifier(path1) {
|
|
321
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
322
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
323
|
+
label: path1.node.name,
|
|
324
|
+
type: getRelationType(path1)
|
|
325
|
+
});
|
|
326
|
+
} }, path.scope, path);
|
|
327
|
+
},
|
|
328
|
+
VariableDeclarator(path) {
|
|
329
|
+
if (path.node.init) {
|
|
330
|
+
if (path.node.id.type === "Identifier") {
|
|
331
|
+
const name = path.node.id.name;
|
|
332
|
+
if (name && graph.nodes.has(name) && path.scope.getBinding(name)?.scope === functionScope) {
|
|
333
|
+
if (path.node.init.type === "CallExpression" && path.node.init.callee.type === "Identifier" && allEffectHooks.includes(path.node.init.callee.name)) traverseHooks(path.node.init, path.scope);
|
|
334
|
+
traverse$4(path.node.init, { Identifier(path1) {
|
|
335
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
336
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
337
|
+
label: path1.node.name,
|
|
338
|
+
type: getRelationType(path1)
|
|
339
|
+
});
|
|
340
|
+
} }, path.scope, path);
|
|
341
|
+
}
|
|
342
|
+
} else if (path.node.id.type === "ObjectPattern") path.node.id.properties.forEach((property) => {
|
|
343
|
+
if (property.type === "ObjectProperty" && property.value.type === "Identifier") {
|
|
344
|
+
const name = property.value.name;
|
|
345
|
+
const isValidNode = name && graph.nodes.has(name) && path.node.init && path.scope.getBinding(name)?.scope === functionScope;
|
|
346
|
+
if (isValidNode) traverse$4(path.node.init, { Identifier(path1) {
|
|
347
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
348
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
349
|
+
label: path1.node.name,
|
|
350
|
+
type: getRelationType(path1)
|
|
351
|
+
});
|
|
352
|
+
} }, path.scope, path);
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
else if (path.node.id.type === "ArrayPattern") path.node.id.elements.forEach((element) => {
|
|
356
|
+
if (element?.type === "Identifier") {
|
|
357
|
+
const name = element.name;
|
|
358
|
+
const isValidNode = name && graph.nodes.has(name) && path.node.init && path.scope.getBinding(name)?.scope === functionScope;
|
|
359
|
+
if (isValidNode) traverse$4(path.node.init, { Identifier(path1) {
|
|
360
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
361
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
362
|
+
label: path1.node.name,
|
|
363
|
+
type: getRelationType(path1)
|
|
364
|
+
});
|
|
365
|
+
} }, path.scope, path);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
ObjectMethod(path) {
|
|
371
|
+
if (path.node.key.type === "Identifier" && graph.nodes.has(path.node.key.name)) {
|
|
372
|
+
const name = path.node.key.name;
|
|
373
|
+
traverse$4(path.node.body, { Identifier(path1) {
|
|
374
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
375
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
376
|
+
label: path1.node.name,
|
|
377
|
+
type: getRelationType(path1)
|
|
378
|
+
});
|
|
379
|
+
} }, path.scope, path);
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
ObjectProperty(path) {
|
|
383
|
+
if (path.node.key.type === "Identifier" && graph.nodes.has(path.node.key.name)) {
|
|
384
|
+
const name = path.node.key.name;
|
|
385
|
+
traverse$4(path.node.value, { Identifier(path1) {
|
|
386
|
+
if (path1.node.name === name) return;
|
|
387
|
+
const binding = path1.scope.getBinding(path1.node.name);
|
|
388
|
+
if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && binding?.scope === functionScope) graph.edges.get(name)?.add({
|
|
389
|
+
label: path1.node.name,
|
|
390
|
+
type: getRelationType(path1)
|
|
391
|
+
});
|
|
392
|
+
} }, path.scope, path);
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
ExpressionStatement(path) {
|
|
396
|
+
if (path.node.expression.type === "CallExpression" && path.node.expression.callee.type === "Identifier") {
|
|
397
|
+
const name = path.node.expression.callee.name;
|
|
398
|
+
if (graph.nodes.has(name) && path.scope.getBinding(name)?.scope === functionScope) {
|
|
399
|
+
const _node = nodeCollection.getNode(name);
|
|
400
|
+
if (_node?.info?.used) _node?.info?.used?.add("Call Expression");
|
|
401
|
+
else if (_node) _node.info = {
|
|
402
|
+
..._node?.info,
|
|
403
|
+
used: new Set(["Call Expression"])
|
|
404
|
+
};
|
|
405
|
+
} else traverseHooks(path.node.expression, path.scope);
|
|
406
|
+
}
|
|
407
|
+
if (path.node.expression.type === "AssignmentExpression" && path.node.expression.right.type === "CallExpression" && path.node.expression.right.callee.type === "Identifier") traverseHooks(path.node.expression.right, path.scope);
|
|
408
|
+
}
|
|
409
|
+
}, functionScope, functionPath);
|
|
410
|
+
traverse$4(bodyNode, { ReturnStatement(path) {
|
|
411
|
+
const fnParent = path.findParent((p) => p.isFunction());
|
|
412
|
+
if (fnParent && fnParent.node !== functionNode) return;
|
|
413
|
+
if (path.node.argument?.type === "ObjectExpression") {
|
|
414
|
+
const returnNode = path.node.argument;
|
|
415
|
+
traverse$4(returnNode, {
|
|
416
|
+
ObjectProperty(path3) {
|
|
417
|
+
if (path3.parent === returnNode) {
|
|
418
|
+
if (path3.node.key.type === "Identifier" && path3.node.value.type === "Identifier") nodesUsedInReturn.add(path3.node.value.name);
|
|
419
|
+
}
|
|
420
|
+
},
|
|
421
|
+
SpreadElement(path3) {
|
|
422
|
+
if (path3.node.argument.type === "Identifier") nodesUsedInReturn.add(path3.node.argument.name);
|
|
423
|
+
}
|
|
424
|
+
}, path.scope, path);
|
|
425
|
+
} else if (path.node.argument?.type === "ArrayExpression") path.node.argument.elements.forEach((element) => {
|
|
426
|
+
if (element?.type === "Identifier") nodesUsedInReturn.add(element.name);
|
|
427
|
+
});
|
|
428
|
+
else if (path.node.argument?.type === "Identifier") nodesUsedInReturn.add(path.node.argument.name);
|
|
429
|
+
} }, functionScope, functionPath);
|
|
430
|
+
return {
|
|
431
|
+
graph,
|
|
432
|
+
nodeCollection,
|
|
433
|
+
nodesUsedInReturn,
|
|
434
|
+
hookName
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
function analyzeHook(content, lineOffset = 0, framework = "vue") {
|
|
438
|
+
const ast = babelParse(content, {
|
|
439
|
+
sourceType: "module",
|
|
440
|
+
plugins: ["typescript", "jsx"]
|
|
441
|
+
});
|
|
442
|
+
const results = [];
|
|
443
|
+
function walkCallExpressionChain(node, path, pathSegments) {
|
|
444
|
+
if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") try {
|
|
445
|
+
return path.get(pathSegments.join("."));
|
|
446
|
+
} catch {
|
|
447
|
+
return void 0;
|
|
448
|
+
}
|
|
449
|
+
if (node.type === "CallExpression") for (let i = 0; i < node.arguments.length; i++) {
|
|
450
|
+
const arg = node.arguments[i];
|
|
451
|
+
if (arg.type === "ArrowFunctionExpression" || arg.type === "FunctionExpression") try {
|
|
452
|
+
return path.get([
|
|
453
|
+
...pathSegments,
|
|
454
|
+
"arguments",
|
|
455
|
+
i
|
|
456
|
+
].join("."));
|
|
457
|
+
} catch {}
|
|
458
|
+
else if (arg.type === "CallExpression") {
|
|
459
|
+
const result = walkCallExpressionChain(arg, path, [
|
|
460
|
+
...pathSegments,
|
|
461
|
+
"arguments",
|
|
462
|
+
i
|
|
463
|
+
]);
|
|
464
|
+
if (result) return result;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return void 0;
|
|
468
|
+
}
|
|
469
|
+
function extractHookFromDeclarator(decl, varPath) {
|
|
470
|
+
const init = decl.init;
|
|
471
|
+
const hookName = decl.id.type === "Identifier" ? decl.id.name : "";
|
|
472
|
+
if (!init) return;
|
|
473
|
+
const funcPath = walkCallExpressionChain(init, varPath, ["init"]);
|
|
474
|
+
if (funcPath) results.push(processHookFunction(funcPath, lineOffset, hookName, framework));
|
|
475
|
+
}
|
|
476
|
+
traverse$4(ast, {
|
|
477
|
+
ExportDefaultDeclaration(path) {
|
|
478
|
+
const declaration = path.node.declaration;
|
|
479
|
+
if (declaration.type === "FunctionDeclaration" && declaration.id?.name.startsWith("use")) {
|
|
480
|
+
const funcPath = path.get("declaration");
|
|
481
|
+
results.push(processHookFunction(funcPath, lineOffset, "", framework));
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
ExportNamedDeclaration(path) {
|
|
485
|
+
const declaration = path.node.declaration;
|
|
486
|
+
if (declaration?.type === "FunctionDeclaration" && declaration.id?.name.startsWith("use")) {
|
|
487
|
+
const funcPath = path.get("declaration");
|
|
488
|
+
results.push(processHookFunction(funcPath, lineOffset, "", framework));
|
|
489
|
+
} else if (declaration?.type === "VariableDeclaration") declaration.declarations.forEach((decl) => {
|
|
490
|
+
if (decl.id.type === "Identifier" && decl.id.name.startsWith("use")) {
|
|
491
|
+
const varPath = path.get("declaration.declarations").find((p) => {
|
|
492
|
+
const node = p.node;
|
|
493
|
+
const nodeId = node.id;
|
|
494
|
+
return nodeId.type === "Identifier" && nodeId.name === decl.id.name;
|
|
495
|
+
});
|
|
496
|
+
if (varPath) extractHookFromDeclarator(decl, varPath);
|
|
497
|
+
}
|
|
498
|
+
});
|
|
499
|
+
},
|
|
500
|
+
FunctionDeclaration(path) {
|
|
501
|
+
if (path.node.id?.name.startsWith("use") && path.parent.type === "Program") results.push(processHookFunction(path, lineOffset, "", framework));
|
|
502
|
+
},
|
|
503
|
+
VariableDeclaration(path) {
|
|
504
|
+
if (path.parent.type === "Program") path.node.declarations.forEach((decl) => {
|
|
505
|
+
if (decl.id.type === "Identifier" && decl.id.name.startsWith("use")) {
|
|
506
|
+
const declName = decl.id.name;
|
|
507
|
+
const varPath = path.get("declarations").find((p) => {
|
|
508
|
+
const node = p.node;
|
|
509
|
+
const nodeId = node.id;
|
|
510
|
+
return nodeId.type === "Identifier" && nodeId.name === declName;
|
|
511
|
+
});
|
|
512
|
+
if (varPath) extractHookFromDeclarator(decl, varPath);
|
|
513
|
+
}
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
});
|
|
517
|
+
return results.map((result) => ({
|
|
518
|
+
graph: result.nodeCollection.map(result.graph),
|
|
519
|
+
nodesUsedInReturn: result.nodesUsedInReturn,
|
|
520
|
+
hookName: result.hookName
|
|
521
|
+
}));
|
|
522
|
+
}
|
|
523
|
+
|
|
122
524
|
//#endregion
|
|
123
525
|
//#region src/analyze/setupScript.ts
|
|
124
526
|
const traverse$3 = _traverse.default?.default || _traverse.default || _traverse;
|
|
@@ -1779,7 +2181,6 @@ function buildWeightedGraph(graph, options = {}) {
|
|
|
1779
2181
|
const { semanticWeight = 1, similarityThreshold = .3 } = options;
|
|
1780
2182
|
const weighted = /* @__PURE__ */ new Map();
|
|
1781
2183
|
const allNodes = /* @__PURE__ */ new Set();
|
|
1782
|
-
const connectedPairs = /* @__PURE__ */ new Set();
|
|
1783
2184
|
for (const [node, edges] of graph) {
|
|
1784
2185
|
allNodes.add(node);
|
|
1785
2186
|
for (const edge of edges) allNodes.add(edge.node);
|
|
@@ -1791,8 +2192,6 @@ function buildWeightedGraph(graph, options = {}) {
|
|
|
1791
2192
|
weighted.get(node).set(edge.node, Math.max(currentWeight, structuralWeight));
|
|
1792
2193
|
const reverseWeight = weighted.get(edge.node).get(node) || 0;
|
|
1793
2194
|
weighted.get(edge.node).set(node, Math.max(reverseWeight, structuralWeight));
|
|
1794
|
-
const pairKey = [node.label, edge.node.label].sort().join("|");
|
|
1795
|
-
connectedPairs.add(pairKey);
|
|
1796
2195
|
}
|
|
1797
2196
|
if (semanticWeight > 0) {
|
|
1798
2197
|
const nodeWordsCache = /* @__PURE__ */ new Map();
|
|
@@ -1819,14 +2218,11 @@ function buildWeightedGraph(graph, options = {}) {
|
|
|
1819
2218
|
const wordsB = nodeWordsCache.get(nodeB);
|
|
1820
2219
|
const similarity = calculateSemanticSimilarityCached(nodeA.label, nodeB.label, wordsA, wordsB);
|
|
1821
2220
|
if (similarity > similarityThreshold) {
|
|
1822
|
-
const isConnected = connectedPairs.has(comparedKey);
|
|
1823
2221
|
const semanticEdgeWeight = similarity * semanticWeight;
|
|
1824
|
-
const currentAB = weighted.get(nodeA).get(nodeB)
|
|
1825
|
-
|
|
1826
|
-
weighted.get(
|
|
1827
|
-
|
|
1828
|
-
const newWeightBA = isConnected ? Math.max(currentBA, semanticEdgeWeight) : currentBA + semanticEdgeWeight;
|
|
1829
|
-
weighted.get(nodeB).set(nodeA, Math.min(newWeightBA, 2));
|
|
2222
|
+
const currentAB = weighted.get(nodeA).get(nodeB);
|
|
2223
|
+
if (typeof currentAB === "number") weighted.get(nodeA).set(nodeB, Math.min(Math.max(currentAB, semanticEdgeWeight), 2));
|
|
2224
|
+
const currentBA = weighted.get(nodeB).get(nodeA);
|
|
2225
|
+
if (typeof currentBA === "number") weighted.get(nodeB).set(nodeA, Math.min(Math.max(currentBA, semanticEdgeWeight), 2));
|
|
1830
2226
|
}
|
|
1831
2227
|
}
|
|
1832
2228
|
}
|
|
@@ -2310,7 +2706,7 @@ function filterNodeUserd(used) {
|
|
|
2310
2706
|
const usedArray = Array.from(used || []);
|
|
2311
2707
|
return new Set(usedArray.filter((u) => !["Assignment Expression", "Call Expression"].includes(u)));
|
|
2312
2708
|
}
|
|
2313
|
-
function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__ */ new Set()) {
|
|
2709
|
+
function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__ */ new Set(), usedLabel) {
|
|
2314
2710
|
const usedNodes = new Set([...nodesUsedInTemplate, ...nodesUsedInStyle]);
|
|
2315
2711
|
const nodes = [];
|
|
2316
2712
|
const edges = [];
|
|
@@ -2333,7 +2729,7 @@ function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__
|
|
|
2333
2729
|
shape: node.type === "var" ? "dot" : "diamond",
|
|
2334
2730
|
group: usedNodes.has(node.label) || node.info?.used?.size ? "used" : "normal",
|
|
2335
2731
|
size: 20 + 1.6 ** (inDegree * .75 + outDegree * .25),
|
|
2336
|
-
title: `${filterNodeUserd(node.info?.used).size ? `used by ${Array.from(filterNodeUserd(node.info?.used))?.map((i) => `\`${i}\``).join(",")}\n\n` : ""}${usedNodes.has(node.label) ? `used in ${[nodesUsedInStyle.has(node.label) ? "style" : "", nodesUsedInTemplate.has(node.label) ? "template" : ""].filter(Boolean).join(" and ")}\n\n` : ""}${node.info?.comment || ""}`.trim() || void 0,
|
|
2732
|
+
title: `${filterNodeUserd(node.info?.used).size ? `used by ${Array.from(filterNodeUserd(node.info?.used))?.map((i) => `\`${i}\``).join(",")}\n\n` : ""}${usedNodes.has(node.label) ? `used in ${[nodesUsedInStyle.has(node.label) ? "style" : "", nodesUsedInTemplate.has(node.label) ? usedLabel || "template" : ""].filter(Boolean).join(" and ")}\n\n` : ""}${node.info?.comment || ""}`.trim() || void 0,
|
|
2337
2733
|
info: node.info
|
|
2338
2734
|
});
|
|
2339
2735
|
});
|
|
@@ -2357,5 +2753,5 @@ function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__
|
|
|
2357
2753
|
}
|
|
2358
2754
|
|
|
2359
2755
|
//#endregion
|
|
2360
|
-
export { SuggestionType, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
2756
|
+
export { SuggestionType, analyzeHook, analyze as analyzeOptions, analyze$1 as analyzeSetupScript, analyze$2 as analyzeStyle, analyze$3 as analyzeTemplate, analyze$4 as analyzeTsx, detectCommunities, gen, generateCommunityColors, generateCommunityColorsRGBA, getMermaidText, getVisData, parse };
|
|
2361
2757
|
//# sourceMappingURL=index.js.map
|