js-code-detector 0.0.15 → 0.0.17

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.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ require('../dist/cjs/index').getEslintCheckResult();
@@ -7,3 +7,4 @@ export declare function getGitRepositoryAndBranch(): Promise<{
7
7
  export declare function generateReport(content: string): void;
8
8
  export declare function sameCodeDetect(dirOfCwd?: string): Promise<void>;
9
9
  export declare function gitDiffDetect(): Promise<void>;
10
+ export declare function getEslintCheckResult(today: string): Promise<void>;
package/dist/cjs/index.js CHANGED
@@ -8,13 +8,13 @@ var __export = (target, all) => {
8
8
  for (var name in all)
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
- var __copyProps = (to, from, except, desc) => {
11
+ var __copyProps = (to2, from, except, desc) => {
12
12
  if (from && typeof from === "object" || typeof from === "function") {
13
13
  for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ if (!__hasOwnProp.call(to2, key) && key !== except)
15
+ __defProp(to2, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
16
  }
17
- return to;
17
+ return to2;
18
18
  };
19
19
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
20
  // If the importer is in node compatibility mode or this is not an ESM
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  var src_exports = {};
31
31
  __export(src_exports, {
32
32
  generateReport: () => generateReport,
33
+ getEslintCheckResult: () => getEslintCheckResult,
33
34
  getGitRepositoryAndBranch: () => getGitRepositoryAndBranch,
34
35
  gitDiffDetect: () => gitDiffDetect,
35
36
  sameCodeDetect: () => sameCodeDetect,
@@ -48,10 +49,17 @@ var import_dayjs = __toESM(require("dayjs"));
48
49
  var import_createMdByJson = require("./util/report_util/createMdByJson");
49
50
  var import_readDirFiles = require("./util/shared/readDirFiles");
50
51
  var import_Core = __toESM(require("./util/ast_util/Core"));
52
+ var import_constants = require("./util/constants");
53
+ var import_await_to_js = __toESM(require("await-to-js"));
51
54
  var jsonName = "git_diff_report.md";
55
+ var gitDiffFileName = "git_diff.txt";
56
+ var gitDiffJsonName = "git_diff.json";
57
+ var eslintJsonName = "eslint-report.json";
58
+ var eslintFinalJsonName = "eslint-final-report.json";
52
59
  async function umiPluginCallback(api) {
53
- const diff_txt = (0, import_fs.readFileSync)((0, import_path.join)(api.cwd, "git_diff.txt"), "utf-8");
60
+ const diff_txt = (0, import_fs.readFileSync)((0, import_path.join)(api.cwd, gitDiffFileName), "utf-8");
54
61
  const gitDiffDetail = (0, import_format_git_diff_content.formatGitDiffContent)(diff_txt);
62
+ (0, import_fs2.writeFileSync)((0, import_path.join)(api.cwd, gitDiffJsonName), JSON.stringify(gitDiffDetail, null, 2), { encoding: "utf-8", flag: "w" });
55
63
  const madgeUtil = await (0, import_madge_util.default)(api);
56
64
  if (!madgeUtil) {
57
65
  return;
@@ -131,19 +139,19 @@ async function gitDiffDetect() {
131
139
  import_utils.logger.ready("准备clone源代码到临时目录下的target文件夹");
132
140
  await import_utils.execa.execa(`git clone ${gitUrl} ${today}/target`, { shell: "/bin/bash" });
133
141
  import_utils.logger.info("源代码clone完成");
134
- import_utils.logger.ready("准备clone源代码到临时目录下的source文件夹");
135
- await import_utils.execa.execa(`git clone ${gitUrl} ${today}/source`, { shell: "/bin/bash" });
142
+ import_utils.logger.ready(`准备clone源代码到临时目录下的 ${import_constants.SOURCE} 文件夹`);
143
+ await import_utils.execa.execa(`git clone ${gitUrl} ${today}/${import_constants.SOURCE}`, { shell: "/bin/bash" });
136
144
  import_utils.logger.info("源代码clone完成");
137
145
  import_utils.logger.ready("准备切换到目标分支");
138
146
  await import_utils.execa.execa(`cd ${today}/target && git fetch origin ${branchName}:${branchName} && git checkout ${branchName}`, { shell: "/bin/bash" });
139
147
  import_utils.logger.info("分支切换完成");
140
148
  import_utils.logger.ready("准备生成git_diff.txt文件");
141
- await import_utils.execa.execa(`cd ${today}/target && git diff master..${branchName} --unified=0 --output=git_diff.txt`, { shell: "/bin/bash" });
149
+ await import_utils.execa.execa(`cd ${today}/target && git diff master..${branchName} --unified=0 --output=${gitDiffFileName}`, { shell: "/bin/bash" });
142
150
  import_utils.logger.info("git_diff.txt文件生成完成");
143
151
  import_utils.logger.ready("准备生成插件文件");
144
152
  (0, import_fs2.writeFileSync)((0, import_path.join)(process.cwd(), today, "target", "plugin.ts"), pluginFileContent, { encoding: "utf-8", flag: "w" });
145
153
  import_utils.logger.info("插件文件生成完成");
146
- import_utils.logger.ready("准备生成报告");
154
+ import_utils.logger.wait("准备生成报告");
147
155
  await import_utils.execa.execa(`cd ${today}/target && yarn install && npm run build`, { shell: "/bin/bash" });
148
156
  import_utils.logger.info("报告生成完成!");
149
157
  import_utils.logger.ready("准备移动报告");
@@ -151,10 +159,37 @@ async function gitDiffDetect() {
151
159
  const mdFileName = `${(0, import_dayjs.default)().format("YYYYMDD_HHmm")}_${jsonName}`;
152
160
  (0, import_fs2.writeFileSync)((0, import_path.join)(process.cwd(), mdFileName), content, { encoding: "utf-8", flag: "w" });
153
161
  import_utils.logger.info("报告完成: " + mdFileName);
162
+ await getEslintCheckResult(today);
163
+ (0, import_utils.rimraf)((0, import_path.join)(process.cwd(), today), () => {
164
+ import_utils.logger.info("临时目录已删除");
165
+ });
166
+ }
167
+ async function getEslintCheckResult(today) {
168
+ today = today || (0, import_dayjs.default)().format("YYYYMDD");
169
+ import_utils.logger.ready("准备生成 eslint 类型检查 json");
170
+ await (0, import_await_to_js.default)(import_utils.execa.execa(`cd ${today}/target && npx eslint src --ext .js,.jsx,.ts,.tsx --format json -o ${eslintJsonName}`, { shell: "/bin/bash" }));
171
+ import_utils.logger.info("eslint 类型检查 json 生成完成");
172
+ import_utils.logger.ready(`读取 ${eslintJsonName} 文件内容,并解析`);
173
+ let eslintJson = [];
174
+ {
175
+ const content = (0, import_fs.readFileSync)((0, import_path.join)(process.cwd(), today, "target", eslintJsonName), "utf-8");
176
+ try {
177
+ eslintJson = JSON.parse(content);
178
+ } catch (error) {
179
+ import_utils.logger.error("解析json文件失败");
180
+ }
181
+ }
182
+ const validEslintJson = eslintJson.filter((e) => {
183
+ const { filePath, ...rest } = e;
184
+ return Object.values(rest).some((v) => Array.isArray(v) && v.length > 0 || !Array.isArray(v) && v);
185
+ });
186
+ (0, import_fs2.writeFileSync)((0, import_path.join)(process.cwd(), eslintFinalJsonName), JSON.stringify(validEslintJson, null, 2), { encoding: "utf-8", flag: "w" });
187
+ import_utils.logger.info(`${eslintFinalJsonName} 文件生成`);
154
188
  }
155
189
  // Annotate the CommonJS export names for ESM import in node:
156
190
  0 && (module.exports = {
157
191
  generateReport,
192
+ getEslintCheckResult,
158
193
  getGitRepositoryAndBranch,
159
194
  gitDiffDetect,
160
195
  sameCodeDetect,
@@ -1,4 +1,5 @@
1
1
  export interface AstNode {
2
+ computed?: boolean;
2
3
  type: string;
3
4
  name?: string;
4
5
  start?: number | null;
@@ -26,71 +27,48 @@ export interface AstNode {
26
27
  dependenceIds: Set<AstNode>;
27
28
  holdingIds: Set<AstNode>;
28
29
  holdingIdNameMap: Map<string, Set<AstNode>>;
30
+ holdingIdType: 'Import' | 'Variable' | 'Function' | 'Class' | 'Param' | null;
29
31
  inject: Set<AstNode>;
30
32
  provide: Set<AstNode>;
31
33
  effectIds: Set<AstNode>;
32
- crossScope: Set<AstNode>;
33
34
  };
34
35
  }
35
36
  export default class AstUtil {
36
37
  static invalidNodeKey: string[];
37
38
  static getNodePath(node: AstNode): string;
38
- static deepFirstTravel(node: AstNode, filePath: string, mapUuidToNode: Map<string, AstNode>, mapFileLineToNodeSet: Map<number, Set<AstNode>>): AstNode | undefined;
39
- static _deepFirstTravel(node: AstNode, visitedNodeSet: Set<typeof node>, extra: {
40
- filePath: string;
41
- depth: number;
42
- mapUuidToNode: Map<string, AstNode>;
43
- mapFileLineToNodeSet: Map<number, Set<AstNode>>;
44
- }): AstNode;
45
- static collectInjectProvide(ast: AstNode): void;
46
- static collectHoldingIds(node: AstNode & {
47
- body: AstNode | null;
48
- }): void;
49
- static isVarInit(node: AstNode): boolean;
39
+ static getShortNodeMsg(node: AstNode): string;
40
+ static deepFirstTravel(node: AstNode, filePath: string, mapUuidToNode: Map<string, AstNode>, mapFileLineToNodeSet: Map<number, Set<AstNode>>, mapPathToNodeSet: Map<string, Set<AstNode>>): AstNode | undefined;
41
+ private static _deepFirstTravel;
42
+ private static collectInjectAndProvide;
43
+ private static collectHoldingIds;
44
+ private static isVarInit;
50
45
  static isReturnArgument(node: AstNode): boolean;
51
- static collectDependenceIds(node: AstNode): void;
52
- static markDependenceIdCrossScope(node: AstNode, scopeId: AstNode): void;
53
- static isUseStateVarDec(node: AstNode): node is (AstNode & {
54
- type: "VariableDeclarator";
55
- id: {
56
- type: "ArrayPattern";
57
- elements: (null | AstNode)[];
58
- };
59
- init: {
60
- type: "CallExpression";
61
- callee: AstNode;
62
- arguments: [AstNode] | [];
63
- };
64
- });
46
+ private static collectDependenceIds;
47
+ private static isUseStateVarDec;
65
48
  static isUseMemoVarDec(node: AstNode): boolean;
66
- static isUseCallbackVarDec(node: AstNode): boolean;
67
- static collectEffectId(node: AstNode): void;
68
- static collectEffectIdOfVarDec(node: AstNode): void;
69
- static collectEffectIdOfUseState(node: AstNode): void;
70
- static collectEffectIdOfUseMemo(node: AstNode): void;
71
- static collectEffectIdOfUseCallback(node: AstNode): void;
72
- static collectEffectIdOfAssign(node: AstNode): void;
73
- static collectEffectIdOfUnaryUpdate(node: AstNode): void;
74
- static isBodyArray(node: AstNode): node is ({
75
- body: AstNode[];
76
- } & AstNode);
77
- static findExportIdentifiers(node: any, callback: (identifier: AstNode) => void): void;
78
- static expressionTypeIsIdentifier(exp: AstNode | null): exp is AstNode & {
79
- type: "Identifier";
80
- };
49
+ private static isUseCallbackVarDec;
50
+ private static collectEffectId;
51
+ private static collectEffectIdOfFnCall;
52
+ private static collectEffectIdOfVarDec;
53
+ private static collectEffectIdOfUseState;
54
+ private static collectEffectIdOfUseMemo;
55
+ private static collectEffectIdOfUseCallback;
56
+ private static collectEffectIdOfAssign;
57
+ private static collectEffectIdOfUnaryUpdate;
58
+ private static isBodyArray;
59
+ private static findExportIdentifiers;
60
+ private static expressionTypeIsIdentifier;
61
+ static collectExpressionIdentifiers(exp: AstNode | null, callback: (identifier: AstNode) => void): void;
62
+ private static _collectExpressionIdentifiers;
81
63
  static deepFindIdOfExpression(exp: AstNode | null, callback: (identifier: AstNode) => void): void;
82
- static _deepFindIdOfExpression(exp: AstNode | null, callback: (identifier: AstNode) => void): void;
83
- static getRootIdentifierOfMemberExpression(memExp: AstNode): AstNode;
84
- static findIdOfImport(node: AstNode, callback: (identifier: AstNode) => void): void;
85
- static findIdOfFunctionOrVariableOrClass(node: AstNode, callback: (identifier: AstNode) => void): void;
86
- static findIdOfVariable(node: AstNode, callback: (identifier: AstNode) => void): void;
64
+ private static _deepFindIdOfExpression;
65
+ private static getRootIdentifierOfMemberExpression;
66
+ private static findIdOfImport;
67
+ private static findIdOfVariable;
87
68
  private static _deepFindIdentifier;
88
- static updateLoc(astNode: AstNode, extra: {
89
- mapUuidToNode: Map<string, AstNode>;
90
- mapFileLineToNodeSet: Map<number, Set<AstNode>>;
91
- }): void;
92
- static isValidArrayNodeCollect(astNode: any): astNode is AstNode[];
93
- static isValidNodeCollect(astNode: AstNode): astNode is AstNode;
69
+ private static updateLoc;
70
+ private static isValidArrayNodeCollect;
71
+ private static isValidNodeCollect;
94
72
  static windowProperties: string[];
95
73
  static intrinsicElements: string[];
96
74
  static standardAttributes: string[];
@@ -24,20 +24,24 @@ __export(AstUtil_exports, {
24
24
  module.exports = __toCommonJS(AstUtil_exports);
25
25
  var import_windowProperties = require("./windowProperties");
26
26
  var import_intrinsicElements = require("./intrinsicElements");
27
- var AstUtil = class {
27
+ var _AstUtil = class {
28
28
  static getNodePath(node) {
29
29
  return [...node._util.ancestors, node].map((n) => n.type).join(":") + ":" + node.name;
30
30
  }
31
- static deepFirstTravel(node, filePath, mapUuidToNode, mapFileLineToNodeSet) {
31
+ static getShortNodeMsg(node) {
32
+ const { _util: { startLine, startColumn, endLine, endColumn } } = node;
33
+ return `${node.name || node.type}「${startLine}:${startColumn}, ${endLine}:${endColumn}」`;
34
+ }
35
+ static deepFirstTravel(node, filePath, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet) {
32
36
  const visitedNodeSet = /* @__PURE__ */ new Set();
33
37
  if (!node) {
34
38
  return;
35
39
  }
36
- return this._deepFirstTravel(node, visitedNodeSet, { filePath, depth: 0, mapUuidToNode, mapFileLineToNodeSet });
40
+ return this._deepFirstTravel(node, visitedNodeSet, { filePath, depth: 0, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet });
37
41
  }
38
42
  static _deepFirstTravel(node, visitedNodeSet, extra) {
39
43
  visitedNodeSet.add(node);
40
- const { filePath, depth, mapUuidToNode, mapFileLineToNodeSet } = extra;
44
+ const { filePath, depth, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet } = extra;
41
45
  const _util = {
42
46
  startLine: NaN,
43
47
  endLine: NaN,
@@ -53,12 +57,12 @@ var AstUtil = class {
53
57
  uuid: "",
54
58
  variableScope: [],
55
59
  dependenceIds: /* @__PURE__ */ new Set(),
60
+ holdingIdType: null,
56
61
  holdingIds: /* @__PURE__ */ new Set(),
57
62
  holdingIdNameMap: /* @__PURE__ */ new Map(),
58
63
  inject: /* @__PURE__ */ new Set(),
59
64
  provide: /* @__PURE__ */ new Set(),
60
- effectIds: /* @__PURE__ */ new Set(),
61
- crossScope: /* @__PURE__ */ new Set()
65
+ effectIds: /* @__PURE__ */ new Set()
62
66
  };
63
67
  node._util = _util;
64
68
  const { nodeCollection, children } = _util;
@@ -71,13 +75,13 @@ var AstUtil = class {
71
75
  return;
72
76
  }
73
77
  if (this.isValidNodeCollect(nodeValue)) {
74
- const childNode = this._deepFirstTravel(nodeValue, visitedNodeSet, { filePath, depth: depth + 1, mapUuidToNode, mapFileLineToNodeSet });
78
+ const childNode = this._deepFirstTravel(nodeValue, visitedNodeSet, { filePath, depth: depth + 1, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet });
75
79
  nodeCollection.push(childNode, ...childNode._util.nodeCollection);
76
80
  children.push(childNode);
77
81
  childNode._util.parentProperty = nodeKey;
78
82
  } else if (this.isValidArrayNodeCollect(nodeValue)) {
79
83
  const validNodeArray = nodeValue.filter((nodeItem) => this.isValidNodeCollect(nodeItem)).map((v) => {
80
- return this._deepFirstTravel(v, visitedNodeSet, { filePath, depth: depth + 1, mapUuidToNode, mapFileLineToNodeSet });
84
+ return this._deepFirstTravel(v, visitedNodeSet, { filePath, depth: depth + 1, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet });
81
85
  });
82
86
  nodeCollection.push(...validNodeArray.map((n) => [n, ...n._util.nodeCollection]).flat());
83
87
  children.push(...validNodeArray);
@@ -90,12 +94,15 @@ var AstUtil = class {
90
94
  children.forEach((child) => child._util.parent = node);
91
95
  nodeCollection.forEach((nodeItem) => nodeItem._util.ancestors.unshift(node));
92
96
  this.collectHoldingIds(node);
93
- this.collectInjectProvide(node);
94
- this.collectEffectId(node);
95
- this.updateLoc(node, { mapUuidToNode, mapFileLineToNodeSet });
97
+ this.collectDependenceIds(node);
98
+ this.collectInjectAndProvide(node);
99
+ if (node.type === "Program") {
100
+ nodeCollection.forEach((child) => this.collectEffectId(child));
101
+ }
102
+ this.updateLoc(node, { mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet });
96
103
  return node;
97
104
  }
98
- static collectInjectProvide(ast) {
105
+ static collectInjectAndProvide(ast) {
99
106
  const { type, _util: { inject, provide, holdingIds } } = ast;
100
107
  if (type !== "Program" || !this.isBodyArray(ast)) {
101
108
  return;
@@ -113,7 +120,7 @@ var AstUtil = class {
113
120
  const theOne = [...holdingIds].find((e) => e.name === declaration.name);
114
121
  theOne && provide.add(theOne);
115
122
  } else {
116
- this.deepFindIdOfExpression(declaration, (id) => provide.add(id));
123
+ provide.add(declaration);
117
124
  }
118
125
  }
119
126
  if (node.type === "ExportNamedDeclaration") {
@@ -136,23 +143,53 @@ var AstUtil = class {
136
143
  const { body } = node;
137
144
  body.forEach((cur) => {
138
145
  if (cur.type === "ImportDeclaration") {
139
- this.findIdOfImport(cur, (id) => holdingIds.add(id));
146
+ this.findIdOfImport(cur, (id) => {
147
+ holdingIds.add(id);
148
+ id._util.variableScope = [id];
149
+ id._util.holdingIdType = "Import";
150
+ });
140
151
  } else if (cur.type === "FunctionDeclaration" || cur.type === "ClassDeclaration") {
141
152
  const id = cur.id;
142
- id && holdingIds.add(id);
153
+ if (id) {
154
+ holdingIds.add(id);
155
+ id._util.variableScope = [id];
156
+ id._util.holdingIdType = cur.type === "ClassDeclaration" ? "Class" : "Function";
157
+ }
143
158
  } else if (cur.type === "VariableDeclaration") {
144
- this.findIdOfVariable(cur, (id) => holdingIds.add(id));
159
+ this.findIdOfVariable(cur, (id) => {
160
+ holdingIds.add(id);
161
+ id._util.variableScope = [id];
162
+ id._util.holdingIdType = "Variable";
163
+ });
145
164
  }
146
165
  });
147
166
  }
148
167
  if (node.body && this.isBodyArray(node.body)) {
149
168
  const { body } = node.body;
150
169
  body.forEach((cur) => {
151
- this.findIdOfFunctionOrVariableOrClass(cur, (id) => holdingIds.add(id));
170
+ if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
171
+ const id = node.id;
172
+ if (id) {
173
+ holdingIds.add(id);
174
+ id._util.variableScope = [id];
175
+ id._util.holdingIdType = node.type === "ClassDeclaration" ? "Class" : "Function";
176
+ }
177
+ } else if (node.type === "VariableDeclaration") {
178
+ this.findIdOfVariable(node, (id) => {
179
+ holdingIds.add(id);
180
+ id._util.variableScope = [id];
181
+ id._util.holdingIdType = "Variable";
182
+ });
183
+ }
152
184
  });
153
185
  }
154
186
  if (["FunctionDeclaration", "ArrowFunctionExpression", "FunctionExpression"].includes(node.type)) {
155
- node.params.forEach((param) => this._deepFindIdentifier(param, (id) => holdingIds.add(id)));
187
+ const params = node.params;
188
+ params.forEach((param) => this._deepFindIdentifier(param, (id) => {
189
+ holdingIds.add(id || node);
190
+ id._util.variableScope = [id];
191
+ id._util.holdingIdType = "Param";
192
+ }));
156
193
  }
157
194
  holdingIds.forEach((holdingId) => {
158
195
  const holdingIdName = holdingId.name;
@@ -160,7 +197,6 @@ var AstUtil = class {
160
197
  nodeSetOfIdName.add(holdingId);
161
198
  holdingIdNameMap.set(holdingIdName, nodeSetOfIdName);
162
199
  });
163
- this.collectDependenceIds(node);
164
200
  }
165
201
  static isVarInit(node) {
166
202
  var _a;
@@ -173,44 +209,20 @@ var AstUtil = class {
173
209
  static collectDependenceIds(node) {
174
210
  const { nodeCollection, dependenceIds, holdingIdNameMap } = node._util;
175
211
  nodeCollection.forEach((e) => {
176
- this.deepFindIdOfExpression(e, (id) => dependenceIds.add(id));
177
212
  this.findExportIdentifiers(e, (id) => dependenceIds.add(id));
178
- if (e.type === "Identifier" && (this.isVarInit(e) || this.isReturnArgument(e))) {
179
- dependenceIds.add(e);
180
- }
213
+ this.collectExpressionIdentifiers(e, (id) => dependenceIds.add(id));
181
214
  });
182
215
  for (const dependenceId of dependenceIds) {
183
216
  if (dependenceId._util.variableScope.length === 0) {
184
217
  const sameNameIds = [...holdingIdNameMap.get(dependenceId.name) || []];
185
218
  dependenceId._util.variableScope.push(...sameNameIds);
186
219
  const firstPick = sameNameIds[0];
187
- if (firstPick) {
220
+ if (firstPick && firstPick._util.uuid !== dependenceId._util.uuid) {
188
221
  firstPick._util.effectIds.add(dependenceId);
189
- this.markDependenceIdCrossScope(dependenceId, firstPick);
190
222
  }
191
223
  }
192
224
  }
193
225
  }
194
- static markDependenceIdCrossScope(node, scopeId) {
195
- var _a, _b, _c;
196
- const isParamsElement = scopeId._util.parentProperty === "params";
197
- const isCalleeId = ((_a = node._util.parent) == null ? void 0 : _a.type) === "CallExpression" && node._util.parentProperty === "callee";
198
- if (isParamsElement && isCalleeId) {
199
- const fn = scopeId._util.parent;
200
- const isFn = fn.type === "FunctionExpression" || fn.type === "ArrowFunctionExpression";
201
- const isFnInVarDec = fn._util.parentProperty === "init" && ((_b = fn._util.parent) == null ? void 0 : _b.type) === "VariableDeclarator";
202
- const isFnInAssign = fn._util.parentProperty === "right" && ((_c = fn._util.parent) == null ? void 0 : _c.type) === "AssignmentExpression";
203
- if (isFn && isFnInVarDec) {
204
- const idHolderOfFn = fn._util.parent.id;
205
- node._util.crossScope.add(idHolderOfFn);
206
- } else if (isFn && isFnInAssign) {
207
- const idHolderOfFn = fn._util.parent.left;
208
- node._util.crossScope.add(idHolderOfFn);
209
- } else if (fn.type === "FunctionDeclaration") {
210
- node._util.crossScope.add(fn);
211
- }
212
- }
213
- }
214
226
  static isUseStateVarDec(node) {
215
227
  if (node.type !== "VariableDeclarator")
216
228
  return false;
@@ -250,6 +262,50 @@ var AstUtil = class {
250
262
  const isDeleteOperator = "UnaryExpression" === node.type && node.operator === "delete";
251
263
  if (isDeleteOperator || ["UpdateExpression"].includes(node.type)) {
252
264
  this.collectEffectIdOfUnaryUpdate(node);
265
+ return;
266
+ }
267
+ if (node.type === "CallExpression") {
268
+ this.collectEffectIdOfFnCall(node);
269
+ return;
270
+ }
271
+ }
272
+ static collectEffectIdOfFnCall(node) {
273
+ var _a, _b, _c;
274
+ if (node.type !== "CallExpression") {
275
+ return;
276
+ }
277
+ const idSet = /* @__PURE__ */ new Set();
278
+ this.collectExpressionIdentifiers(node, (id) => idSet.add(id));
279
+ for (const id of idSet) {
280
+ if (id._util.variableScope.length === 0) {
281
+ continue;
282
+ }
283
+ const scopeId = id._util.variableScope[0];
284
+ const isParamsElement = scopeId._util.parentProperty === "params";
285
+ if (isParamsElement) {
286
+ const fnNode = scopeId._util.parent;
287
+ if (fnNode.type === "FunctionExpression" || fnNode.type === "ArrowFunctionExpression") {
288
+ if (fnNode._util.parentProperty === "init" && ((_a = fnNode._util.parent) == null ? void 0 : _a.type) === "VariableDeclarator") {
289
+ fnNode._util.parent.id._util.effectIds.add(id);
290
+ } else if (fnNode._util.parentProperty === "right" && ((_b = fnNode._util.parent) == null ? void 0 : _b.type) === "AssignmentExpression") {
291
+ fnNode._util.parent.left._util.effectIds.add(id);
292
+ } else if (fnNode._util.parentProperty === "value" && ((_c = fnNode._util.parent) == null ? void 0 : _c.type) === "MethodDefinition") {
293
+ fnNode._util.parent.key._util.effectIds.add(id);
294
+ }
295
+ } else if (fnNode.type === "FunctionDeclaration") {
296
+ fnNode._util.effectIds.add(id);
297
+ }
298
+ }
299
+ const kindOfParamsElement = [...scopeId._util.effectIds].filter((e) => {
300
+ var _a2;
301
+ return ((_a2 = e._util.variableScope[0]) == null ? void 0 : _a2._util.holdingIdType) === "Param";
302
+ });
303
+ if (kindOfParamsElement.length > 0) {
304
+ kindOfParamsElement.map((ele) => {
305
+ var _a2;
306
+ (_a2 = ele._util.variableScope[0]._util.parent) == null ? void 0 : _a2._util.effectIds.add(id);
307
+ });
308
+ }
253
309
  }
254
310
  }
255
311
  static collectEffectIdOfVarDec(node) {
@@ -272,7 +328,7 @@ var AstUtil = class {
272
328
  const idSet = /* @__PURE__ */ new Set();
273
329
  this._deepFindIdentifier(id, (ele) => idSet.add(ele));
274
330
  const createdExpIdSet = /* @__PURE__ */ new Set();
275
- ["Identifier", "ArrowFunctionExpression", "FunctionExpression"].includes(init.type) ? createdExpIdSet.add(init) : this.deepFindIdOfExpression(init, (id2) => createdExpIdSet.add(id2));
331
+ ["Identifier", "ArrowFunctionExpression", "FunctionExpression"].includes(init.type) ? createdExpIdSet.add(init) : this.collectExpressionIdentifiers(init, (id2) => createdExpIdSet.add(id2));
276
332
  for (const createdId of idSet) {
277
333
  createdId._util.effectIds = /* @__PURE__ */ new Set([...createdExpIdSet, ...createdId._util.effectIds]);
278
334
  }
@@ -289,7 +345,7 @@ var AstUtil = class {
289
345
  this._deepFindIdentifier(stateNode, (ele) => stateIdSet.add(ele));
290
346
  const setStateIdSet = /* @__PURE__ */ new Set();
291
347
  if (setStateNode) {
292
- this._deepFindIdentifier(setStateNode, (ele) => setStateIdSet.add(ele));
348
+ setStateIdSet.add(setStateNode);
293
349
  }
294
350
  for (const stateId of stateIdSet) {
295
351
  stateId._util.effectIds = /* @__PURE__ */ new Set([...argsIdSet, ...setStateIdSet]);
@@ -319,14 +375,14 @@ var AstUtil = class {
319
375
  static collectEffectIdOfAssign(node) {
320
376
  const { left, right } = node;
321
377
  const idSetOfRight = /* @__PURE__ */ new Set();
322
- this.deepFindIdOfExpression(right, (id) => idSetOfRight.add(id));
378
+ this.collectExpressionIdentifiers(right, (id) => idSetOfRight.add(id));
323
379
  if (left.type === "Identifier") {
324
380
  const { left: left2 } = node;
325
381
  left2._util.effectIds = /* @__PURE__ */ new Set([...idSetOfRight, ...left2._util.effectIds]);
326
382
  } else {
327
383
  const { left: left2 } = node;
328
384
  const idSetOfLeft = /* @__PURE__ */ new Set();
329
- this.deepFindIdOfExpression(left2, (id) => idSetOfLeft.add(id));
385
+ this.collectExpressionIdentifiers(left2, (id) => idSetOfLeft.add(id));
330
386
  for (const id of idSetOfLeft) {
331
387
  id._util.effectIds = /* @__PURE__ */ new Set([...idSetOfRight, ...id._util.effectIds]);
332
388
  }
@@ -336,7 +392,7 @@ var AstUtil = class {
336
392
  static collectEffectIdOfUnaryUpdate(node) {
337
393
  const { argument } = node;
338
394
  const idSetOfArgument = /* @__PURE__ */ new Set();
339
- this.deepFindIdOfExpression(argument, (id) => idSetOfArgument.add(id));
395
+ this.collectExpressionIdentifiers(argument, (id) => idSetOfArgument.add(id));
340
396
  argument._util.effectIds = /* @__PURE__ */ new Set([...argument._util.effectIds, ...idSetOfArgument]);
341
397
  }
342
398
  static isBodyArray(node) {
@@ -354,8 +410,7 @@ var AstUtil = class {
354
410
  if (node.type === "ExportNamedDeclaration" && Array.isArray(node.specifiers)) {
355
411
  for (const specifier of node.specifiers) {
356
412
  if (specifier.type === "ExportSpecifier") {
357
- const local = specifier.local;
358
- callback(local);
413
+ callback(specifier.local);
359
414
  }
360
415
  }
361
416
  }
@@ -363,6 +418,36 @@ var AstUtil = class {
363
418
  static expressionTypeIsIdentifier(exp) {
364
419
  return (exp == null ? void 0 : exp.type) === "Identifier";
365
420
  }
421
+ static collectExpressionIdentifiers(exp, callback) {
422
+ if (!exp || exp.type === "ThisExpression") {
423
+ return;
424
+ }
425
+ this._collectExpressionIdentifiers(exp, callback);
426
+ }
427
+ static _collectExpressionIdentifiers(exp, callback) {
428
+ var _a, _b, _c;
429
+ if (!exp || exp.type === "ThisExpression") {
430
+ return;
431
+ }
432
+ if (exp._util.holdingIdType !== null) {
433
+ return;
434
+ }
435
+ if (exp.type === "Identifier") {
436
+ if (exp._util.parentProperty === "property" || exp._util.parentProperty === "key") {
437
+ if (exp._util.parent.computed) {
438
+ callback(exp);
439
+ }
440
+ } else if (!((_b = (_a = exp._util.parent) == null ? void 0 : _a.type) == null ? void 0 : _b.startsWith("TS"))) {
441
+ callback(exp);
442
+ }
443
+ return;
444
+ }
445
+ if (exp.type === "JSXIdentifier" && ((_c = exp._util.parent) == null ? void 0 : _c.type) !== "JSXAttribute") {
446
+ callback(exp);
447
+ return;
448
+ }
449
+ exp._util.nodeCollection.forEach((ele) => this._collectExpressionIdentifiers(ele, callback));
450
+ }
366
451
  static deepFindIdOfExpression(exp, callback) {
367
452
  if (!exp || exp.type === "ThisExpression") {
368
453
  return;
@@ -370,10 +455,20 @@ var AstUtil = class {
370
455
  this._deepFindIdOfExpression(exp, callback);
371
456
  }
372
457
  static _deepFindIdOfExpression(exp, callback) {
458
+ var _a;
373
459
  if (!exp || exp.type === "ThisExpression") {
374
460
  return;
375
461
  }
376
- if (exp.type === "SpreadElement") {
462
+ if (exp.type === "IfStatement") {
463
+ const { test, alternate, consequent } = exp;
464
+ test.type === "Identifier" ? callback(test) : this._deepFindIdOfExpression(test, callback);
465
+ this._deepFindIdOfExpression(consequent, callback);
466
+ this._deepFindIdOfExpression(alternate, callback);
467
+ } else if (exp.type === "TryStatement") {
468
+ const { block, finalizer } = exp;
469
+ this._deepFindIdOfExpression(block, callback);
470
+ finalizer && this._deepFindIdOfExpression(finalizer, callback);
471
+ } else if (exp.type === "SpreadElement") {
377
472
  const { argument } = exp;
378
473
  this.expressionTypeIsIdentifier(argument) && callback(argument);
379
474
  } else if (exp.type === "JSXSpreadChild") {
@@ -424,7 +519,7 @@ var AstUtil = class {
424
519
  } else if (exp.type === "JSXExpressionContainer") {
425
520
  const { expression } = exp;
426
521
  expression.name && callback(expression);
427
- } else if (exp.type === "JSXIdentifier") {
522
+ } else if (exp.type === "JSXIdentifier" && ((_a = exp._util.parent) == null ? void 0 : _a.type) !== "JSXAttribute") {
428
523
  callback(exp);
429
524
  } else if (exp.type === "JSXAttribute") {
430
525
  const value = exp.value;
@@ -449,16 +544,7 @@ var AstUtil = class {
449
544
  static findIdOfImport(node, callback) {
450
545
  const specifiers = node.specifiers;
451
546
  for (const specifier of specifiers) {
452
- const local = specifier.local;
453
- callback(local);
454
- }
455
- }
456
- static findIdOfFunctionOrVariableOrClass(node, callback) {
457
- if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
458
- const id = node.id;
459
- id && callback(id);
460
- } else if (node.type === "VariableDeclaration") {
461
- this.findIdOfVariable(node, callback);
547
+ callback(specifier.local);
462
548
  }
463
549
  }
464
550
  static findIdOfVariable(node, callback) {
@@ -499,10 +585,10 @@ var AstUtil = class {
499
585
  }
500
586
  }
501
587
  static updateLoc(astNode, extra) {
502
- var _a, _b, _c, _d, _e;
588
+ var _a, _b, _c, _d, _e, _f, _g;
503
589
  const { _util, type, name } = astNode;
504
- const { mapUuidToNode, mapFileLineToNodeSet } = extra;
505
- const { nodeCollection, filePath } = _util;
590
+ const { mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet } = extra;
591
+ const { nodeCollection, filePath, parent } = _util;
506
592
  _util.startLine = Math.min(...nodeCollection.map((n) => {
507
593
  var _a2, _b2;
508
594
  return (_b2 = (_a2 = n.loc) == null ? void 0 : _a2.start) == null ? void 0 : _b2.line;
@@ -511,23 +597,31 @@ var AstUtil = class {
511
597
  var _a2, _b2;
512
598
  return (_b2 = (_a2 = n.loc) == null ? void 0 : _a2.end) == null ? void 0 : _b2.line;
513
599
  }), (_b = astNode.loc) == null ? void 0 : _b.end.line);
514
- _util.startColumn = Math.min(...nodeCollection.map((n) => {
600
+ _util.startColumn = ((_c = astNode.loc) == null ? void 0 : _c.start.column) ?? Math.min(...nodeCollection.map((n) => {
515
601
  var _a2, _b2;
516
602
  return (_b2 = (_a2 = n.loc) == null ? void 0 : _a2.start) == null ? void 0 : _b2.column;
517
- }), (_c = astNode.loc) == null ? void 0 : _c.start.column);
518
- _util.endColumn = Math.max(...nodeCollection.map((n) => {
603
+ }), (_d = astNode.loc) == null ? void 0 : _d.start.column);
604
+ _util.endColumn = ((_e = astNode.loc) == null ? void 0 : _e.end.column) ?? Math.max(...nodeCollection.map((n) => {
519
605
  var _a2, _b2;
520
606
  return (_b2 = (_a2 = n.loc) == null ? void 0 : _a2.end) == null ? void 0 : _b2.column;
521
- }), (_d = astNode.loc) == null ? void 0 : _d.end.column);
607
+ }), (_f = astNode.loc) == null ? void 0 : _f.end.column);
522
608
  _util.uuid = `${filePath}:${type}:${name}「${_util.startLine}:${_util.startColumn},${_util.endLine}:${_util.endColumn}」`;
523
609
  mapUuidToNode.set(_util.uuid, astNode);
524
610
  for (let i = _util.startLine; i <= _util.endLine; i++) {
525
611
  mapFileLineToNodeSet.set(i, mapFileLineToNodeSet.get(i) || /* @__PURE__ */ new Set());
526
- (_e = mapFileLineToNodeSet.get(i)) == null ? void 0 : _e.add(astNode);
612
+ (_g = mapFileLineToNodeSet.get(i)) == null ? void 0 : _g.add(astNode);
527
613
  }
528
614
  if (astNode.type === "Program") {
529
615
  mapUuidToNode.set(astNode.type, astNode);
530
616
  }
617
+ if (parent === null) {
618
+ nodeCollection.forEach((n) => {
619
+ var _a2;
620
+ const path = _AstUtil.getNodePath(n);
621
+ mapPathToNodeSet.set(path, mapPathToNodeSet.get(path) || /* @__PURE__ */ new Set());
622
+ (_a2 = mapPathToNodeSet.get(path)) == null ? void 0 : _a2.add(n);
623
+ });
624
+ }
531
625
  }
532
626
  static isValidArrayNodeCollect(astNode) {
533
627
  return Array.isArray(astNode) && astNode.some((v) => typeof (v == null ? void 0 : v.type) === "string");
@@ -587,6 +681,7 @@ var AstUtil = class {
587
681
  return [node._util.filePath, ":", node._util.startLine, "-", node._util.endLine, ":[", node.name || node.value, "]"].join("");
588
682
  }
589
683
  };
684
+ var AstUtil = _AstUtil;
590
685
  AstUtil.invalidNodeKey = [
591
686
  "comments",
592
687
  "tokens"
@@ -2,4 +2,5 @@ import { AstNode } from "./AstUtil";
2
2
  export default function getAstKitByFilePath(filePath: string, absPathPrefix: string): {
3
3
  mapFileLineToNodeSet: Map<number, Set<AstNode>>;
4
4
  mapUuidToNode: Map<string, AstNode>;
5
+ mapPathToNodeSet: Map<string, Set<AstNode>>;
5
6
  };
@@ -38,10 +38,11 @@ var mapFilePathToTools = /* @__PURE__ */ new Map();
38
38
  var createMapFileLineToNodeSet = (file, absPathPrefix) => {
39
39
  const ast = import_FileUtil.default.getASTByFilePath(file);
40
40
  const mapUuidToNode = /* @__PURE__ */ new Map();
41
+ const mapPathToNodeSet = /* @__PURE__ */ new Map();
41
42
  const mapFileLineToNodeSet = /* @__PURE__ */ new Map();
42
43
  const filePathRelative = file.replace(absPathPrefix, "");
43
- import_AstUtil.default.deepFirstTravel(ast, filePathRelative, mapUuidToNode, mapFileLineToNodeSet);
44
- return { mapFileLineToNodeSet, mapUuidToNode };
44
+ import_AstUtil.default.deepFirstTravel(ast, filePathRelative, mapUuidToNode, mapFileLineToNodeSet, mapPathToNodeSet);
45
+ return { mapFileLineToNodeSet, mapUuidToNode, mapPathToNodeSet };
45
46
  };
46
47
  function getAstKitByFilePath(filePath, absPathPrefix) {
47
48
  let tools = mapFilePathToTools.get(filePath);
@@ -0,0 +1,2 @@
1
+ export declare const SOURCE = "source";
2
+ export declare const TARGET = "target";
@@ -0,0 +1,32 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/util/constants.ts
20
+ var constants_exports = {};
21
+ __export(constants_exports, {
22
+ SOURCE: () => SOURCE,
23
+ TARGET: () => TARGET
24
+ });
25
+ module.exports = __toCommonJS(constants_exports);
26
+ var SOURCE = "source";
27
+ var TARGET = "target";
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ SOURCE,
31
+ TARGET
32
+ });
@@ -35,6 +35,7 @@ module.exports = __toCommonJS(code_block_detect_exports);
35
35
  var import_path = require("path");
36
36
  var import_getAstKitByFilePath = __toESM(require("../ast_util/getAstKitByFilePath"));
37
37
  var import_AstUtil = __toESM(require("../ast_util/AstUtil"));
38
+ var import_constants = require("../constants");
38
39
  var createBlockReport = (kind, index) => ({
39
40
  index,
40
41
  diff_txt: [],
@@ -68,7 +69,7 @@ function codeBlockDetect(arg) {
68
69
  const { gitDiffItem, absPathPrefix, blockReports, index } = arg;
69
70
  const { filePath, startLineOfNew, items, startLineOfOld } = gitDiffItem;
70
71
  const { mapFileLineToNodeSet, mapUuidToNode } = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
71
- const filePathOfOld = (0, import_path.join)(process.cwd(), "..", "source", filePath);
72
+ const filePathOfOld = (0, import_path.join)(process.cwd(), "..", import_constants.SOURCE, filePath);
72
73
  const { mapFileLineToNodeSet: mapFileLineToNodeSetOld } = (0, import_getAstKitByFilePath.default)(filePathOfOld, absPathPrefix);
73
74
  const programNode = mapUuidToNode.get("Program");
74
75
  if (programNode) {
@@ -106,7 +107,7 @@ function extractEffectItem(list) {
106
107
  function pushBlockReport(blockReportInfoItem, programNode, index) {
107
108
  if (blockReportInfoItem.kind === "Other") {
108
109
  ["added", "removed"].forEach((key) => {
109
- const tailElements = blockReportInfoItem[key].map((ele) => ele.split(":").at(-1)).filter(Boolean);
110
+ const tailElements = blockReportInfoItem[key].map((ele) => ele.split(":").at(-1)).filter((e) => e && e !== "undefined");
110
111
  blockReportInfoItem[key] = [...new Set(tailElements)];
111
112
  });
112
113
  }
@@ -35,12 +35,14 @@ ${report.map((r) => `- ${r.filePath}`).join("\n")}
35
35
  return allFiles + report.map(reportItemToMd).join("\n\n\n");
36
36
  }
37
37
  function reportItemToMd(report) {
38
- const { filePath, filesDependsOnMe, type, dangerIdentifiers, blockReports } = report;
38
+ const { filePath, filesDependsOnMe, type, dangerIdentifiers, undefinedIdentifiers, blockReports } = report;
39
39
  return [
40
40
  `## ${filePath}`,
41
41
  `### 类型: ${mapReportType[type]}`,
42
- filesDependsOnMe.length > 0 ? `### 所影响的文件
43
- ${filesDependsOnMe.map((files) => `- ${files.join("")}`).join("\n")}` : "",
42
+ filesDependsOnMe.length > 0 ? `### 所影响的文件(重要性由高到低)
43
+ ${filesDependsOnMe.map((files, index) => files.map((file) => " ".repeat(index) + `- ${file}`)).flat().join("\n")}` : "",
44
+ undefinedIdentifiers.length > 0 ? `### 未定义的变量
45
+ > ${undefinedIdentifiers.map((e) => `**${e}**`).join(", ")}` : "",
44
46
  dangerIdentifiers.length > 0 ? `### 重点检查使用的变量
45
47
  > ${dangerIdentifiers.join(", ")}` : "",
46
48
  blockReports.length > 0 ? `### 对比分析 共${blockReports.length}处` : "",
@@ -63,23 +65,14 @@ ${diff_txt.join("\n")}
63
65
  }
64
66
  function blockReportInfoItemToMd(info, index) {
65
67
  const {
66
- kind,
67
- added,
68
- addedEffects,
69
- removed,
70
- removedEffects
68
+ causeBy,
69
+ effects
71
70
  } = info;
72
71
  return [
73
- `#### 分类${index + 1}: ${kind}`,
74
- added.length > 0 ? `- 新增标识符
75
- > ${added.join(", ")}` : "",
76
- addedEffects.length > 0 ? `- 新增标识符影响
77
- ` : "",
78
- addedEffects.map(({ causeBy, effects }) => `> ${causeBy}相关: ${effects.join()}`).join("\n\n"),
79
- removed.length > 0 ? `- 删除标识符
80
- > ${removed.join(", ")}` : "",
81
- removedEffects.length > 0 ? `- 删除标识符影响` : "",
82
- removedEffects.map(({ causeBy, effects }) => `> ${causeBy}相关: ${effects.join()}`).join("\n\n")
72
+ `#### 序号${index + 1}`,
73
+ effects.length > 0 ? `#### ${causeBy}
74
+ - 影响:
75
+ ${effects.map((e) => `> ${e}`).join("\n")}` : ""
83
76
  ].filter(Boolean).join("\n\n");
84
77
  }
85
78
  // Annotate the CommonJS export names for ESM import in node:
@@ -0,0 +1,20 @@
1
+ import { GitDiffDetail } from "../format_git_diff_content";
2
+ import { AstNode } from "../ast_util/AstUtil";
3
+ import { DetectReport } from "../report_util";
4
+ export type BlockReportItem = {
5
+ index: number;
6
+ diff_txt: string[];
7
+ addNodeAndPaths: ReturnType<typeof createPathsOfNodes>;
8
+ removeNodeAndPaths: ReturnType<typeof createPathsOfNodes>;
9
+ };
10
+ declare function createPathsOfNodes(ast: AstNode, blockIndex: number): {
11
+ node: AstNode;
12
+ nodePath: string;
13
+ blockIndex: number;
14
+ }[];
15
+ export declare function diffBlockDetect(gitDiffDetail: GitDiffDetail, index: number, extra: {
16
+ reportItem: DetectReport;
17
+ absPathPrefix: string;
18
+ }): void;
19
+ export declare function reportItemDetect(reportItem: DetectReport, absPathPrefix: string): void;
20
+ export {};
@@ -0,0 +1,112 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/util/report_util/diffBlockDetect.ts
30
+ var diffBlockDetect_exports = {};
31
+ __export(diffBlockDetect_exports, {
32
+ diffBlockDetect: () => diffBlockDetect,
33
+ reportItemDetect: () => reportItemDetect
34
+ });
35
+ module.exports = __toCommonJS(diffBlockDetect_exports);
36
+ var import_getAstKitByFilePath = __toESM(require("../ast_util/getAstKitByFilePath"));
37
+ var import_path = require("path");
38
+ var import_constants = require("../constants");
39
+ var import_AstUtil = __toESM(require("../ast_util/AstUtil"));
40
+ var createBlockReport = (index) => ({
41
+ index,
42
+ diff_txt: [],
43
+ addNodeAndPaths: [],
44
+ removeNodeAndPaths: []
45
+ });
46
+ function createPathsOfNodes(ast, blockIndex) {
47
+ return [ast, ...ast._util.nodeCollection].map((node) => {
48
+ return { node, nodePath: import_AstUtil.default.getNodePath(node), blockIndex };
49
+ });
50
+ }
51
+ function findOrCreateBlockReport(blockReports, index) {
52
+ const res = blockReports.find((item) => item.index === index) || createBlockReport(index);
53
+ if (!blockReports.includes(res)) {
54
+ blockReports.push(res);
55
+ }
56
+ return res;
57
+ }
58
+ function diffBlockDetect(gitDiffDetail, index, extra) {
59
+ const { filePath, startLineOfNew, items, startLineOfOld } = gitDiffDetail;
60
+ const { reportItem, absPathPrefix } = extra;
61
+ const { blockReports, _fileRemovedNodesPaths, _fileAddedNodesPaths } = reportItem;
62
+ const blockReportItem = findOrCreateBlockReport(blockReports, index);
63
+ const { mapFileLineToNodeSet, mapUuidToNode } = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
64
+ const filePathOfOld = (0, import_path.join)(process.cwd(), "..", import_constants.SOURCE, filePath);
65
+ const { mapFileLineToNodeSet: mapFileLineToNodeSetOld } = (0, import_getAstKitByFilePath.default)(filePathOfOld, absPathPrefix.replace(`${import_constants.TARGET}/`, `${import_constants.SOURCE}/`));
66
+ const programNode = mapUuidToNode.get("Program");
67
+ if (programNode) {
68
+ const lineNumberStartNew = Number(startLineOfNew);
69
+ const lineNumberEndNew = lineNumberStartNew + items.filter((item) => item.startsWith("+")).length - 1;
70
+ const lineNumberStartOld = Number(startLineOfOld);
71
+ const lineNumberEndOld = lineNumberStartOld + items.filter((item) => item.startsWith("-")).length - 1;
72
+ const addNodes = import_AstUtil.default.getTopScopeNodesByLineNumberRange(mapFileLineToNodeSet, lineNumberStartNew, lineNumberEndNew);
73
+ const removeNodes = import_AstUtil.default.getTopScopeNodesByLineNumberRange(mapFileLineToNodeSetOld, lineNumberStartOld, lineNumberEndOld);
74
+ blockReportItem.diff_txt = items;
75
+ const addNodeAndPaths = addNodes.map((e) => createPathsOfNodes(e, index)).flat();
76
+ const removeNodeAndPaths = removeNodes.map((e) => createPathsOfNodes(e, index)).flat();
77
+ blockReportItem.addNodeAndPaths = addNodeAndPaths;
78
+ blockReportItem.removeNodeAndPaths = removeNodeAndPaths;
79
+ _fileAddedNodesPaths.push(...addNodeAndPaths);
80
+ _fileRemovedNodesPaths.push(...removeNodeAndPaths);
81
+ }
82
+ }
83
+ function reportItemDetect(reportItem, absPathPrefix) {
84
+ const { _fileRemovedNodesPaths, _fileAddedNodesPaths, filePath } = reportItem;
85
+ const filePathOfOld = (0, import_path.join)(process.cwd(), "..", import_constants.SOURCE, filePath);
86
+ const { mapPathToNodeSet } = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
87
+ const _fileAddedPaths = _fileAddedNodesPaths.map((e) => e.nodePath);
88
+ const _fileRemovedPaths = _fileRemovedNodesPaths.map((e) => e.nodePath);
89
+ const _fileSamePathsNode = _fileAddedPaths.filter((e) => _fileRemovedPaths.includes(e));
90
+ if (_fileSamePathsNode.length) {
91
+ reportItem._fileAddedNodesPaths = [...new Set(_fileAddedNodesPaths)].filter((e) => !_fileSamePathsNode.includes(e.nodePath));
92
+ reportItem._fileRemovedNodesPaths = [...new Set(_fileRemovedNodesPaths)].filter((e) => !_fileSamePathsNode.includes(e.nodePath));
93
+ const { blockReports, dangerIdentifiers } = reportItem;
94
+ blockReports.forEach((e) => {
95
+ e.addNodeAndPaths = e.addNodeAndPaths.filter((item) => !_fileSamePathsNode.includes(item.nodePath));
96
+ e.removeNodeAndPaths = e.removeNodeAndPaths.filter((item) => !_fileSamePathsNode.includes(item.nodePath));
97
+ const effectedNodeOfRemove = e.removeNodeAndPaths.map((item) => [...item.node._util.effectIds]).flat();
98
+ effectedNodeOfRemove.forEach((item) => {
99
+ const path = import_AstUtil.default.getNodePath(item);
100
+ const nodes = mapPathToNodeSet.get(path);
101
+ if (nodes) {
102
+ dangerIdentifiers.push(...[...nodes].map((e2) => import_AstUtil.default.getShortNodeMsg(e2)));
103
+ }
104
+ });
105
+ });
106
+ }
107
+ }
108
+ // Annotate the CommonJS export names for ESM import in node:
109
+ 0 && (module.exports = {
110
+ diffBlockDetect,
111
+ reportItemDetect
112
+ });
@@ -1 +1,2 @@
1
+ export declare function extractUndefinedIdentifiers(filePath: string, absPathPrefix: string): string[];
1
2
  export declare function fileIdentifierDetect(filePath: string, absPathPrefix: string): string[];
@@ -29,34 +29,33 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/util/report_util/file_identifier_detect.ts
30
30
  var file_identifier_detect_exports = {};
31
31
  __export(file_identifier_detect_exports, {
32
+ extractUndefinedIdentifiers: () => extractUndefinedIdentifiers,
32
33
  fileIdentifierDetect: () => fileIdentifierDetect
33
34
  });
34
35
  module.exports = __toCommonJS(file_identifier_detect_exports);
35
36
  var import_getAstKitByFilePath = __toESM(require("../ast_util/getAstKitByFilePath"));
36
37
  var import_AstUtil = __toESM(require("../ast_util/AstUtil"));
37
- function fileIdentifierDetect(filePath, absPathPrefix) {
38
+ function extractUndefinedIdentifiers(filePath, absPathPrefix) {
38
39
  const { mapUuidToNode } = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
39
40
  const programNode = mapUuidToNode.get("Program");
40
41
  if (!programNode) {
41
42
  return [];
42
43
  }
43
44
  const { dependenceIds } = programNode._util;
44
- const ids = [...dependenceIds].filter((id) => {
45
- return import_AstUtil.default.isUntrackedId(id) || id._util.crossScope.size > 0;
46
- });
47
- return ids.map((id) => {
48
- const { name, _util } = id;
49
- const { crossScope } = _util;
50
- const isUntracked = import_AstUtil.default.isUntrackedId(id);
51
- const notFoundInfo = isUntracked ? `${name}:「${_util.startLine}:${_util.startColumn},${_util.endLine}:${_util.endColumn}」` : "";
52
- const dangerScopeInfo = [...crossScope].map((scope) => {
53
- const { _util: _util2 } = scope;
54
- return `${scope.name}:「${_util2.startLine}:${_util2.startColumn},${_util2.endLine}:${_util2.endColumn}」`;
55
- }).join(",");
56
- return [notFoundInfo, dangerScopeInfo].filter(Boolean).join(",");
57
- });
45
+ const ids = [...dependenceIds].filter((id) => import_AstUtil.default.isUntrackedId(id));
46
+ return ids.map((id) => import_AstUtil.default.getShortNodeMsg(id));
47
+ }
48
+ function fileIdentifierDetect(filePath, absPathPrefix) {
49
+ const { mapUuidToNode } = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
50
+ const programNode = mapUuidToNode.get("Program");
51
+ if (!programNode) {
52
+ return [];
53
+ }
54
+ const { effectIds } = programNode._util;
55
+ return [...effectIds].map((id) => import_AstUtil.default.getShortNodeMsg(id));
58
56
  }
59
57
  // Annotate the CommonJS export names for ESM import in node:
60
58
  0 && (module.exports = {
59
+ extractUndefinedIdentifiers,
61
60
  fileIdentifierDetect
62
61
  });
@@ -1,11 +1,23 @@
1
1
  import { GitDiffDetail } from "./format_git_diff_content";
2
- import { BlockReport } from "./report_util/code_block_detect";
2
+ import { AstNode } from "./ast_util/AstUtil";
3
+ import { BlockReportItem } from "./report_util/diffBlockDetect";
3
4
  export type DetectReport = {
4
5
  filePath: string;
5
6
  type: "modify" | "add" | "delete";
6
7
  filesDependsOnMe: string[][];
8
+ undefinedIdentifiers: string[];
7
9
  dangerIdentifiers: string[];
8
- blockReports: BlockReport[];
10
+ _fileAddedNodesPaths: {
11
+ node: AstNode;
12
+ nodePath: string;
13
+ blockIndex: number;
14
+ }[];
15
+ _fileRemovedNodesPaths: {
16
+ node: AstNode;
17
+ nodePath: string;
18
+ blockIndex: number;
19
+ }[];
20
+ blockReports: BlockReportItem[];
9
21
  };
10
22
  type Arg = {
11
23
  groupGitDiffLines: GitDiffDetail[];
@@ -16,25 +28,14 @@ export declare function createDetectReport(arg: Arg): {
16
28
  blockReports: {
17
29
  diff_txt: string[];
18
30
  infos: {
19
- addedEffects: {
20
- causeBy: string;
21
- effects: string[];
22
- }[];
23
- removedEffects: {
24
- causeBy: string;
25
- effects: (string | undefined)[];
26
- }[];
27
- kind: "Import" | "Declaration" | "Assignment" | "SelfUpdate" | "Invoke" | "Other";
28
- added: string[];
29
- addedNotUsed: string[];
30
- addedNotFound: string[];
31
- removed: string[];
32
- removedStillUsing: string[];
31
+ causeBy: string;
32
+ effects: string[];
33
33
  }[];
34
34
  }[];
35
- filePath: string;
36
- type: "modify" | "add" | "delete";
35
+ type: "delete" | "modify" | "add";
37
36
  filesDependsOnMe: string[][];
37
+ undefinedIdentifiers: string[];
38
38
  dangerIdentifiers: string[];
39
+ filePath: string;
39
40
  }[];
40
41
  export {};
@@ -32,11 +32,10 @@ __export(report_util_exports, {
32
32
  createDetectReport: () => createDetectReport
33
33
  });
34
34
  module.exports = __toCommonJS(report_util_exports);
35
- var import_code_block_detect = __toESM(require("./report_util/code_block_detect"));
36
- var import_getAstKitByFilePath = __toESM(require("./ast_util/getAstKitByFilePath"));
37
35
  var import_AstUtil = __toESM(require("./ast_util/AstUtil"));
38
36
  var import_file_identifier_detect = require("./report_util/file_identifier_detect");
39
37
  var import_getFileDepends = __toESM(require("./report_util/getFileDepends"));
38
+ var import_diffBlockDetect = require("./report_util/diffBlockDetect");
40
39
  function createDetectReport(arg) {
41
40
  const { groupGitDiffLines, tree, absPathPrefix } = arg;
42
41
  const reports = [];
@@ -49,56 +48,44 @@ function createDetectReport(arg) {
49
48
  filePath,
50
49
  type,
51
50
  filesDependsOnMe,
51
+ undefinedIdentifiers: [],
52
52
  dangerIdentifiers: [],
53
+ _fileAddedNodesPaths: [],
54
+ _fileRemovedNodesPaths: [],
53
55
  blockReports: []
54
56
  };
55
57
  reports.push(reportItem);
56
58
  }
59
+ reportItem.undefinedIdentifiers = (0, import_file_identifier_detect.extractUndefinedIdentifiers)(filePath, absPathPrefix);
57
60
  reportItem.dangerIdentifiers = (0, import_file_identifier_detect.fileIdentifierDetect)(filePath, absPathPrefix);
58
61
  if (type === "modify") {
59
- (0, import_code_block_detect.default)({ gitDiffItem: item, absPathPrefix, blockReports: reportItem.blockReports, index });
62
+ (0, import_diffBlockDetect.diffBlockDetect)(item, index, { reportItem, absPathPrefix });
60
63
  }
61
64
  });
62
- return reports.map((report) => {
63
- const filePath = report.filePath;
64
- const astKit = (0, import_getAstKitByFilePath.default)(filePath, absPathPrefix);
65
- const allNodes = new Map([...astKit.mapUuidToNode.values()].map((ele) => [import_AstUtil.default.getNodePath(ele), ele]));
65
+ return reports.map((reportItem) => {
66
+ const { _fileAddedNodesPaths, _fileRemovedNodesPaths, filePath, blockReports, ...reportProperties } = reportItem;
67
+ (0, import_diffBlockDetect.reportItemDetect)(reportItem, absPathPrefix);
68
+ const fileAddedNodesPaths = reportItem._fileAddedNodesPaths.map((item) => item.nodePath);
69
+ const fileRemovedNodesPaths = reportItem._fileRemovedNodesPaths.map((item) => item.nodePath);
66
70
  return {
67
- ...report,
68
- blockReports: report.blockReports.map((blockReport) => {
69
- const { infos, diff_txt } = blockReport;
70
- const infosList = infos.map((info) => {
71
- const { addedEffects, removedEffects, topAdded, topRemoved, ...rest } = info;
72
- const removedEffectsInfos = removedEffects.map((item) => {
73
- const tmpList = item.effects.map((ele) => {
74
- const nodePath = import_AstUtil.default.getNodePath(ele);
75
- const item2 = allNodes.get(nodePath);
76
- return item2 && import_AstUtil.default.createScopeContent(item2);
77
- }).filter(Boolean);
78
- const effects = [...new Set(tmpList)];
79
- return {
80
- causeBy: item.causeBy.name || item.causeBy.type,
81
- effects
82
- };
83
- }).filter((item) => item.effects.length > 0);
84
- const addedEffectsInfos = addedEffects.map((item) => {
85
- const effects = [...new Set(item.effects.map(import_AstUtil.default.createScopeContent))];
86
- return {
87
- causeBy: item.causeBy.name || item.causeBy.type,
88
- effects
89
- };
90
- }).filter((item) => item.effects.length > 0);
71
+ filePath,
72
+ ...reportProperties,
73
+ blockReports: blockReports.map((blockReport) => {
74
+ const { diff_txt } = blockReport;
75
+ const addNodeAndPaths = blockReport.addNodeAndPaths.filter((e) => fileAddedNodesPaths.includes(e.nodePath));
76
+ const infosList = addNodeAndPaths.map((item) => {
77
+ const { node } = item;
78
+ const { effectIds } = node._util;
91
79
  return {
92
- ...rest,
93
- addedEffects: addedEffectsInfos,
94
- removedEffects: removedEffectsInfos
80
+ causeBy: import_AstUtil.default.getShortNodeMsg(node),
81
+ effects: [...effectIds].map((e) => import_AstUtil.default.getShortNodeMsg(e))
95
82
  };
96
83
  });
97
84
  return {
98
85
  diff_txt,
99
- infos: infosList
86
+ infos: infosList.filter((e) => e.effects.length > 0)
100
87
  };
101
- })
88
+ }).filter((e) => e.infos.length > 0)
102
89
  };
103
90
  });
104
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-code-detector",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/cjs/index.d.ts",
@@ -37,10 +37,12 @@
37
37
  "dependencies": {
38
38
  "@babel/parser": "^7.28.3",
39
39
  "@umijs/utils": "^4.4.12",
40
+ "await-to-js": "^3.0.0",
40
41
  "crypto-js": "^4.2.0",
41
42
  "dayjs": "^1.11.13",
42
43
  "lodash-es": "^4.17.21",
43
44
  "madge": "^8.0.0",
45
+ "tsx": "^4.20.5",
44
46
  "vue-eslint-parser": "^10.2.0"
45
47
  }
46
48
  }