scancscode 1.0.31 → 1.0.34
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/.trae/specs/fix-doc-comment-boundary/checklist.md +7 -0
- package/.trae/specs/fix-doc-comment-boundary/spec.md +52 -0
- package/.trae/specs/fix-doc-comment-boundary/tasks.md +34 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/checklist.md +7 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/spec.md +55 -0
- package/.trae/specs/fix-interpolated-string-nested-literals/tasks.md +25 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/checklist.md +9 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/spec.md +59 -0
- package/.trae/specs/fix-remaining-interpolated-string-index/tasks.md +41 -0
- package/.trae/specs/fix-return-interpolated-string/checklist.md +8 -0
- package/.trae/specs/fix-return-interpolated-string/spec.md +60 -0
- package/.trae/specs/fix-return-interpolated-string/tasks.md +39 -0
- package/.trae/specs/handle-anonymous-function-strings/checklist.md +11 -0
- package/.trae/specs/handle-anonymous-function-strings/spec.md +137 -0
- package/.trae/specs/handle-anonymous-function-strings/tasks.md +65 -0
- package/.trae/specs/handle-interpolated-string-double-braces/checklist.md +9 -0
- package/.trae/specs/handle-interpolated-string-double-braces/spec.md +61 -0
- package/.trae/specs/handle-interpolated-string-double-braces/tasks.md +41 -0
- package/.trae/specs/handle-return-statement/checklist.md +11 -0
- package/.trae/specs/handle-return-statement/spec.md +76 -0
- package/.trae/specs/handle-return-statement/tasks.md +44 -0
- package/.trae/specs/handle-special-string-characters/checklist.md +13 -0
- package/.trae/specs/handle-special-string-characters/spec.md +94 -0
- package/.trae/specs/handle-special-string-characters/tasks.md +74 -0
- package/.trae/specs/unify-return-statement-string-extraction/checklist.md +10 -0
- package/.trae/specs/unify-return-statement-string-extraction/spec.md +70 -0
- package/.trae/specs/unify-return-statement-string-extraction/tasks.md +54 -0
- package/bin/scanliterals.js +3 -3
- package/bin/slimlangs.js +3 -3
- package/dist/debug-arg.js +30 -0
- package/dist/debug-args.js +34 -0
- package/dist/debug-comment-5.js +25 -0
- package/dist/debug-comment-strings.js +24 -0
- package/dist/debug-full.js +14 -0
- package/dist/debug-template-issue.js +33 -0
- package/dist/debug-test-5.js +23 -0
- package/dist/debug-test.js +21 -0
- package/dist/debug.js +15 -0
- package/dist/simple-debug.js +27 -0
- package/dist/simple-test.js +61 -0
- package/dist/src/CSharpStringExtractor.js +1791 -358
- package/dist/src/CmdExecutor.js +6 -8
- package/dist/temp-original-source.js +1 -0
- package/dist/test/CSharpStringExtractor.test.js +1587 -207
- package/dist/test-logic.js +79 -0
- package/dist/test-regex.js +13 -0
- package/docs/CSharpStringExtractor/344/273/243/347/240/201/347/224/237/346/210/220/346/217/220/347/244/272/350/257/215.txt +73 -0
- package/jest.config.js +9 -9
- package/package.json +1 -1
- package/src/CSCodeScanner.ts +305 -305
- package/src/CSVUtils.ts +181 -181
- package/src/CSharpStringExtractor.ts +2058 -479
- package/src/CmdExecutor.ts +107 -106
- package/src/LiteralCollector.ts +143 -143
- package/src/RunConvert.ts +3 -3
- package/src/RunSlimLangs.ts +3 -3
- package/src/TableScanner.ts +92 -92
- package/test/CSharpStringExtractor.test.ts +1673 -208
- package/test/KeeperDialog.cs +114 -0
- package/test/TestSpecialString.cs +24 -0
- package/tsconfig.json +109 -109
package/src/CSVUtils.ts
CHANGED
|
@@ -1,181 +1,181 @@
|
|
|
1
|
-
import * as csv from "fast-csv";
|
|
2
|
-
import * as fs from "fs";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export class CSVUtils {
|
|
6
|
-
filePath: string;
|
|
7
|
-
constructor(filePath: string) {
|
|
8
|
-
this.filePath = filePath;
|
|
9
|
-
}
|
|
10
|
-
async parseCsv() {
|
|
11
|
-
if (fs.existsSync(this.filePath)) {
|
|
12
|
-
let stream = csv.parseFile(this.filePath, {
|
|
13
|
-
delimiter: ",",
|
|
14
|
-
});
|
|
15
|
-
let rows: string[][] = await stream.toArray();
|
|
16
|
-
stream.destroy();
|
|
17
|
-
return rows;
|
|
18
|
-
} else {
|
|
19
|
-
console.error(`文件不存在: ${this.filePath}`);
|
|
20
|
-
return []
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
getShortKey(content: string) {
|
|
24
|
-
// let max = 16
|
|
25
|
-
// if (content.length < max) {
|
|
26
|
-
// return content
|
|
27
|
-
// } else {
|
|
28
|
-
// return content.substring(0, max)
|
|
29
|
-
// }
|
|
30
|
-
return content;
|
|
31
|
-
}
|
|
32
|
-
tryGetEntry(content: string, map01: Map<string, string[]>, map02: Map<string, string[]>): [boolean, string, string[] | undefined] {
|
|
33
|
-
if (map02.has(content)) {
|
|
34
|
-
let row2 = map02.get(content)!;
|
|
35
|
-
return [row2 != null, content, row2];
|
|
36
|
-
}
|
|
37
|
-
let shortKey = this.getShortKey(content);
|
|
38
|
-
if (map01.has(shortKey)) {
|
|
39
|
-
let row1 = map01.get(shortKey)!;
|
|
40
|
-
if (row1 != null && (row1[0] == shortKey || row1[1] == content)) {
|
|
41
|
-
return [true, shortKey, row1];
|
|
42
|
-
} else {
|
|
43
|
-
return [false, shortKey, undefined];
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return [false, shortKey, undefined];
|
|
47
|
-
}
|
|
48
|
-
merge(rows0: string[][], rows1: string[], langs: string[]) {
|
|
49
|
-
// 短key
|
|
50
|
-
let map01: Map<string, string[]> = new Map();
|
|
51
|
-
// 全文key
|
|
52
|
-
let map02: Map<string, string[]> = new Map();
|
|
53
|
-
if (rows0 != null) {
|
|
54
|
-
for (let index = 1; index < rows0.length; index++) {
|
|
55
|
-
const row = rows0[index];
|
|
56
|
-
let key = row[0];
|
|
57
|
-
map01.set(key, row);
|
|
58
|
-
}
|
|
59
|
-
for (let index = 1; index < rows0.length; index++) {
|
|
60
|
-
const row = rows0[index];
|
|
61
|
-
let key = row[1];
|
|
62
|
-
if (key != null && key != "") {
|
|
63
|
-
map02.set(key, row);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let rows2: string[][] = [];
|
|
69
|
-
if (rows0 != null && rows0.length > 0) {
|
|
70
|
-
// rows2.push(rows0[0]);
|
|
71
|
-
// 合并 langs 中没有的语言列
|
|
72
|
-
let headers = [...rows0[0]];
|
|
73
|
-
for (const lang of langs) {
|
|
74
|
-
if (!headers.includes(lang)) {
|
|
75
|
-
headers.push(lang);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
rows2.push(headers);
|
|
79
|
-
} else {
|
|
80
|
-
rows2.push(["key", ...langs]);
|
|
81
|
-
}
|
|
82
|
-
for (let index = 0; index < rows1.length; index++) {
|
|
83
|
-
const content = rows1[index];
|
|
84
|
-
let [exist, key, row] = this.tryGetEntry(content, map01, map02);
|
|
85
|
-
if (exist) {
|
|
86
|
-
if (row != null) {
|
|
87
|
-
rows2.push(row);
|
|
88
|
-
} else {
|
|
89
|
-
if (key != content) {
|
|
90
|
-
rows2.push([key, content]);
|
|
91
|
-
} else {
|
|
92
|
-
rows2.push([content, '']);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
} else {
|
|
96
|
-
if (key != content) {
|
|
97
|
-
rows2.push([key, content]);
|
|
98
|
-
} else {
|
|
99
|
-
rows2.push([content, '']);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return rows2;
|
|
104
|
-
}
|
|
105
|
-
static async writeCsv(filePath: string, rows: string[][]) {
|
|
106
|
-
let str = await csv.writeToString(rows);
|
|
107
|
-
fs.writeFileSync(filePath, str, "utf-8");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
static async updateToFile(filePath: string, literals: string[], langs: string[]) {
|
|
111
|
-
let csvUtils = new CSVUtils(filePath);
|
|
112
|
-
let rows0 = await csvUtils.parseCsv();
|
|
113
|
-
|
|
114
|
-
// 优化:使用Set去重,减少重复处理
|
|
115
|
-
const uniqueLiterals = [...new Set(literals)];
|
|
116
|
-
|
|
117
|
-
let rows2 = csvUtils.merge(rows0, uniqueLiterals, langs);
|
|
118
|
-
await CSVUtils.writeCsv(filePath, rows2);
|
|
119
|
-
console.log(`已经更新多语言表: ${filePath} , 共有 ${rows2.length - 1} 条目`);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 表格第一列为 key + 语言列表, 按照 langs 精简表格列, 只保留指定key列和指定语言列
|
|
124
|
-
* @param filePath csv文件路径
|
|
125
|
-
* @param outFilePath 输出csv文件路径
|
|
126
|
-
* @param langs 指定要保留的语言列表
|
|
127
|
-
*/
|
|
128
|
-
static async slimCsvWithLangs(filePaths: string[], outFilePath: string, langs: string[]) {
|
|
129
|
-
let rows2: string[][] = [];
|
|
130
|
-
let keySpace: Set<string> = new Set();
|
|
131
|
-
let conflictKeySpace: Set<string> = new Set();
|
|
132
|
-
let existAnyInput = false;
|
|
133
|
-
for (const filePath of filePaths) {
|
|
134
|
-
if (fs.existsSync(filePath) == false) {
|
|
135
|
-
console.warn(`文件不存在: ${filePath}`);
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
existAnyInput = true;
|
|
139
|
-
let csvUtils = new CSVUtils(filePath);
|
|
140
|
-
let rows0 = await csvUtils.parseCsv();
|
|
141
|
-
let header = rows0[0];
|
|
142
|
-
if (rows2.length == 0) {
|
|
143
|
-
rows2.push([header[0], ...langs]);
|
|
144
|
-
}
|
|
145
|
-
let langIndexes: number[] = [];
|
|
146
|
-
for (const lang of langs) {
|
|
147
|
-
let langIndex = header.indexOf(lang);
|
|
148
|
-
if (langIndex != -1) {
|
|
149
|
-
langIndexes.push(langIndex);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
for (let index = 1; index < rows0.length; index++) {
|
|
153
|
-
const row = rows0[index];
|
|
154
|
-
let newRow: string[] = [];
|
|
155
|
-
let key = row[0];
|
|
156
|
-
if (keySpace.has(key)) {
|
|
157
|
-
conflictKeySpace.add(key);
|
|
158
|
-
} else {
|
|
159
|
-
keySpace.add(key);
|
|
160
|
-
}
|
|
161
|
-
newRow.push(key);
|
|
162
|
-
for (const langIndex of langIndexes) {
|
|
163
|
-
newRow.push(row[langIndex]);
|
|
164
|
-
}
|
|
165
|
-
rows2.push(newRow);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
if (existAnyInput == false) {
|
|
169
|
-
console.warn(`不存在有效文件, 未输出文件:`, filePaths);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
if (rows2.length > 0) {
|
|
173
|
-
await CSVUtils.writeCsv(outFilePath, rows2);
|
|
174
|
-
if (conflictKeySpace.size > 0) {
|
|
175
|
-
console.error(`冲突的key有 ${conflictKeySpace.size} 个:`, conflictKeySpace);
|
|
176
|
-
}
|
|
177
|
-
} else {
|
|
178
|
-
console.warn(`没有生成任何数据,未输出文件。`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
1
|
+
import * as csv from "fast-csv";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export class CSVUtils {
|
|
6
|
+
filePath: string;
|
|
7
|
+
constructor(filePath: string) {
|
|
8
|
+
this.filePath = filePath;
|
|
9
|
+
}
|
|
10
|
+
async parseCsv() {
|
|
11
|
+
if (fs.existsSync(this.filePath)) {
|
|
12
|
+
let stream = csv.parseFile(this.filePath, {
|
|
13
|
+
delimiter: ",",
|
|
14
|
+
});
|
|
15
|
+
let rows: string[][] = await stream.toArray();
|
|
16
|
+
stream.destroy();
|
|
17
|
+
return rows;
|
|
18
|
+
} else {
|
|
19
|
+
console.error(`文件不存在: ${this.filePath}`);
|
|
20
|
+
return []
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
getShortKey(content: string) {
|
|
24
|
+
// let max = 16
|
|
25
|
+
// if (content.length < max) {
|
|
26
|
+
// return content
|
|
27
|
+
// } else {
|
|
28
|
+
// return content.substring(0, max)
|
|
29
|
+
// }
|
|
30
|
+
return content;
|
|
31
|
+
}
|
|
32
|
+
tryGetEntry(content: string, map01: Map<string, string[]>, map02: Map<string, string[]>): [boolean, string, string[] | undefined] {
|
|
33
|
+
if (map02.has(content)) {
|
|
34
|
+
let row2 = map02.get(content)!;
|
|
35
|
+
return [row2 != null, content, row2];
|
|
36
|
+
}
|
|
37
|
+
let shortKey = this.getShortKey(content);
|
|
38
|
+
if (map01.has(shortKey)) {
|
|
39
|
+
let row1 = map01.get(shortKey)!;
|
|
40
|
+
if (row1 != null && (row1[0] == shortKey || row1[1] == content)) {
|
|
41
|
+
return [true, shortKey, row1];
|
|
42
|
+
} else {
|
|
43
|
+
return [false, shortKey, undefined];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return [false, shortKey, undefined];
|
|
47
|
+
}
|
|
48
|
+
merge(rows0: string[][], rows1: string[], langs: string[]) {
|
|
49
|
+
// 短key
|
|
50
|
+
let map01: Map<string, string[]> = new Map();
|
|
51
|
+
// 全文key
|
|
52
|
+
let map02: Map<string, string[]> = new Map();
|
|
53
|
+
if (rows0 != null) {
|
|
54
|
+
for (let index = 1; index < rows0.length; index++) {
|
|
55
|
+
const row = rows0[index];
|
|
56
|
+
let key = row[0];
|
|
57
|
+
map01.set(key, row);
|
|
58
|
+
}
|
|
59
|
+
for (let index = 1; index < rows0.length; index++) {
|
|
60
|
+
const row = rows0[index];
|
|
61
|
+
let key = row[1];
|
|
62
|
+
if (key != null && key != "") {
|
|
63
|
+
map02.set(key, row);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let rows2: string[][] = [];
|
|
69
|
+
if (rows0 != null && rows0.length > 0) {
|
|
70
|
+
// rows2.push(rows0[0]);
|
|
71
|
+
// 合并 langs 中没有的语言列
|
|
72
|
+
let headers = [...rows0[0]];
|
|
73
|
+
for (const lang of langs) {
|
|
74
|
+
if (!headers.includes(lang)) {
|
|
75
|
+
headers.push(lang);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
rows2.push(headers);
|
|
79
|
+
} else {
|
|
80
|
+
rows2.push(["key", ...langs]);
|
|
81
|
+
}
|
|
82
|
+
for (let index = 0; index < rows1.length; index++) {
|
|
83
|
+
const content = rows1[index];
|
|
84
|
+
let [exist, key, row] = this.tryGetEntry(content, map01, map02);
|
|
85
|
+
if (exist) {
|
|
86
|
+
if (row != null) {
|
|
87
|
+
rows2.push(row);
|
|
88
|
+
} else {
|
|
89
|
+
if (key != content) {
|
|
90
|
+
rows2.push([key, content]);
|
|
91
|
+
} else {
|
|
92
|
+
rows2.push([content, '']);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
if (key != content) {
|
|
97
|
+
rows2.push([key, content]);
|
|
98
|
+
} else {
|
|
99
|
+
rows2.push([content, '']);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return rows2;
|
|
104
|
+
}
|
|
105
|
+
static async writeCsv(filePath: string, rows: string[][]) {
|
|
106
|
+
let str = await csv.writeToString(rows);
|
|
107
|
+
fs.writeFileSync(filePath, str, "utf-8");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static async updateToFile(filePath: string, literals: string[], langs: string[]) {
|
|
111
|
+
let csvUtils = new CSVUtils(filePath);
|
|
112
|
+
let rows0 = await csvUtils.parseCsv();
|
|
113
|
+
|
|
114
|
+
// 优化:使用Set去重,减少重复处理
|
|
115
|
+
const uniqueLiterals = [...new Set(literals)];
|
|
116
|
+
|
|
117
|
+
let rows2 = csvUtils.merge(rows0, uniqueLiterals, langs);
|
|
118
|
+
await CSVUtils.writeCsv(filePath, rows2);
|
|
119
|
+
console.log(`已经更新多语言表: ${filePath} , 共有 ${rows2.length - 1} 条目`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 表格第一列为 key + 语言列表, 按照 langs 精简表格列, 只保留指定key列和指定语言列
|
|
124
|
+
* @param filePath csv文件路径
|
|
125
|
+
* @param outFilePath 输出csv文件路径
|
|
126
|
+
* @param langs 指定要保留的语言列表
|
|
127
|
+
*/
|
|
128
|
+
static async slimCsvWithLangs(filePaths: string[], outFilePath: string, langs: string[]) {
|
|
129
|
+
let rows2: string[][] = [];
|
|
130
|
+
let keySpace: Set<string> = new Set();
|
|
131
|
+
let conflictKeySpace: Set<string> = new Set();
|
|
132
|
+
let existAnyInput = false;
|
|
133
|
+
for (const filePath of filePaths) {
|
|
134
|
+
if (fs.existsSync(filePath) == false) {
|
|
135
|
+
console.warn(`文件不存在: ${filePath}`);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
existAnyInput = true;
|
|
139
|
+
let csvUtils = new CSVUtils(filePath);
|
|
140
|
+
let rows0 = await csvUtils.parseCsv();
|
|
141
|
+
let header = rows0[0];
|
|
142
|
+
if (rows2.length == 0) {
|
|
143
|
+
rows2.push([header[0], ...langs]);
|
|
144
|
+
}
|
|
145
|
+
let langIndexes: number[] = [];
|
|
146
|
+
for (const lang of langs) {
|
|
147
|
+
let langIndex = header.indexOf(lang);
|
|
148
|
+
if (langIndex != -1) {
|
|
149
|
+
langIndexes.push(langIndex);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (let index = 1; index < rows0.length; index++) {
|
|
153
|
+
const row = rows0[index];
|
|
154
|
+
let newRow: string[] = [];
|
|
155
|
+
let key = row[0];
|
|
156
|
+
if (keySpace.has(key)) {
|
|
157
|
+
conflictKeySpace.add(key);
|
|
158
|
+
} else {
|
|
159
|
+
keySpace.add(key);
|
|
160
|
+
}
|
|
161
|
+
newRow.push(key);
|
|
162
|
+
for (const langIndex of langIndexes) {
|
|
163
|
+
newRow.push(row[langIndex]);
|
|
164
|
+
}
|
|
165
|
+
rows2.push(newRow);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
if (existAnyInput == false) {
|
|
169
|
+
console.warn(`不存在有效文件, 未输出文件:`, filePaths);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (rows2.length > 0) {
|
|
173
|
+
await CSVUtils.writeCsv(outFilePath, rows2);
|
|
174
|
+
if (conflictKeySpace.size > 0) {
|
|
175
|
+
console.error(`冲突的key有 ${conflictKeySpace.size} 个:`, conflictKeySpace);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
console.warn(`没有生成任何数据,未输出文件。`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|