mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-16 05:58:32 -06:00
* wip: add types * wip * Add cases * Add some case * Add more check * accept baseline * add abstract abd declare method * add override in declaration * accept baseline * add property override * Fix decalre modifier * update baseline * Add more cases * make lint happy * make lint happy * Update description * Add codefix * simplify code * accept baseline * Update desc * Accept baseline * Add override completions * filter out implements field in override context * fix tests * Add parameter property check * Accept baseline * acept baseline * Add parameter property to declaration code action * Add quickfix for override parameter property * fix code style * Add override with interface tests * Add more cases about modifier position * rename flag * rename flags * Added tests. * Accepted baselines. * Always issue errors for unnecessary 'override' modifiers. * Accepted baselines. * Override perf (#4) * try cache check result * pre check for override * Do not issue error if implement abstract * Add abstract-spec check * Avoid override dead lock * Add more case * Add codefix for new error * Fix error message * Add jsdoc override tag (#6) * Override jsdoc tag (#7) * accept baseline * Disallow codefix in js * update baseline * Omit override in d.ts * Add more case in js * Accept baseline * fix override js test * fix crlf * Revert merge conflict changes * Accept baseline * Avoid space * Fix CR issues * Accept baseline * Fix typo and add more check * Fix error name Co-authored-by: Daniel Rosenwasser <Daniel.Rosenwasser@microsoft.com>
104 lines
5.2 KiB
TypeScript
104 lines
5.2 KiB
TypeScript
/* @internal */
|
|
namespace ts.codefix {
|
|
const errorCodeToFixes = createMultiMap<CodeFixRegistration>();
|
|
const fixIdToRegistration = new Map<string, CodeFixRegistration>();
|
|
|
|
export type DiagnosticAndArguments = DiagnosticMessage | [DiagnosticMessage, string] | [DiagnosticMessage, string, string];
|
|
function diagnosticToString(diag: DiagnosticAndArguments): string {
|
|
return isArray(diag)
|
|
? formatStringFromArgs(getLocaleSpecificMessage(diag[0]), diag.slice(1) as readonly string[])
|
|
: getLocaleSpecificMessage(diag);
|
|
}
|
|
|
|
export function createCodeFixActionWithoutFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticAndArguments) {
|
|
return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, /*fixId*/ undefined, /*fixAllDescription*/ undefined);
|
|
}
|
|
|
|
export function createCodeFixAction(fixName: string, changes: FileTextChanges[], description: DiagnosticAndArguments, fixId: {}, fixAllDescription: DiagnosticAndArguments, command?: CodeActionCommand): CodeFixAction {
|
|
return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, diagnosticToString(fixAllDescription), command);
|
|
}
|
|
|
|
export function createCodeFixActionMaybeFixAll(fixName: string, changes: FileTextChanges[], description: DiagnosticAndArguments, fixId?: {}, fixAllDescription?: DiagnosticAndArguments, command?: CodeActionCommand) {
|
|
return createCodeFixActionWorker(fixName, diagnosticToString(description), changes, fixId, fixAllDescription && diagnosticToString(fixAllDescription), command);
|
|
}
|
|
|
|
function createCodeFixActionWorker(fixName: string, description: string, changes: FileTextChanges[], fixId?: {}, fixAllDescription?: string, command?: CodeActionCommand): CodeFixAction {
|
|
return { fixName, description, changes, fixId, fixAllDescription, commands: command ? [command] : undefined };
|
|
}
|
|
|
|
export function registerCodeFix(reg: CodeFixRegistration) {
|
|
for (const error of reg.errorCodes) {
|
|
errorCodeToFixes.add(String(error), reg);
|
|
}
|
|
if (reg.fixIds) {
|
|
for (const fixId of reg.fixIds) {
|
|
Debug.assert(!fixIdToRegistration.has(fixId));
|
|
fixIdToRegistration.set(fixId, reg);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getSupportedErrorCodes(): string[] {
|
|
return arrayFrom(errorCodeToFixes.keys());
|
|
}
|
|
|
|
function removeFixIdIfFixAllUnavailable(registration: CodeFixRegistration, diagnostics: Diagnostic[]) {
|
|
const { errorCodes } = registration;
|
|
let maybeFixableDiagnostics = 0;
|
|
for (const diag of diagnostics) {
|
|
if (contains(errorCodes, diag.code)) maybeFixableDiagnostics++;
|
|
if (maybeFixableDiagnostics > 1) break;
|
|
}
|
|
|
|
const fixAllUnavailable = maybeFixableDiagnostics < 2;
|
|
return ({ fixId, fixAllDescription, ...action }: CodeFixAction): CodeFixAction => {
|
|
return fixAllUnavailable ? action : { ...action, fixId, fixAllDescription };
|
|
};
|
|
}
|
|
|
|
export function getFixes(context: CodeFixContext): readonly CodeFixAction[] {
|
|
const diagnostics = getDiagnostics(context);
|
|
const registrations = errorCodeToFixes.get(String(context.errorCode));
|
|
return flatMap(registrations, f => map(f.getCodeActions(context), removeFixIdIfFixAllUnavailable(f, diagnostics)));
|
|
}
|
|
|
|
export function getAllFixes(context: CodeFixAllContext): CombinedCodeActions {
|
|
// Currently fixId is always a string.
|
|
return fixIdToRegistration.get(cast(context.fixId, isString))!.getAllCodeActions!(context);
|
|
}
|
|
|
|
export function createCombinedCodeActions(changes: FileTextChanges[], commands?: CodeActionCommand[]): CombinedCodeActions {
|
|
return { changes, commands };
|
|
}
|
|
|
|
export function createFileTextChanges(fileName: string, textChanges: TextChange[]): FileTextChanges {
|
|
return { fileName, textChanges };
|
|
}
|
|
|
|
export function codeFixAll(
|
|
context: CodeFixAllContext,
|
|
errorCodes: number[],
|
|
use: (changes: textChanges.ChangeTracker, error: DiagnosticWithLocation, commands: Push<CodeActionCommand>) => void,
|
|
): CombinedCodeActions {
|
|
const commands: CodeActionCommand[] = [];
|
|
const changes = textChanges.ChangeTracker.with(context, t => eachDiagnostic(context, errorCodes, diag => use(t, diag, commands)));
|
|
return createCombinedCodeActions(changes, commands.length === 0 ? undefined : commands);
|
|
}
|
|
|
|
export function eachDiagnostic(context: CodeFixAllContext, errorCodes: readonly number[], cb: (diag: DiagnosticWithLocation) => void): void {
|
|
for (const diag of getDiagnostics(context)) {
|
|
if (contains(errorCodes, diag.code)) {
|
|
cb(diag as DiagnosticWithLocation);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getDiagnostics({ program, sourceFile, cancellationToken }: CodeFixContextBase) {
|
|
return [
|
|
...program.getSemanticDiagnostics(sourceFile, cancellationToken),
|
|
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
|
...computeSuggestionDiagnostics(sourceFile, program, cancellationToken)
|
|
];
|
|
}
|
|
}
|