@alexgorbatchev/typescript-ai-policy 1.0.2 → 1.0.3
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/README.md +39 -37
- package/package.json +1 -1
- package/src/oxlint/createOxlintConfig.ts +1 -0
- package/src/oxlint/plugin.ts +2 -0
- package/src/oxlint/rules/no-i-prefixed-type-aliases.ts +45 -0
- package/src/oxlint/rules/require-template-indent.ts +46 -9
- package/src/oxlint/rules/testid-naming-convention.ts +1 -1
- package/src/semantic-fixes/applyFileChanges.ts +6 -6
- package/src/semantic-fixes/applySemanticFixes.ts +29 -26
- package/src/semantic-fixes/applyTextEdits.ts +20 -20
- package/src/semantic-fixes/backends/tsgo-lsp/TsgoLspClient.ts +49 -49
- package/src/semantic-fixes/backends/tsgo-lsp/createTsgoLspSemanticFixBackend.ts +41 -41
- package/src/semantic-fixes/providers/createInterfaceNamingConventionSemanticFixProvider.ts +15 -89
- package/src/semantic-fixes/providers/createNoIPrefixedTypeAliasesSemanticFixProvider.ts +49 -0
- package/src/semantic-fixes/providers/createTestFileLocationConventionSemanticFixProvider.ts +9 -19
- package/src/semantic-fixes/providers/helpers.ts +117 -0
- package/src/semantic-fixes/readMovedFileTextEdits.ts +7 -7
- package/src/semantic-fixes/readSemanticFixRuntimePaths.ts +2 -2
- package/src/semantic-fixes/runApplySemanticFixes.ts +5 -5
- package/src/semantic-fixes/runOxlintJson.ts +9 -9
- package/src/semantic-fixes/types.ts +35 -41
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
|
+
import ts from "typescript";
|
|
4
|
+
import type { OxlintDiagnostic, SemanticFixProviderContext, SymbolRenameOperation } from "../types.ts";
|
|
5
|
+
|
|
6
|
+
type NamedDeclarationWithIdentifier = ts.Node & {
|
|
7
|
+
name: ts.Identifier;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type NamedDeclarationMatcher<TDeclaration extends NamedDeclarationWithIdentifier> = (
|
|
11
|
+
node: ts.Node,
|
|
12
|
+
) => node is TDeclaration;
|
|
13
|
+
|
|
14
|
+
export function readAbsoluteDiagnosticFilePath(
|
|
15
|
+
diagnostic: OxlintDiagnostic,
|
|
16
|
+
context: SemanticFixProviderContext,
|
|
17
|
+
): string {
|
|
18
|
+
if (isAbsolute(diagnostic.filename)) {
|
|
19
|
+
return diagnostic.filename;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return resolve(context.targetDirectoryPath, diagnostic.filename);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function readDiagnosticSourceFile(
|
|
26
|
+
diagnostic: OxlintDiagnostic,
|
|
27
|
+
context: SemanticFixProviderContext,
|
|
28
|
+
): ts.SourceFile {
|
|
29
|
+
const filePath = readAbsoluteDiagnosticFilePath(diagnostic, context);
|
|
30
|
+
const content = readFileSync(filePath, "utf8");
|
|
31
|
+
|
|
32
|
+
return ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function readOffsetFromLineAndColumn(sourceFile: ts.SourceFile, line: number, column: number): number | null {
|
|
36
|
+
if (line < 1 || column < 1) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
return ts.getPositionOfLineAndCharacter(sourceFile, line - 1, column - 1);
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function readNamedDeclarationAtOffset<TDeclaration extends NamedDeclarationWithIdentifier>(
|
|
48
|
+
node: ts.Node,
|
|
49
|
+
offset: number,
|
|
50
|
+
isMatchingDeclaration: NamedDeclarationMatcher<TDeclaration>,
|
|
51
|
+
): TDeclaration | null {
|
|
52
|
+
if (isMatchingDeclaration(node)) {
|
|
53
|
+
const declarationNameStart = node.name.getStart();
|
|
54
|
+
const declarationNameEnd = node.name.getEnd();
|
|
55
|
+
if (offset >= declarationNameStart && offset <= declarationNameEnd) {
|
|
56
|
+
return node;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let matchingDeclaration: TDeclaration | null = null;
|
|
61
|
+
|
|
62
|
+
ts.forEachChild(node, (childNode) => {
|
|
63
|
+
if (matchingDeclaration) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
matchingDeclaration = readNamedDeclarationAtOffset(childNode, offset, isMatchingDeclaration);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return matchingDeclaration;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function readNamedDeclarationFromDiagnosticLabel<TDeclaration extends NamedDeclarationWithIdentifier>(
|
|
74
|
+
sourceFile: ts.SourceFile,
|
|
75
|
+
label: OxlintDiagnostic["labels"][number],
|
|
76
|
+
isMatchingDeclaration: NamedDeclarationMatcher<TDeclaration>,
|
|
77
|
+
): TDeclaration | null {
|
|
78
|
+
const declarationAtReportedOffset = readNamedDeclarationAtOffset(
|
|
79
|
+
sourceFile,
|
|
80
|
+
label.span.offset,
|
|
81
|
+
isMatchingDeclaration,
|
|
82
|
+
);
|
|
83
|
+
if (declarationAtReportedOffset) {
|
|
84
|
+
return declarationAtReportedOffset;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const offsetFromLineAndColumn = readOffsetFromLineAndColumn(sourceFile, label.span.line, label.span.column);
|
|
88
|
+
if (offsetFromLineAndColumn === null || offsetFromLineAndColumn === label.span.offset) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return readNamedDeclarationAtOffset(sourceFile, offsetFromLineAndColumn, isMatchingDeclaration);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function readRenameSymbolOperation(
|
|
96
|
+
diagnostic: OxlintDiagnostic,
|
|
97
|
+
sourceFile: ts.SourceFile,
|
|
98
|
+
declarationName: ts.Identifier,
|
|
99
|
+
newName: string,
|
|
100
|
+
): SymbolRenameOperation {
|
|
101
|
+
const filePath = sourceFile.fileName;
|
|
102
|
+
const start = ts.getLineAndCharacterOfPosition(sourceFile, declarationName.getStart());
|
|
103
|
+
const symbolName = declarationName.text;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
filePath,
|
|
107
|
+
id: `${diagnostic.code}:${filePath}:${start.line}:${start.character}:${newName}`,
|
|
108
|
+
kind: "rename-symbol",
|
|
109
|
+
newName,
|
|
110
|
+
position: {
|
|
111
|
+
character: start.character,
|
|
112
|
+
line: start.line,
|
|
113
|
+
},
|
|
114
|
+
ruleCode: diagnostic.code,
|
|
115
|
+
symbolName,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { dirname, relative, resolve } from "node:path";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
3
|
import ts from "typescript";
|
|
4
|
-
import type {
|
|
4
|
+
import type { TextEdit } from "./types.ts";
|
|
5
5
|
|
|
6
6
|
function isRelativeModuleSpecifier(moduleSpecifier: string): boolean {
|
|
7
7
|
return (
|
|
@@ -21,7 +21,7 @@ function readRelativeModuleSpecifier(fromDirectoryPath: string, targetPath: stri
|
|
|
21
21
|
return relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
type
|
|
24
|
+
type ModuleSpecifierEntry = {
|
|
25
25
|
moduleSpecifier: string;
|
|
26
26
|
node: ts.StringLiteralLike;
|
|
27
27
|
};
|
|
@@ -34,7 +34,7 @@ function readImportTypeArgumentLiteral(node: ts.ImportTypeNode): ts.StringLitera
|
|
|
34
34
|
return ts.isStringLiteralLike(node.argument.literal) ? node.argument.literal : null;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
function readModuleSpecifierEntry(node: ts.Node):
|
|
37
|
+
function readModuleSpecifierEntry(node: ts.Node): ModuleSpecifierEntry | null {
|
|
38
38
|
if (ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) {
|
|
39
39
|
return node.moduleSpecifier && ts.isStringLiteralLike(node.moduleSpecifier)
|
|
40
40
|
? {
|
|
@@ -88,8 +88,8 @@ function readModuleSpecifierEntry(node: ts.Node): IModuleSpecifierEntry | null {
|
|
|
88
88
|
return null;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function readModuleSpecifierEntries(sourceFile: ts.SourceFile): readonly
|
|
92
|
-
const moduleSpecifierEntries:
|
|
91
|
+
function readModuleSpecifierEntries(sourceFile: ts.SourceFile): readonly ModuleSpecifierEntry[] {
|
|
92
|
+
const moduleSpecifierEntries: ModuleSpecifierEntry[] = [];
|
|
93
93
|
|
|
94
94
|
function visitNode(node: ts.Node): void {
|
|
95
95
|
const moduleSpecifierEntry = readModuleSpecifierEntry(node);
|
|
@@ -105,12 +105,12 @@ function readModuleSpecifierEntries(sourceFile: ts.SourceFile): readonly IModule
|
|
|
105
105
|
return moduleSpecifierEntries;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
export function readMovedFileTextEdits(sourceFilePath: string, destinationFilePath: string): readonly
|
|
108
|
+
export function readMovedFileTextEdits(sourceFilePath: string, destinationFilePath: string): readonly TextEdit[] {
|
|
109
109
|
const content = readFileSync(sourceFilePath, "utf8");
|
|
110
110
|
const sourceFile = ts.createSourceFile(sourceFilePath, content, ts.ScriptTarget.Latest, true);
|
|
111
111
|
const sourceDirectoryPath = dirname(sourceFilePath);
|
|
112
112
|
const destinationDirectoryPath = dirname(destinationFilePath);
|
|
113
|
-
const textEdits:
|
|
113
|
+
const textEdits: TextEdit[] = [];
|
|
114
114
|
|
|
115
115
|
for (const moduleSpecifierEntry of readModuleSpecifierEntries(sourceFile)) {
|
|
116
116
|
if (!isRelativeModuleSpecifier(moduleSpecifierEntry.moduleSpecifier)) {
|
|
@@ -2,7 +2,7 @@ import { createRequire } from "node:module";
|
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type SemanticFixRuntimePaths = {
|
|
6
6
|
oxlintConfigPath: string;
|
|
7
7
|
oxlintExecutablePath: string;
|
|
8
8
|
tsgoExecutablePath: string;
|
|
@@ -20,7 +20,7 @@ function readInstalledPackageRootPath(packageName: string, resolutionFailureMess
|
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export function readSemanticFixRuntimePaths():
|
|
23
|
+
export function readSemanticFixRuntimePaths(): SemanticFixRuntimePaths {
|
|
24
24
|
const oxlintPackageRootPath = readInstalledPackageRootPath(
|
|
25
25
|
"oxlint",
|
|
26
26
|
'Missing peer dependency "oxlint". Install oxlint in the consuming project so the semantic-fix CLI can run repository policy checks.',
|
|
@@ -4,9 +4,9 @@ import { existsSync, statSync } from "node:fs";
|
|
|
4
4
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
5
5
|
import { applySemanticFixes } from "./applySemanticFixes.ts";
|
|
6
6
|
import { readSemanticFixRuntimePaths } from "./readSemanticFixRuntimePaths.ts";
|
|
7
|
-
import type {
|
|
7
|
+
import type { ApplySemanticFixesProgressEvent, SkippedDiagnostic } from "./types.ts";
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type CliOptions = {
|
|
10
10
|
dryRun: boolean;
|
|
11
11
|
targetDirectoryPath: string;
|
|
12
12
|
};
|
|
@@ -26,7 +26,7 @@ function readUsageText(): string {
|
|
|
26
26
|
].join("\n");
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
function readCliOptions(argv: readonly string[]):
|
|
29
|
+
function readCliOptions(argv: readonly string[]): CliOptions {
|
|
30
30
|
const remainingArguments = argv.slice(2);
|
|
31
31
|
const targetDirectoryArgument = remainingArguments.find((argument) => !argument.startsWith("-"));
|
|
32
32
|
if (!targetDirectoryArgument) {
|
|
@@ -54,11 +54,11 @@ function readDisplayPath(targetDirectoryPath: string, filePath: string): string
|
|
|
54
54
|
return relativeFilePath.length > 0 ? relativeFilePath : ".";
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function formatSkippedDiagnostic(targetDirectoryPath: string, skippedDiagnostic:
|
|
57
|
+
function formatSkippedDiagnostic(targetDirectoryPath: string, skippedDiagnostic: SkippedDiagnostic): string {
|
|
58
58
|
return `- [${skippedDiagnostic.ruleCode}] ${readDisplayPath(targetDirectoryPath, skippedDiagnostic.filePath)}: ${skippedDiagnostic.reason}`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
function formatProgressEvent(event:
|
|
61
|
+
function formatProgressEvent(event: ApplySemanticFixesProgressEvent): string {
|
|
62
62
|
switch (event.kind) {
|
|
63
63
|
case "running-oxlint": {
|
|
64
64
|
return "running oxlint...";
|
|
@@ -3,20 +3,20 @@ import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
-
import type {
|
|
6
|
+
import type { OxlintDiagnostic } from "./types.ts";
|
|
7
7
|
|
|
8
|
-
type
|
|
8
|
+
type RunOxlintJsonOptions = {
|
|
9
9
|
oxlintConfigPath: string;
|
|
10
10
|
oxlintExecutablePath: string;
|
|
11
11
|
targetDirectoryPath: string;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
type
|
|
14
|
+
type OxlintProcessCompletion = {
|
|
15
15
|
exitCode: number | null;
|
|
16
16
|
signal: NodeJS.Signals | null;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
type
|
|
19
|
+
type OxlintProcessResult = OxlintProcessCompletion & {
|
|
20
20
|
stderr: string;
|
|
21
21
|
stdout: string;
|
|
22
22
|
};
|
|
@@ -25,7 +25,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
|
|
25
25
|
return typeof value === "object" && value !== null;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function isOxlintDiagnostic(value: unknown): value is
|
|
28
|
+
function isOxlintDiagnostic(value: unknown): value is OxlintDiagnostic {
|
|
29
29
|
if (!isRecord(value)) {
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
@@ -49,7 +49,7 @@ function readNormalizedRuleCode(ruleCode: string): string {
|
|
|
49
49
|
return `${pluginName}/${localRuleName}`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function readDiagnostics(report: unknown): readonly
|
|
52
|
+
function readDiagnostics(report: unknown): readonly OxlintDiagnostic[] {
|
|
53
53
|
if (!isRecord(report) || !Array.isArray(report.diagnostics)) {
|
|
54
54
|
throw new Error(`Unexpected Oxlint JSON output: ${JSON.stringify(report)}`);
|
|
55
55
|
}
|
|
@@ -65,7 +65,7 @@ function readDiagnostics(report: unknown): readonly IOxlintDiagnostic[] {
|
|
|
65
65
|
}));
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async function runOxlintProcess(options:
|
|
68
|
+
async function runOxlintProcess(options: RunOxlintJsonOptions): Promise<OxlintProcessResult> {
|
|
69
69
|
const tempDirectoryPath = await mkdtemp(join(tmpdir(), "semantic-fixes-oxlint-"));
|
|
70
70
|
const stdoutPath = join(tempDirectoryPath, "oxlint-report.json");
|
|
71
71
|
const stdoutFileDescriptor = openSync(stdoutPath, "w");
|
|
@@ -96,7 +96,7 @@ async function runOxlintProcess(options: IRunOxlintJsonOptions): Promise<IOxlint
|
|
|
96
96
|
stderrChunks.push(chunk.toString("utf8"));
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
const processCompletion = await new Promise<
|
|
99
|
+
const processCompletion = await new Promise<OxlintProcessCompletion>((resolve, reject) => {
|
|
100
100
|
childProcess.once("error", (error: Error) => {
|
|
101
101
|
reject(error);
|
|
102
102
|
});
|
|
@@ -118,7 +118,7 @@ async function runOxlintProcess(options: IRunOxlintJsonOptions): Promise<IOxlint
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
export async function runOxlintJson(options:
|
|
121
|
+
export async function runOxlintJson(options: RunOxlintJsonOptions): Promise<readonly OxlintDiagnostic[]> {
|
|
122
122
|
const runResult = await runOxlintProcess(options);
|
|
123
123
|
const stdout = runResult.stdout.trim();
|
|
124
124
|
if (stdout.length === 0) {
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type OxlintSpan = {
|
|
2
2
|
column: number;
|
|
3
3
|
length: number;
|
|
4
4
|
line: number;
|
|
5
5
|
offset: number;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type OxlintLabel = {
|
|
9
9
|
label?: string;
|
|
10
|
-
span:
|
|
10
|
+
span: OxlintSpan;
|
|
11
11
|
};
|
|
12
12
|
|
|
13
|
-
export type
|
|
13
|
+
export type OxlintDiagnostic = {
|
|
14
14
|
code: string;
|
|
15
15
|
filename: string;
|
|
16
|
-
labels: readonly
|
|
16
|
+
labels: readonly OxlintLabel[];
|
|
17
17
|
message: string;
|
|
18
18
|
severity: string;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
export type
|
|
22
|
-
diagnostics: readonly
|
|
21
|
+
export type OxlintJsonReport = {
|
|
22
|
+
diagnostics: readonly OxlintDiagnostic[];
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
export type
|
|
25
|
+
export type LineAndCharacter = {
|
|
26
26
|
character: number;
|
|
27
27
|
line: number;
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
export type
|
|
31
|
-
end:
|
|
30
|
+
export type TextEdit = {
|
|
31
|
+
end: LineAndCharacter;
|
|
32
32
|
filePath: string;
|
|
33
33
|
newText: string;
|
|
34
|
-
start:
|
|
34
|
+
start: LineAndCharacter;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
export type
|
|
37
|
+
export type SymbolRenameOperation = {
|
|
38
38
|
filePath: string;
|
|
39
39
|
id: string;
|
|
40
40
|
kind: "rename-symbol";
|
|
41
41
|
newName: string;
|
|
42
|
-
position:
|
|
42
|
+
position: LineAndCharacter;
|
|
43
43
|
ruleCode: string;
|
|
44
44
|
symbolName: string;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
export type
|
|
47
|
+
export type MoveFileOperation = {
|
|
48
48
|
filePath: string;
|
|
49
49
|
id: string;
|
|
50
50
|
kind: "move-file";
|
|
@@ -52,59 +52,53 @@ export type IMoveFileOperation = {
|
|
|
52
52
|
ruleCode: string;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
export type
|
|
55
|
+
export type SemanticFixOperation = SymbolRenameOperation | MoveFileOperation;
|
|
56
56
|
|
|
57
|
-
export type
|
|
57
|
+
export type FileMove = {
|
|
58
58
|
destinationFilePath: string;
|
|
59
59
|
sourceFilePath: string;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
-
export type
|
|
62
|
+
export type SemanticFixPlan = {
|
|
63
63
|
description: string;
|
|
64
|
-
fileMoves: readonly
|
|
64
|
+
fileMoves: readonly FileMove[];
|
|
65
65
|
operationId: string;
|
|
66
66
|
ruleCode: string;
|
|
67
|
-
textEdits: readonly
|
|
67
|
+
textEdits: readonly TextEdit[];
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
export type
|
|
70
|
+
export type SemanticFixPlanSuccess = {
|
|
71
71
|
kind: "plan";
|
|
72
|
-
plan:
|
|
72
|
+
plan: SemanticFixPlan;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
export type
|
|
75
|
+
export type SemanticFixPlanSkip = {
|
|
76
76
|
kind: "skip";
|
|
77
77
|
reason: string;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
export type
|
|
80
|
+
export type SemanticFixPlanResult = SemanticFixPlanSkip | SemanticFixPlanSuccess;
|
|
81
81
|
|
|
82
|
-
export type
|
|
82
|
+
export type SemanticFixProviderContext = {
|
|
83
83
|
targetDirectoryPath: string;
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
-
export type
|
|
87
|
-
createOperation: (
|
|
88
|
-
diagnostic: IOxlintDiagnostic,
|
|
89
|
-
context: ISemanticFixProviderContext,
|
|
90
|
-
) => ISemanticFixOperation | null;
|
|
86
|
+
export type SemanticFixProvider = {
|
|
87
|
+
createOperation: (diagnostic: OxlintDiagnostic, context: SemanticFixProviderContext) => SemanticFixOperation | null;
|
|
91
88
|
ruleCode: string;
|
|
92
89
|
};
|
|
93
90
|
|
|
94
|
-
export type
|
|
91
|
+
export type SemanticFixBackendContext = {
|
|
95
92
|
targetDirectoryPath: string;
|
|
96
93
|
};
|
|
97
94
|
|
|
98
|
-
export type
|
|
99
|
-
createPlan: (
|
|
100
|
-
operation: ISemanticFixOperation,
|
|
101
|
-
context: ISemanticFixBackendContext,
|
|
102
|
-
) => Promise<ISemanticFixPlanResult>;
|
|
95
|
+
export type SemanticFixBackend = {
|
|
96
|
+
createPlan: (operation: SemanticFixOperation, context: SemanticFixBackendContext) => Promise<SemanticFixPlanResult>;
|
|
103
97
|
dispose: () => Promise<void>;
|
|
104
98
|
name: string;
|
|
105
99
|
};
|
|
106
100
|
|
|
107
|
-
export type
|
|
101
|
+
export type ApplySemanticFixesProgressEvent =
|
|
108
102
|
| {
|
|
109
103
|
kind: "running-oxlint";
|
|
110
104
|
targetDirectoryPath: string;
|
|
@@ -139,25 +133,25 @@ export type IApplySemanticFixesProgressEvent =
|
|
|
139
133
|
skippedDiagnosticCount: number;
|
|
140
134
|
};
|
|
141
135
|
|
|
142
|
-
export type
|
|
136
|
+
export type ApplySemanticFixesOptions = {
|
|
143
137
|
dryRun?: boolean;
|
|
144
|
-
onProgress?: (event:
|
|
138
|
+
onProgress?: (event: ApplySemanticFixesProgressEvent) => void;
|
|
145
139
|
oxlintConfigPath: string;
|
|
146
140
|
oxlintExecutablePath: string;
|
|
147
141
|
targetDirectoryPath: string;
|
|
148
142
|
tsgoExecutablePath: string;
|
|
149
143
|
};
|
|
150
144
|
|
|
151
|
-
export type
|
|
145
|
+
export type SkippedDiagnostic = {
|
|
152
146
|
filePath: string;
|
|
153
147
|
reason: string;
|
|
154
148
|
ruleCode: string;
|
|
155
149
|
};
|
|
156
150
|
|
|
157
|
-
export type
|
|
151
|
+
export type ApplySemanticFixesResult = {
|
|
158
152
|
appliedFileCount: number;
|
|
159
153
|
backendName: string;
|
|
160
154
|
changedFilePaths: readonly string[];
|
|
161
155
|
plannedFixCount: number;
|
|
162
|
-
skippedDiagnostics: readonly
|
|
156
|
+
skippedDiagnostics: readonly SkippedDiagnostic[];
|
|
163
157
|
};
|