mirror of
https://github.com/microsoft/monaco-editor.git
synced 2025-12-22 17:25:39 +01:00
Adds a CodeAction provider to support fixits
This commit is contained in:
parent
2389ae38aa
commit
b8063f957f
5 changed files with 87 additions and 5 deletions
|
|
@ -160,13 +160,16 @@ export class DiagnostcsAdapter extends Adapter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const promises: Promise<ts.Diagnostic[]>[] = [];
|
const promises: Promise<ts.Diagnostic[]>[] = [];
|
||||||
const { noSyntaxValidation, noSemanticValidation } = this._defaults.getDiagnosticsOptions();
|
const { noSyntaxValidation, noSemanticValidation, noSuggestionDiagnostics } = this._defaults.getDiagnosticsOptions();
|
||||||
if (!noSyntaxValidation) {
|
if (!noSyntaxValidation) {
|
||||||
promises.push(worker.getSyntacticDiagnostics(resource.toString()));
|
promises.push(worker.getSyntacticDiagnostics(resource.toString()));
|
||||||
}
|
}
|
||||||
if (!noSemanticValidation) {
|
if (!noSemanticValidation) {
|
||||||
promises.push(worker.getSemanticDiagnostics(resource.toString()));
|
promises.push(worker.getSemanticDiagnostics(resource.toString()));
|
||||||
}
|
}
|
||||||
|
if (!noSuggestionDiagnostics) {
|
||||||
|
promises.push(worker.getSuggestionDiagnostics(resource.toString()));
|
||||||
|
}
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}).then(diagnostics => {
|
}).then(diagnostics => {
|
||||||
if (!diagnostics || !monaco.editor.getModel(resource)) {
|
if (!diagnostics || !monaco.editor.getModel(resource)) {
|
||||||
|
|
@ -188,14 +191,24 @@ export class DiagnostcsAdapter extends Adapter {
|
||||||
const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(resource, diag.start + diag.length);
|
const { lineNumber: endLineNumber, column: endColumn } = this._offsetToPosition(resource, diag.start + diag.length);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
severity: monaco.MarkerSeverity.Error,
|
severity: this._tsDiagnosticCategoryToMarkerSeverity(diag.category),
|
||||||
startLineNumber,
|
startLineNumber,
|
||||||
startColumn,
|
startColumn,
|
||||||
endLineNumber,
|
endLineNumber,
|
||||||
endColumn,
|
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 ------
|
// --- suggest ------
|
||||||
|
|
@ -626,3 +639,57 @@ 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.Command | monaco.languages.CodeAction)[]> {
|
||||||
|
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 });
|
||||||
|
|
||||||
|
// TODO: where to get the current formatting options from?
|
||||||
|
const formatOptions = FormatHelper._convertOptions({insertSpaces: true, tabSize: 2});
|
||||||
|
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);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,
|
||||||
|
command: {
|
||||||
|
id: codeFix.fixName,
|
||||||
|
title: codeFix.description,
|
||||||
|
tooltip: codeFix.description
|
||||||
|
},
|
||||||
|
kind: codeFix.fixName
|
||||||
|
};
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
1
src/monaco.d.ts
vendored
1
src/monaco.d.ts
vendored
|
|
@ -125,6 +125,7 @@ declare module monaco.languages.typescript {
|
||||||
export interface DiagnosticsOptions {
|
export interface DiagnosticsOptions {
|
||||||
noSemanticValidation?: boolean;
|
noSemanticValidation?: boolean;
|
||||||
noSyntaxValidation?: boolean;
|
noSyntaxValidation?: boolean;
|
||||||
|
noSuggestionDiagnostics ?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LanguageServiceDefaults {
|
export interface LanguageServiceDefaults {
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,8 @@ function setupMode(defaults: LanguageServiceDefaultsImpl, modeId: string): (firs
|
||||||
monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker));
|
monaco.languages.registerDocumentSymbolProvider(modeId, new languageFeatures.OutlineAdapter(worker));
|
||||||
monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker));
|
monaco.languages.registerDocumentRangeFormattingEditProvider(modeId, new languageFeatures.FormatAdapter(worker));
|
||||||
monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker));
|
monaco.languages.registerOnTypeFormattingEditProvider(modeId, new languageFeatures.FormatOnTypeAdapter(worker));
|
||||||
|
monaco.languages.registerCodeActionProvider(modeId, new languageFeatures.CodeActionAdaptor(worker));
|
||||||
|
|
||||||
new languageFeatures.DiagnostcsAdapter(defaults, modeId, worker);
|
new languageFeatures.DiagnostcsAdapter(defaults, modeId, worker);
|
||||||
|
|
||||||
return worker;
|
return worker;
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,12 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
|
||||||
return Promise.resolve(diagnostics);
|
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[]> {
|
getCompilerOptionsDiagnostics(fileName: string): Promise<ts.Diagnostic[]> {
|
||||||
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
|
const diagnostics = this._languageService.getCompilerOptionsDiagnostics();
|
||||||
TypeScriptWorker.clearFiles(diagnostics);
|
TypeScriptWorker.clearFiles(diagnostics);
|
||||||
|
|
@ -200,6 +206,11 @@ export class TypeScriptWorker implements ts.LanguageServiceHost {
|
||||||
return Promise.resolve(this._languageService.getEmitOutput(fileName));
|
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) {
|
updateExtraLibs(extraLibs: IExtraLibs) {
|
||||||
this._extraLibs = extraLibs;
|
this._extraLibs = extraLibs;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,10 +165,11 @@
|
||||||
'var game = new Conway.GameOfLife();',
|
'var game = new Conway.GameOfLife();',
|
||||||
|
|
||||||
].join('\n'),
|
].join('\n'),
|
||||||
language: 'typescript'
|
language: 'typescript',
|
||||||
|
lightbulb: { enabled: true }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue