Skip to content

Commit 429878e

Browse files
committed
helper script
1 parent 76d82e1 commit 429878e

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

devops/tsc/index.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import ts from 'typescript';
2+
import path from 'node:path';
3+
import fs from 'node:fs/promises';
4+
5+
const tsconfigPath = './tsconfig.json';
6+
7+
const cwd = process.cwd();
8+
9+
async function fixOverride() {
10+
const configFile = path.isAbsolute(tsconfigPath)
11+
? tsconfigPath
12+
: ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath);
13+
14+
if (!configFile) {
15+
console.error('No tsconfig file found for path:', tsconfigPath);
16+
process.exit(1);
17+
}
18+
19+
const config = ts.readConfigFile(configFile, ts.sys.readFile);
20+
21+
const { options, fileNames } = ts.parseJsonConfigFileContent(
22+
config.config,
23+
ts.sys,
24+
25+
// Resolve to the folder where the tsconfig file located
26+
path.dirname(tsconfigPath),
27+
);
28+
29+
const program = ts.createProgram({
30+
rootNames: fileNames,
31+
options,
32+
});
33+
34+
if (fileNames.length === 0) {
35+
console.error('No files in the project.', {
36+
fileNames,
37+
options,
38+
});
39+
40+
process.exit(1);
41+
}
42+
let emitResult = program.emit();
43+
44+
const overrideErrors = ts
45+
.getPreEmitDiagnostics(program)
46+
.concat(emitResult.diagnostics)
47+
.filter((diagnostic) =>
48+
[
49+
// This member must have an 'override' modifier because it overrides a member in the base class '{0}'.
50+
4114,
51+
// This parameter property must have an 'override' modifier because it overrides a member in base class '{0}'
52+
4115,
53+
// This member must have an 'override' modifier because it overrides an abstract method that is declared in the base class '{0}'.
54+
4116,
55+
].includes(diagnostic.code),
56+
);
57+
58+
const sortedErrors = sortErrors(overrideErrors);
59+
60+
for (const diagnostic of sortedErrors) {
61+
await addOverride(diagnostic);
62+
}
63+
}
64+
65+
/**
66+
*
67+
* @param {ts.Diagnostic} diagnostic
68+
* @returns {Promise<void>}
69+
*/
70+
async function addOverride(diagnostic) {
71+
const fileContent = (await fs.readFile(diagnostic.file.fileName, 'utf-8')).toString();
72+
let startIndex = diagnostic.start;
73+
74+
if (fileContent.slice(0, startIndex).endsWith(' get ')) {
75+
startIndex -= 'get '.length;
76+
}
77+
if (fileContent.slice(0, startIndex).endsWith(' async ')) {
78+
startIndex -= 'async '.length;
79+
}
80+
if (fileContent.slice(0, startIndex).endsWith(' readonly ')) {
81+
startIndex -= 'readonly '.length;
82+
}
83+
84+
const newFileContent = [fileContent.slice(0, startIndex), 'override ', fileContent.slice(startIndex)].join('');
85+
await fs.writeFile(diagnostic.file.fileName, newFileContent);
86+
}
87+
88+
/**
89+
*
90+
* @param {ts.Diagnostic[]} errors
91+
* @returns {ts.Diagnostic[]}
92+
*/
93+
function sortErrors(errors) {
94+
// Sort by file path and start position from end to start
95+
// so we can insert override keyword without changing the start position of other errors in the same file that happen before
96+
return errors.slice(0).sort((a, b) => {
97+
if (a.file && b.file) {
98+
if (a.file.fileName === b.file.fileName) {
99+
return b.start - a.start;
100+
}
101+
102+
return a.file.fileName.localeCompare(b.file.fileName);
103+
}
104+
105+
return 0;
106+
});
107+
}
108+
109+
fixOverride();

0 commit comments

Comments
 (0)