mirror of
https://github.com/microsoft/vscode-extension-samples.git
synced 2026-04-27 16:55:44 +08:00
diagnostic code action sample
This commit is contained in:
@ -4,11 +4,16 @@ This sample shows how to provide code actions in the the editor. Code actions ar
|
||||
|
||||
The sample uses the [`CodeActionProvider`](https://code.visualstudio.com/api/references/vscode-api#CodeActionProvider) api to implement a simple set of code actions that convert `:)` to a smiley emoji in markdown files:
|
||||
|
||||

|
||||

|
||||
|
||||
Second example of code action provider shows how to associate code actions with diagnostic (e.g. compilation) problems.
|
||||
|
||||

|
||||
|
||||
## VS Code API
|
||||
|
||||
### `vscode` module
|
||||
|
||||
- [`languages.registerCodeActionsProvider`](https://code.visualstudio.com/api/references/vscode-api#languages.registerCodeActionsProvider)
|
||||
- [`Diagnostic.code`](https://code.visualstudio.com/api/references/vscode-api#Diagnostic)
|
||||
- [`CodeActionContext.diagnostics`](https://code.visualstudio.com/api/references/vscode-api#CodeActionContext)
|
||||
|
||||
BIN
code-actions-sample/example_diagnostic.gif
Normal file
BIN
code-actions-sample/example_diagnostic.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 141 KiB |
67
code-actions-sample/src/diagnostics.ts
Normal file
67
code-actions-sample/src/diagnostics.ts
Normal file
@ -0,0 +1,67 @@
|
||||
/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
/** To demonstrate code actions associated with Diagnostics problems, this file provides a mock diagnostics entries. */
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
/** Code that is used to associate diagnostic entries with code actions. */
|
||||
export const EMOJI_MENTION = 'emoji_mention';
|
||||
|
||||
/** String to detect in the text document. */
|
||||
const EMOJI = 'emoji';
|
||||
|
||||
/**
|
||||
* Analyzes the text document for problems.
|
||||
* This demo diagnostic problem provider finds all mentions of 'emoji'.
|
||||
* @param doc text document to analyze
|
||||
* @param emojiDiagnostics diagnostic collection
|
||||
*/
|
||||
export function refreshDiagnostics(doc: vscode.TextDocument, emojiDiagnostics: vscode.DiagnosticCollection): void {
|
||||
let diagnostics: vscode.Diagnostic[] = [];
|
||||
|
||||
for (let lineIndex = 0; lineIndex < doc.lineCount; lineIndex++) {
|
||||
const lineOfText = doc.lineAt(lineIndex);
|
||||
if (lineOfText.text.includes(EMOJI)) {
|
||||
diagnostics.push(createDiagnostic(doc, lineOfText, lineIndex));
|
||||
}
|
||||
}
|
||||
|
||||
emojiDiagnostics.set(doc.uri, diagnostics);
|
||||
}
|
||||
|
||||
function createDiagnostic(doc: vscode.TextDocument, lineOfText: vscode.TextLine, lineIndex: number): vscode.Diagnostic {
|
||||
// find where in the line of thet the 'emoji' is mentioned
|
||||
let index = lineOfText.text.indexOf(EMOJI);
|
||||
|
||||
// create range that represents, where in the document the word is
|
||||
let range = new vscode.Range(lineIndex, index, lineIndex, index + EMOJI.length);
|
||||
|
||||
let diagnostic = new vscode.Diagnostic(range, "When you say 'emoji', do you want to find out more?",
|
||||
vscode.DiagnosticSeverity.Information);
|
||||
diagnostic.code = EMOJI_MENTION;
|
||||
return diagnostic;
|
||||
}
|
||||
|
||||
export function subscribeToDocumentChanges(context: vscode.ExtensionContext, emojiDiagnostics: vscode.DiagnosticCollection): void {
|
||||
if (vscode.window.activeTextEditor) {
|
||||
refreshDiagnostics(vscode.window.activeTextEditor.document, emojiDiagnostics);
|
||||
}
|
||||
context.subscriptions.push(
|
||||
vscode.window.onDidChangeActiveTextEditor(editor => {
|
||||
if (editor) {
|
||||
refreshDiagnostics(editor.document, emojiDiagnostics);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.onDidChangeTextDocument(e => refreshDiagnostics(e.document, emojiDiagnostics))
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.workspace.onDidCloseTextDocument(doc => emojiDiagnostics.delete(doc.uri))
|
||||
);
|
||||
|
||||
}
|
||||
@ -3,12 +3,37 @@
|
||||
*--------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { subscribeToDocumentChanges, EMOJI_MENTION } from './diagnostics';
|
||||
|
||||
const COMMAND = 'code-actions-sample.command';
|
||||
|
||||
var emojiDiagnostics: vscode.DiagnosticCollection;
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(
|
||||
vscode.languages.registerCodeActionsProvider('markdown', new Emojizer(), {
|
||||
providedCodeActionKinds: Emojizer.providedCodeActionKinds
|
||||
}));
|
||||
|
||||
emojiDiagnostics = vscode.languages.createDiagnosticCollection("emoji");
|
||||
|
||||
subscribeToDocumentChanges(context, emojiDiagnostics);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.languages.registerCodeActionsProvider('markdown', new Emojinfo(), {
|
||||
providedCodeActionKinds: Emojinfo.providedCodeActionKinds
|
||||
})
|
||||
);
|
||||
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand(COMMAND, () => vscode.env.openExternal(vscode.Uri.parse('https://unicode.org/emoji/charts-12.0/full-emoji-list.html')))
|
||||
);
|
||||
}
|
||||
|
||||
export function deactivate(context: vscode.ExtensionContext) {
|
||||
if (emojiDiagnostics) {
|
||||
emojiDiagnostics.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,10 +59,13 @@ export class Emojizer implements vscode.CodeActionProvider {
|
||||
|
||||
const replaceWithSmileyHankyFix = this.createFix(document, range, '💩');
|
||||
|
||||
const commandAction = this.createCommand();
|
||||
|
||||
return [
|
||||
replaceWithSmileyCatFix,
|
||||
replaceWithSmileyFix,
|
||||
replaceWithSmileyHankyFix
|
||||
replaceWithSmileyHankyFix,
|
||||
commandAction
|
||||
];
|
||||
}
|
||||
|
||||
@ -53,5 +81,35 @@ export class Emojizer implements vscode.CodeActionProvider {
|
||||
fix.edit.replace(document.uri, new vscode.Range(range.start, range.start.translate(0, 2)), emoji);
|
||||
return fix;
|
||||
}
|
||||
|
||||
private createCommand(): vscode.CodeAction {
|
||||
const action = new vscode.CodeAction('Learn more...', vscode.CodeActionKind.Empty);
|
||||
action.command = { command: COMMAND, title: 'Learn more about emojis', tooltip: 'This will open the unicode emoji page.' };
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides code actions corresponding to diagnostic problems.
|
||||
*/
|
||||
export class Emojinfo implements vscode.CodeActionProvider {
|
||||
|
||||
public static readonly providedCodeActionKinds = [
|
||||
vscode.CodeActionKind.QuickFix
|
||||
];
|
||||
|
||||
provideCodeActions(document: vscode.TextDocument, range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, token: vscode.CancellationToken): vscode.CodeAction[] {
|
||||
// for each diagnostic entry that has the matching `code`, create a code action command
|
||||
return context.diagnostics
|
||||
.filter(diagnostic => diagnostic.code === EMOJI_MENTION)
|
||||
.map(diagnostic => this.createCommandCodeAction(diagnostic));
|
||||
}
|
||||
|
||||
private createCommandCodeAction(diagnostic: vscode.Diagnostic): vscode.CodeAction {
|
||||
const action = new vscode.CodeAction('Learn more...', vscode.CodeActionKind.QuickFix);
|
||||
action.command = { command: COMMAND, title: 'Learn more about emojis', tooltip: 'This will open the unicode emoji page.' };
|
||||
action.diagnostics = [diagnostic];
|
||||
action.isPreferred = true;
|
||||
return action;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user