diff --git a/.arclint b/.arclint index aa4841d..d16feac 100644 --- a/.arclint +++ b/.arclint @@ -1,31 +1,34 @@ { "linters": { "chmod": { "type": "chmod" }, "filename": { "type": "filename" }, "generated": { "type": "generated" }, "eslint": { "type": "eslint", "include": "(\\.ts$)", "bin": "./node_modules/.bin/eslint" }, "merge-conflict": { "type": "merge-conflict" }, "nolint": { "type": "nolint" }, "spelling": { "type": "spelling" }, "text": { "type": "text", - "text.max-line-length": 120 + "text.max-line-length": 120, + "severity": { + "2": "disabled" + } } } } diff --git a/.vscodeignore b/.vscodeignore index 34606f3..710d1c6 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,13 +1,13 @@ .vscode/** .vscode-test/** out/test/** src/** .gitignore vsc-extension-quickstart.md **/tsconfig.json **/.eslintrc.json **/*.map **/*.ts +*.vsix NOTES .arc* - diff --git a/TODO b/TODO index edac1bd..4022e0d 100644 --- a/TODO +++ b/TODO @@ -1,25 +1,26 @@ MVP === - lint everything +- when fixing last issue, it doesn't co away. TODO ==== - lint current file - [v] command clear all issues Long Term Desired Features ========================== - Fancy UIs for - arc patch - arc todo - arc unit - arc browse - arc paste (upload and download) - list open Differential in repo (for review) - get hovercard (content) for any object - push notifications from website ? - preview Remarkup - some magic to help the External Editor Link - arc lint: special-case some messages for better visibility (find more range/information.) - arc lint: support auto-fix (apply diff) - arc lint: `locations` field may be parsed into `relatedInformation`. diff --git a/src/arc_lint.ts b/src/arc_lint.ts index d2ba33a..60aa9d4 100644 --- a/src/arc_lint.ts +++ b/src/arc_lint.ts @@ -1,136 +1,135 @@ import * as vscode from 'vscode'; import * as execa from 'execa'; import * as path from 'path'; import { nonNeg } from './misc'; import { ArcanistLintMessage } from './arcanist_types'; import { setupCustomTranslators } from './arc_lint_translators'; export function setup() { setupCustomTranslators(customLintTranslator); updateLintSeverityMap(); } export function lintFile(document: vscode.TextDocument, errorCollection: vscode.DiagnosticCollection) { - if (document.uri.scheme != "file") return; + if (document.uri.scheme !== "file") { return; } function handleExecResult(value: execa.ExecaReturnValue) { - if (!value.stdout) return; + 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. errorCollection.set(document.uri, lintJsonToDiagnostics(lintMessages[filename])); } } catch { console.log("ppfff"); } } const filename = document.uri.path; execa( 'arc', ['lint', '--output', 'json', '--', path.basename(filename)], { cwd: path.dirname(filename) }, ).then(handleExecResult, handleExecResult); } - /** - input: - ``` - { - "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: - ``` - { - 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`') - ] - } - ``` +/** +input: +``` +{ + "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: +``` +{ + 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`') + ] +} +``` - Possible 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`. - */ +Possible 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`. +*/ export type LintTranslator = (lint: ArcanistLintMessage) => vscode.Diagnostic; let customLintTranslator: Map = new Map(); export function defaultLintTranslator(lint: ArcanistLintMessage): 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: ArcanistLintMessage) { - if (lint.description) - return lint.name + ": " + lint.description - return lint.name + if (lint.description) { return lint.name + ": " + lint.description; } + return lint.name; } let lintSeverityMap: Map; export function updateLintSeverityMap(): void { let config = vscode.workspace.getConfiguration('arc-vscode.lint'); let maxLevel: vscode.DiagnosticSeverity; switch (config.maxDiagnosticsLevel as string) { case 'hint': maxLevel = vscode.DiagnosticSeverity.Hint; break; case 'info': maxLevel = vscode.DiagnosticSeverity.Information; break; case 'warning': maxLevel = vscode.DiagnosticSeverity.Warning; break; case 'error': default: maxLevel = vscode.DiagnosticSeverity.Error; break; } function capped(level: vscode.DiagnosticSeverity): vscode.DiagnosticSeverity { return level > maxLevel ? level : maxLevel; } lintSeverityMap = new Map(); - lintSeverityMap.set('disabled', capped(vscode.DiagnosticSeverity.Hint)) - lintSeverityMap.set('autofix', capped(vscode.DiagnosticSeverity.Information)) - lintSeverityMap.set('advice', capped(vscode.DiagnosticSeverity.Information)) - lintSeverityMap.set('warning', capped(vscode.DiagnosticSeverity.Warning)) - lintSeverityMap.set('error', capped(vscode.DiagnosticSeverity.Error)) + lintSeverityMap.set('disabled', capped(vscode.DiagnosticSeverity.Hint)); + lintSeverityMap.set('autofix', capped(vscode.DiagnosticSeverity.Information)); + lintSeverityMap.set('advice', capped(vscode.DiagnosticSeverity.Information)); + lintSeverityMap.set('warning', capped(vscode.DiagnosticSeverity.Warning)); + lintSeverityMap.set('error', capped(vscode.DiagnosticSeverity.Error)); } function severity(lint: ArcanistLintMessage): vscode.DiagnosticSeverity { return lintSeverityMap.get(lint.severity as string) || vscode.DiagnosticSeverity.Error; } function lintJsonToDiagnostics(lintResults: Array): vscode.Diagnostic[] { function translate(lint: ArcanistLintMessage): vscode.Diagnostic { let t = customLintTranslator.get(lint.code) || defaultLintTranslator; return t(lint); } return lintResults.map(translate); } diff --git a/src/arc_lint_translators.ts b/src/arc_lint_translators.ts index 4178952..d765aca 100644 --- a/src/arc_lint_translators.ts +++ b/src/arc_lint_translators.ts @@ -1,48 +1,48 @@ import * as vscode from 'vscode'; -import { LintTranslator, defaultLintTranslator } from './arc_lint' +import { LintTranslator, defaultLintTranslator } from './arc_lint'; import { nonNeg } from './misc'; export function setupCustomTranslators(translators: Map) { translators.set("SPELL1", lint => { - let d = defaultLintTranslator(lint) + let d = defaultLintTranslator(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 + return d; }); // "This line is 116 characters long, but the convention is 80 characters." const re_TXT3_length = /\D(\d+) characters\.$/; translators.set('E501', lint => { - let d = defaultLintTranslator(lint) + let d = defaultLintTranslator(lint); d.range = new vscode.Range( lint.line - 1, lint.char - 1, lint.line - 1, 1e9); return d; }); translators.set('TXT3', lint => { - let d = defaultLintTranslator(lint) + let d = defaultLintTranslator(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; }); } diff --git a/src/misc.ts b/src/misc.ts index dece459..b111845 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -1,3 +1,3 @@ export function nonNeg(n: number): number { - return n < 0 ? 0 : n + return n < 0 ? 0 : n; }