diff --git a/.vscode/settings.json b/.vscode/settings.json index 82e2867..101bf9d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,14 +1,15 @@ // Place your settings in this file to overwrite default and user settings. { "files.exclude": { - "out": false // set this to true to hide the "out" folder with the compiled JS files + "out": true // set this to true to hide the "out" folder with the compiled JS files }, "search.exclude": { "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off", "cSpell.words": [ - "autofix" + "autofix", + "execa" ] -} \ No newline at end of file +} diff --git a/src/extension.ts b/src/extension.ts index 508440a..6ad7270 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,165 +1,190 @@ import * as vscode from 'vscode'; import * as execa from "execa"; import * as path from "path"; export function activate(context: vscode.ExtensionContext) { const collection = vscode.languages.createDiagnosticCollection('arc lint'); setupCustomTranslators(); function d(disposable: vscode.Disposable) { context.subscriptions.push(disposable); } d(vscode.commands.registerCommand('arc-vscode.clearLint', () => collection.clear())); d(vscode.workspace.onDidSaveTextDocument(onTextDocumentEvent)); d(vscode.workspace.onDidOpenTextDocument(onTextDocumentEvent)); if (vscode.window.activeTextEditor) { lintFile(vscode.window.activeTextEditor.document); } d(vscode.window.onDidChangeActiveTextEditor(editor => { if (editor) { lintFile(editor.document); } })); function onTextDocumentEvent(document: vscode.TextDocument) { lintFile(document); } function lintFile(document: vscode.TextDocument) { if (document.uri.scheme != "file") return; function handleExecResult(value: execa.ExecaReturnValue) { - //! this function throws and then we ignore if the lint actually broke. - if (!value.stdout) - return; - - const lintMessages = JSON.parse(value.stdout); - - for (const filename in lintMessages) { - // TODO: This only probably works because we call arc with a single file. - collection.set(document.uri, lintJsonToDiagnostics(lintMessages[filename])); + if (!value.stdout) return; + try { + const lintMessages = JSON.parse(value.stdout); + + for (const filename in lintMessages) { + // TODO: This only probably works because we call arc with a single file. + collection.set(document.uri, lintJsonToDiagnostics(lintMessages[filename])); + } + } catch { + logError("ppfff"); } } const filename = document.uri.path; execa( 'arc', ['lint', '--output', 'json', '--', path.basename(filename)], { cwd: path.dirname(filename) }, ).then(handleExecResult, handleExecResult); } } export function deactivate() { } function logError(x: any) { console.log("this is error", x); } type LintTranslator = (lint: any) => vscode.Diagnostic; let customLintTranslator: Map = new Map(); function lintJsonToDiagnostics(lintResults: Array): vscode.Diagnostic[] { /* input: Array of: { "line": 248, "char": 23, "code": "SPELL1", "severity": "warning", "name": "Possible Spelling Mistake", "description": "Possible spelling error. You wrote 'seperator', but did you mean 'separator'?", "original": "Seperator", "replacement": "Separator", "granularity": 1, "locations": [], "bypassChangedLineFiltering": null, "context": " magic = COLOR_RED;\n break;\n case 30:\n // printf(\"Record Seperator\");\n magic = COLOR_BLUE;\n break;\n case 31:" } output: array of: { code: '', message: 'cannot assign twice to immutable variable `x`', range: new vscode.Range(new vscode.Position(3, 4), new vscode.Position(3, 10)), severity: vscode.DiagnosticSeverity.Error, source: '', relatedInformation: [ new vscode.DiagnosticRelatedInformation(new vscode.Location(document.uri, new vscode.Range(new vscode.Position(1, 8), new vscode.Position(1, 9))), 'first assignment to `x`') ] } */ /* Extra features: - quick-fix to apply patch - try to get better message by parsing `description` field (per message code...) - `locations` may be parsed into `relatedInformation`. */ function translate(lint: any): vscode.Diagnostic { let t = customLintTranslator.get(lint.code) || defaultTranslate; return t(lint); } return lintResults.map(translate); } function nonNeg(n: number): number { - if (n < 0) return 0 - return n + return n < 0 ? 0 : n } function defaultTranslate(lint: any): vscode.Diagnostic { return { code: lint.code, message: message(lint), severity: severity(lint), source: 'arc lint', range: new vscode.Range( lint.line - 1, nonNeg(lint.char - 2), // it's an artificial 3-chars wide thing. lint.line - 1, lint.char + 1), }; } function message(lint: any) { if (lint.description) return lint.name + ": " + lint.description return lint.name } function severity(lint: any): vscode.DiagnosticSeverity { switch (lint.severity as string) { case 'disabled': return vscode.DiagnosticSeverity.Hint; case 'autofix': return vscode.DiagnosticSeverity.Hint; case 'advice': return vscode.DiagnosticSeverity.Information; case 'warning': return vscode.DiagnosticSeverity.Warning; case 'error': return vscode.DiagnosticSeverity.Error; default: return vscode.DiagnosticSeverity.Error; } } function setupCustomTranslators() { - customLintTranslator.set("SPELL1", - lint => { - let d = defaultTranslate(lint) - - d.message = lint.description; - let len = (lint.original).length; - if (len > 0) { - d.range = new vscode.Range( - lint.line - 1, nonNeg(lint.char - 1), - lint.line - 1, lint.char + len - 1); - } + customLintTranslator.set("SPELL1", lint => { + let d = defaultTranslate(lint) + + d.message = lint.description; + let len = (lint.original).length; + if (len > 0) { + d.range = new vscode.Range( + lint.line - 1, nonNeg(lint.char - 1), + lint.line - 1, lint.char + len - 1); + } + + return d + }); + + // "This line is 116 characters long, but the convention is 80 characters." + const re_TXT3_length = /\D(\d+) characters\.$/; - return d + customLintTranslator.set('E501', lint => { + let d = defaultTranslate(lint) + + d.range = new vscode.Range( + lint.line - 1, lint.char - 1, + lint.line - 1, 1e9); + + return d; + }); + + customLintTranslator.set('TXT3', lint => { + let d = defaultTranslate(lint) + + let match = lint.description.match(re_TXT3_length); + if (match) { + let len = parseInt(match[1]); + d.range = new vscode.Range( + lint.line - 1, len, + lint.line - 1, 1e9); } - ); + + return d; + }); }