diff --git a/README.md b/README.md index c22b0d7..438d4a1 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ It is published in the Visual Studio Marketplace [here](https://marketplace.visu ## Releases +### v0.5.0 +- Added Code Actions to automatically suppress typechecker errors via HH_FIXME comments. + ### v0.4.0 - Fixed document symbol outline (⇧⌘O) break in newer hh_client versions. - Added a new setting to enable type coverage checking (now off by default). diff --git a/package.json b/package.json index 14531bb..4278b1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vscode-hack", - "version": "0.4.0", + "version": "0.5.0", "publisher": "pranayagarwal", "engines": { "vscode": "^1.5.0" diff --git a/src/main.ts b/src/main.ts index 0630afb..babb5e2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,7 @@ import * as vscode from 'vscode'; import { HackCoverageChecker } from './coveragechecker'; import * as providers from './providers'; import * as hh_client from './proxy'; +import * as suppressions from './suppressions'; import { HackTypeChecker } from './typechecker'; export async function activate(context: vscode.ExtensionContext) { @@ -35,6 +36,10 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.languages.registerDocumentFormattingEditProvider(HACK_MODE, new providers.HackDocumentFormattingEditProvider())); context.subscriptions.push(vscode.languages.registerReferenceProvider(HACK_MODE, new providers.HackReferenceProvider())); context.subscriptions.push(vscode.languages.registerDefinitionProvider(HACK_MODE, new providers.HackDefinitionProvider())); + context.subscriptions.push(vscode.languages.registerCodeActionsProvider(HACK_MODE, new providers.HackCodeActionProvider())); + + // add command to add an error suppression comment + context.subscriptions.push(vscode.commands.registerCommand('hack.suppressError', suppressions.suppressError)); // create typechecker and run when workspace is first loaded and on every file save const hhvmTypeDiag: vscode.DiagnosticCollection = vscode.languages.createDiagnosticCollection('hack_typecheck'); diff --git a/src/providers.ts b/src/providers.ts index a428369..ed6b983 100644 --- a/src/providers.ts +++ b/src/providers.ts @@ -228,3 +228,30 @@ export class HackDefinitionProvider implements vscode.DefinitionProvider { return definition; } } + +export class HackCodeActionProvider implements vscode.CodeActionProvider { + public async provideCodeActions(document: vscode.TextDocument, range: vscode.Range, context: vscode.CodeActionContext, token: vscode.CancellationToken): + Promise { + const filteredErrors = context.diagnostics.filter(d => d.source === 'Hack' && d.code !== 0); + if (filteredErrors.length === 0) { + return; + } + const commands = []; + for (const error of filteredErrors) { + commands.push({ + title: 'Suppress: ' + error.code, + command: 'hack.suppressError', + arguments: [document, error.range.start.line, [ error.code ]] + }); + } + if (commands.length > 1) { + const allCodes = filteredErrors.map(f => f.code); + commands.push({ + title: 'Suppress All', + command: 'hack.suppressError', + arguments: [document, filteredErrors[0].range.start.line, allCodes] + }); + } + return commands; + } +} diff --git a/src/suppressions.ts b/src/suppressions.ts new file mode 100644 index 0000000..4f272f6 --- /dev/null +++ b/src/suppressions.ts @@ -0,0 +1,16 @@ +/** + * @file Function triggered from 'hack.suppressError' command to add a suppress error comment before the given line. + */ + +import * as vscode from 'vscode'; + +export function suppressError(document: vscode.TextDocument, line: number, errorCodes: number[]) { + const edit = new vscode.WorkspaceEdit(); + const fullLine = document.lineAt(line); + const prefixIndex = fullLine.firstNonWhitespaceCharacterIndex; + const prefix = fullLine.text.substr(0, prefixIndex); + errorCodes.forEach(code => { + edit.insert(document.uri, new vscode.Position(line, 0), prefix + '/* HH_FIXME[' + code + '] */\n'); + }); + return vscode.workspace.applyEdit(edit); +} diff --git a/src/typechecker.ts b/src/typechecker.ts index d3f5b68..099e0b8 100644 --- a/src/typechecker.ts +++ b/src/typechecker.ts @@ -22,7 +22,11 @@ export class HackTypeChecker { const diagnosticMap: Map = new Map(); typecheckResult.errors.forEach(error => { let fullMessage = ''; + let code: number = 0; error.message.forEach(messageUnit => { + if (code === 0) { + code = messageUnit.code; + } fullMessage = fullMessage + messageUnit.descr + ' [' + messageUnit.code + ']' + '\n'; }); const diagnostic = new vscode.Diagnostic( @@ -31,6 +35,7 @@ export class HackTypeChecker { new vscode.Position(error.message[0].line - 1, error.message[0].end)), fullMessage, vscode.DiagnosticSeverity.Error); + diagnostic.code = code; diagnostic.source = 'Hack'; const file = error.message[0].path; if (diagnosticMap.has(file)) { diff --git a/tslint.json b/tslint.json index d4ba409..182fc1b 100644 --- a/tslint.json +++ b/tslint.json @@ -86,7 +86,7 @@ "chai-vague-errors": true, "class-name": true, "comment-format": true, - "export-name": true, + "export-name": false, "function-name": true, "import-name": true, "interface-name": true,