Adds a CodeAction provider to support fixits (#40)

Adds a CodeAction provider to support fixits
pull/2748/head
Alexandru Dima 5 years ago committed by GitHub
commit c050127710
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -163,13 +163,16 @@ export class DiagnosticsAdapter extends Adapter {
return null;
}
const promises: Promise<ts.Diagnostic[]>[] = [];
const { noSyntaxValidation, noSemanticValidation } = this._defaults.getDiagnosticsOptions();
const { noSyntaxValidation, noSemanticValidation, noSuggestionDiagnostics } = this._defaults.getDiagnosticsOptions();
if (!noSyntaxValidation) {
promises.push(worker.getSyntacticDiagnostics(resource.toString()));
}
if (!noSemanticValidation) {
promises.push(worker.getSemanticDiagnostics(resource.toString()));
}
if (!noSuggestionDiagnostics) {
promises.push(worker.getSuggestionDiagnostics(resource.toString()));
}
return Promise.all(promises);
}).then(diagnostics => {
if (!diagnostics || !monaco.editor.getModel(resource)) {
@ -191,14 +194,24 @@ export class DiagnosticsAdapter extends Adapter {
const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(resource, diag.start + diag.length);
return {
severity: monaco.MarkerSeverity.Error,
severity: this._tsDiagnosticCategoryToMarkerSeverity(diag.category),
startLineNumber,
startColumn,
endLineNumber,
endColumn,
message: flattenDiagnosticMessageText(diag.messageText, '\n')
message: flattenDiagnosticMessageText(diag.messageText, '\n'),
code: diag.code.toString()
};
}
private _tsDiagnosticCategoryToMarkerSeverity(category: ts.DiagnosticCategory): monaco.MarkerSeverity {
switch (category) {
case ts.DiagnosticCategory.Error: return monaco.MarkerSeverity.Error
case ts.DiagnosticCategory.Message: return monaco.MarkerSeverity.Info
case ts.DiagnosticCategory.Warning: return monaco.MarkerSeverity.Warning
case ts.DiagnosticCategory.Suggestion: return monaco.MarkerSeverity.Hint
}
}
}
// --- suggest ------
@ -356,7 +369,7 @@ export class SignatureHelpAdapter extends Adapter implements monaco.languages.Si
return {
value: ret,
dispose() {}
dispose() { }
};
});
}
@ -632,6 +645,58 @@ export class FormatOnTypeAdapter extends FormatHelper implements monaco.language
}
}
// --- code actions ------
export class CodeActionAdaptor extends FormatHelper implements monaco.languages.CodeActionProvider {
public provideCodeActions(model: monaco.editor.ITextModel, range: Range, context: monaco.languages.CodeActionContext, token: CancellationToken): Promise<monaco.languages.CodeActionList> {
const resource = model.uri;
return this._worker(resource).then(worker => {
const start = this._positionToOffset(resource, { lineNumber: range.startLineNumber, column: range.startColumn });
const end = this._positionToOffset(resource, { lineNumber: range.endLineNumber, column: range.endColumn });
const formatOptions = FormatHelper._convertOptions(model.getOptions());
const errorCodes = context.markers.filter(m => m.code).map(m => m.code).map(Number);
return worker.getCodeFixesAtPosition(resource.toString(), start, end, errorCodes, formatOptions);
}).then(codeFixes => {
return codeFixes.filter(fix => {
// Removes any 'make a new file'-type code fix
return fix.changes.filter(change => change.isNewFile).length === 0;
}).map(fix => {
return this._tsCodeFixActionToMonacoCodeAction(model, context, fix);
})
}).then(result => {
return {
actions: result,
dispose: () => { }
};
});
}
private _tsCodeFixActionToMonacoCodeAction(model: monaco.editor.ITextModel, context: monaco.languages.CodeActionContext, codeFix: ts.CodeFixAction): monaco.languages.CodeAction {
const edits: monaco.languages.ResourceTextEdit[] = codeFix.changes.map(edit => ({
resource: model.uri,
edits: edit.textChanges.map(tc => ({
range: this._textSpanToRange(model.uri, tc.span),
text: tc.newText
}))
}));
const action: monaco.languages.CodeAction = {
title: codeFix.description,
edit: { edits: edits },
diagnostics: context.markers,
kind: "quickfix"
};
return action;
}
}
// --- rename ----
export class RenameAdapter extends Adapter implements monaco.languages.RenameProvider {
@ -675,4 +740,4 @@ export class RenameAdapter extends Adapter implements monaco.languages.RenamePro
return { edits };
}
}
}

1
src/monaco.d.ts vendored

@ -128,6 +128,7 @@ declare module monaco.languages.typescript {
export interface DiagnosticsOptions {
noSemanticValidation?: boolean;
noSyntaxValidation?: boolean;
noSuggestionDiagnostics?: boolean;
}
export interface LanguageServiceDefaults {

@ -64,6 +64,7 @@ function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (firs
monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker));
monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker));
monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker));
monaco.languages.registerCodeActionProvider(modeId, new languageFeatures.CodeActionAdaptor(worker));
monaco.languages.registerRenameProvider(modeId, new languageFeatures.RenameAdapter(worker));
new languageFeatures.DiagnosticsAdapter(defaults, modeId, worker);

@ -146,6 +146,12 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
return Promise.resolve(diagnostics);
}
getSuggestionDiagnostics(fileName: string): Promise<ts.DiagnosticWithLocation[]> {
const diagnostics = this._languageService.getSuggestionDiagnostics(fileName);
TypeScriptWorker.clearFiles(diagnostics);
return Promise.resolve(diagnostics);
}
getCompilerOptionsDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
TypeScriptWorker.clearFiles(diagnostics);
@ -208,6 +214,11 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
return Promise.resolve(this._languageService.getEmitOutput(fileName));
}
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: number[], formatOptions: ts.FormatCodeOptions): Promise<ReadonlyArray<ts.CodeFixAction>> {
const preferences = {}
return Promise.resolve(this._languageService.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences));
}
updateExtraLibs(extraLibs: IExtraLibs) {
this._extraLibs = extraLibs;
}

@ -160,10 +160,8 @@
'}',
'',
'var game = new Conway.GameOfLife();',
].join('\n')
].join('\n');
}
require([
'vs/basic-languages/monaco.contribution',
'vs/language/typescript/monaco.contribution'

Loading…
Cancel
Save