vue-hook-optimizer 0.0.58 → 0.0.60

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.js CHANGED
@@ -358,6 +358,108 @@ function processSetup(ast, parentScope, parentPath, _spread, _lineOffset = 0) {
358
358
  }
359
359
  }
360
360
  }, parentScope, parentPath);
361
+ function traverseHooks(node, patentScope) {
362
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.type === "Identifier" || node.type === "CallExpression" && node.callee.type === "Identifier") {
363
+ const hookName = (() => {
364
+ if (node.type === "ExpressionStatement" && node.expression.type === "CallExpression" && node.expression.callee.type === "Identifier") {
365
+ return node.expression.callee.name;
366
+ }
367
+ if (node.type === "CallExpression" && node.callee.type === "Identifier") {
368
+ return node.callee.name;
369
+ }
370
+ })() || "";
371
+ if (!hookName) {
372
+ return;
373
+ }
374
+ const hookBinding = patentScope.getBinding(hookName);
375
+ if (!(hookBinding === void 0 || hookBinding?.scope.block.type === "Program" || parentScope === hookBinding?.scope)) {
376
+ return;
377
+ }
378
+ const expression = node.type === "ExpressionStatement" ? node.expression : node;
379
+ const watchArgs = /* @__PURE__ */ new Set();
380
+ if (hookName === "provide") {
381
+ traverse2(expression, {
382
+ Identifier(path1) {
383
+ const binding = path1.scope.getBinding(path1.node.name);
384
+ if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
385
+ const _node = nodeCollection.getNode(path1.node.name);
386
+ if (_node?.info?.used) {
387
+ _node?.info?.used?.add(hookName);
388
+ } else if (_node) {
389
+ _node.info = {
390
+ ..._node?.info,
391
+ used: /* @__PURE__ */ new Set([hookName])
392
+ };
393
+ }
394
+ }
395
+ }
396
+ }, patentScope, node);
397
+ } else if (hookName === "watch") {
398
+ if (expression.arguments[0].type === "Identifier") {
399
+ const binding = patentScope.getBinding(expression.arguments[0].name);
400
+ if (graph.nodes.has(expression.arguments[0].name) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
401
+ watchArgs.add(expression.arguments[0]);
402
+ }
403
+ } else {
404
+ traverse2(expression.arguments[0], {
405
+ Identifier(path1) {
406
+ const binding = path1.scope.getBinding(path1.node.name);
407
+ if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
408
+ watchArgs.add(path1.node);
409
+ }
410
+ }
411
+ }, patentScope, node);
412
+ }
413
+ } else if (hookName === "useEffect" && expression.arguments[1].type === "ArrayExpression") {
414
+ traverse2(expression.arguments[1], {
415
+ Identifier(path1) {
416
+ const binding = path1.scope.getBinding(path1.node.name);
417
+ if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
418
+ watchArgs.add(path1.node);
419
+ }
420
+ }
421
+ }, patentScope, node);
422
+ }
423
+ expression.arguments.forEach((argNode, index) => {
424
+ if (hookName === "watch" && index === 0 && argNode.type === "Identifier") {
425
+ const _node = nodeCollection.getNode(argNode.name);
426
+ if (_node?.info?.used) {
427
+ _node?.info?.used?.add(hookName);
428
+ } else if (_node) {
429
+ _node.info = {
430
+ ..._node?.info,
431
+ used: /* @__PURE__ */ new Set([hookName])
432
+ };
433
+ }
434
+ return;
435
+ }
436
+ traverse2(argNode, {
437
+ Identifier(path1) {
438
+ const binding = path1.scope.getBinding(path1.node.name);
439
+ if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
440
+ if (["watch", "useEffect"].includes(hookName) && watchArgs.size > 0) {
441
+ const watchArgsNames = Array.from(watchArgs).map((arg) => arg.name);
442
+ watchArgs.forEach((watchArg) => {
443
+ if (!watchArgsNames.includes(path1.node.name)) {
444
+ graph.edges.get(watchArg.name)?.add(path1.node.name);
445
+ }
446
+ });
447
+ }
448
+ const _node = nodeCollection.getNode(path1.node.name);
449
+ if (_node?.info?.used) {
450
+ _node?.info?.used?.add(hookName);
451
+ } else if (_node) {
452
+ _node.info = {
453
+ ..._node?.info,
454
+ used: /* @__PURE__ */ new Set([hookName])
455
+ };
456
+ }
457
+ }
458
+ }
459
+ }, patentScope, node);
460
+ });
461
+ }
462
+ }
361
463
  traverse2(ast, {
362
464
  FunctionDeclaration(path) {
363
465
  const name = path.node.id?.name;
@@ -435,6 +537,9 @@ function processSetup(ast, parentScope, parentPath, _spread, _lineOffset = 0) {
435
537
  "ArrowFunctionExpression",
436
538
  "FunctionDeclaration"
437
539
  ].includes(path.node.init.type) && path.node.id.type === "Identifier") {
540
+ if (path.node.init.type === "CallExpression" && path.node.init.callee.type === "Identifier" && ["watch", "watchEffect"].includes(path.node.init.callee.name)) {
541
+ traverseHooks(path.node.init, path.scope);
542
+ }
438
543
  const name = path.node.id?.name;
439
544
  if (name && graph.nodes.has(name)) {
440
545
  traverse2(path.node.init, {
@@ -511,94 +616,35 @@ function processSetup(ast, parentScope, parentPath, _spread, _lineOffset = 0) {
511
616
  }
512
617
  },
513
618
  ExpressionStatement(path) {
514
- if (path.node.expression.type === "CallExpression" && path.node.expression.callee.type === "Identifier") {
515
- const hookName = path.node.expression.callee.name;
516
- const hookBinding = path.scope.getBinding(hookName);
517
- if (!(hookBinding === void 0 || hookBinding?.scope.block.type === "Program" || parentScope === hookBinding?.scope)) {
518
- return;
519
- }
520
- const watchArgs = /* @__PURE__ */ new Set();
521
- if (hookName === "provide") {
522
- traverse2(path.node.expression, {
523
- Identifier(path1) {
524
- const binding = path1.scope.getBinding(path1.node.name);
525
- if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
526
- const _node = nodeCollection.getNode(path1.node.name);
527
- if (_node?.info?.used) {
528
- _node?.info?.used?.add(hookName);
529
- } else if (_node) {
530
- _node.info = {
531
- ..._node?.info,
532
- used: /* @__PURE__ */ new Set([hookName])
533
- };
534
- }
535
- }
536
- }
537
- }, path.scope, path);
538
- } else if (hookName === "watch") {
539
- if (path.node.expression.arguments[0].type === "Identifier") {
540
- const binding = path.scope.getBinding(path.node.expression.arguments[0].name);
541
- if (graph.nodes.has(path.node.expression.arguments[0].name) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
542
- watchArgs.add(path.node.expression.arguments[0]);
543
- }
544
- } else {
545
- traverse2(path.node.expression.arguments[0], {
546
- Identifier(path1) {
547
- const binding = path1.scope.getBinding(path1.node.name);
548
- if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
549
- watchArgs.add(path1.node);
550
- }
551
- }
552
- }, path.scope, path);
619
+ if (path.type === "ExpressionStatement" && path.node.expression.type === "CallExpression" && path.node.expression.callee.type === "Identifier") {
620
+ const name = path.node.expression.callee.name;
621
+ if (graph.nodes.has(name) && path.scope.block.type === "Program") {
622
+ const _node = nodeCollection.getNode(name);
623
+ if (_node?.info?.used) {
624
+ _node?.info?.used?.add("Call Expression");
625
+ } else if (_node) {
626
+ _node.info = {
627
+ ..._node?.info,
628
+ used: /* @__PURE__ */ new Set(["Call Expression"])
629
+ };
553
630
  }
554
- } else if (hookName === "useEffect" && path.node.expression.arguments[1].type === "ArrayExpression") {
555
- traverse2(path.node.expression.arguments[1], {
556
- Identifier(path1) {
557
- const binding = path1.scope.getBinding(path1.node.name);
558
- if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
559
- watchArgs.add(path1.node);
560
- }
561
- }
562
- }, path.scope, path);
631
+ } else {
632
+ traverseHooks(path.node.expression, path.scope);
633
+ }
634
+ }
635
+ if (path.type === "ExpressionStatement" && path.node.expression.type === "AssignmentExpression" && path.node.expression.right.type === "CallExpression" && path.node.expression.right.callee.type === "Identifier") {
636
+ traverseHooks(path.node.expression.right, path.scope);
637
+ }
638
+ if (path.type === "ExpressionStatement" && path.node.expression.type === "AssignmentExpression" && path.node.expression.left.type === "Identifier" && graph.nodes.has(path.node.expression.left.name) && path.scope.block.type === "Program") {
639
+ const _node = nodeCollection.getNode(path.node.expression.left.name);
640
+ if (_node?.info?.used) {
641
+ _node?.info?.used?.add("Assignment Expression");
642
+ } else if (_node) {
643
+ _node.info = {
644
+ ..._node?.info,
645
+ used: /* @__PURE__ */ new Set(["Assignment Expression"])
646
+ };
563
647
  }
564
- path.node.expression.arguments.forEach((argNode, index) => {
565
- if (hookName === "watch" && index === 0 && argNode.type === "Identifier") {
566
- const _node = nodeCollection.getNode(argNode.name);
567
- if (_node?.info?.used) {
568
- _node?.info?.used?.add(hookName);
569
- } else if (_node) {
570
- _node.info = {
571
- ..._node?.info,
572
- used: /* @__PURE__ */ new Set([hookName])
573
- };
574
- }
575
- return;
576
- }
577
- traverse2(argNode, {
578
- Identifier(path1) {
579
- const binding = path1.scope.getBinding(path1.node.name);
580
- if (graph.nodes.has(path1.node.name) && (path1.parent.type !== "MemberExpression" && path1.parent.type !== "OptionalMemberExpression" || path1.parent.object === path1.node) && (binding?.scope.block.type === "Program" || parentScope === binding?.scope)) {
581
- if (["watch", "useEffect"].includes(hookName) && watchArgs.size > 0) {
582
- const watchArgsNames = Array.from(watchArgs).map((arg) => arg.name);
583
- watchArgs.forEach((watchArg) => {
584
- if (!watchArgsNames.includes(path1.node.name)) {
585
- graph.edges.get(watchArg.name)?.add(path1.node.name);
586
- }
587
- });
588
- }
589
- const _node = nodeCollection.getNode(path1.node.name);
590
- if (_node?.info?.used) {
591
- _node?.info?.used?.add(hookName);
592
- } else if (_node) {
593
- _node.info = {
594
- ..._node?.info,
595
- used: /* @__PURE__ */ new Set([hookName])
596
- };
597
- }
598
- }
599
- }
600
- }, path.scope, path);
601
- });
602
648
  }
603
649
  }
604
650
  }, parentScope, parentPath);
@@ -2024,6 +2070,9 @@ function findLinearPaths(graph) {
2024
2070
  const visitedNodes = /* @__PURE__ */ new Set();
2025
2071
  const nodeInDegrees = /* @__PURE__ */ new Map();
2026
2072
  for (const [node, edges] of graph.entries()) {
2073
+ if (!nodeInDegrees.has(node)) {
2074
+ nodeInDegrees.set(node, 0);
2075
+ }
2027
2076
  for (const edge of edges) {
2028
2077
  const inDegree = nodeInDegrees.get(edge) || 0;
2029
2078
  nodeInDegrees.set(edge, inDegree + 1);
@@ -2201,11 +2250,16 @@ function gen(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__ */ new
2201
2250
  }
2202
2251
  const paths = findLinearPaths(g);
2203
2252
  paths.forEach((path) => {
2204
- suggestions.push({
2205
- type: "warning" /* warning */,
2206
- message: `Nodes [${path.length > 10 ? `${path.slice(0, 10).map((node) => node.label).join(",")}...(${path.length})` : path.map((node) => node.label).join(",")}] are have function chain calls, perhaps you can refactor it.`,
2207
- nodeInfo: path
2208
- });
2253
+ const firstUsedNodeIndex = path.findIndex((node) => usedNodes.has(node.label));
2254
+ const reverseLastNotUsedNodeIndex = path.slice().reverse().findIndex((node) => !usedNodes.has(node.label));
2255
+ const lastNotUsedNodeIndex = reverseLastNotUsedNodeIndex !== -1 ? path.length - 1 - reverseLastNotUsedNodeIndex : -1;
2256
+ if (firstUsedNodeIndex > -1 && firstUsedNodeIndex < lastNotUsedNodeIndex) {
2257
+ suggestions.push({
2258
+ type: "warning" /* warning */,
2259
+ message: `Nodes [${path.length > 10 ? `${path.slice(0, 10).map((node) => node.label).join(",")}...(${path.length})` : path.map((node) => node.label).join(",")}] are have function chain calls, perhaps you can refactor it.`,
2260
+ nodeInfo: path
2261
+ });
2262
+ }
2209
2263
  });
2210
2264
  if (g.size > 5) {
2211
2265
  const ap = findArticulationPoints(g);
@@ -2234,6 +2288,13 @@ function gen(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__ */ new
2234
2288
  }
2235
2289
 
2236
2290
  // src/vis.ts
2291
+ function filterNodeUserd(used) {
2292
+ const usedArray = Array.from(used || []);
2293
+ return new Set(usedArray.filter((u) => ![
2294
+ "Assignment Expression",
2295
+ "Call Expression"
2296
+ ].includes(u)));
2297
+ }
2237
2298
  function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__ */ new Set()) {
2238
2299
  const usedNodes = /* @__PURE__ */ new Set([...nodesUsedInTemplate, ...nodesUsedInStyle]);
2239
2300
  const nodes = [];
@@ -2244,7 +2305,7 @@ function getVisData(graph, nodesUsedInTemplate, nodesUsedInStyle = /* @__PURE__
2244
2305
  label: node.label,
2245
2306
  shape: node.type === "var" ? "dot" : "diamond",
2246
2307
  group: usedNodes.has(node.label) || node.info?.used?.size ? "used" : "normal",
2247
- title: `${node.info?.used?.size ? `used by ${Array.from(node.info?.used || [])?.map((i) => `\`${i}\``).join(",")}
2308
+ title: `${filterNodeUserd(node.info?.used).size ? `used by ${Array.from(filterNodeUserd(node.info?.used))?.map((i) => `\`${i}\``).join(",")}
2248
2309
 
2249
2310
  ` : ""}${usedNodes.has(node.label) ? `used in ${[
2250
2311
  nodesUsedInStyle.has(node.label) ? "style" : "",