From 86381852cd4f81dc140230e4270a7347e9974ba1 Mon Sep 17 00:00:00 2001 From: Landon Abney Date: Fri, 16 Sep 2016 15:48:20 -0700 Subject: [PATCH] Add support for endLine and endColumn Add support for creating a full range from an ESLint message if it specifies an `endLine` and `endColumn`. Also adds a `validatePoint` helper function to check that these coordinates given from ESLint are valid since we no longer have the checking built into `helpers.rangeFromLineNumber`. --- lib/helpers.js | 9 +++++ lib/main.js | 12 ++++++- spec/fixtures/end-range/.eslintrc.js | 6 ++++ spec/fixtures/end-range/no-unreachable.js | 8 +++++ spec/linter-eslint-spec.js | 41 +++++++++++++++++------ src/helpers.js | 8 +++++ src/main.js | 18 +++++++--- 7 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 spec/fixtures/end-range/.eslintrc.js create mode 100644 spec/fixtures/end-range/no-unreachable.js diff --git a/lib/helpers.js b/lib/helpers.js index 6cb50a6d..39aec3ad 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { exports.spawnWorker = spawnWorker; exports.showError = showError; exports.idsToIgnoredRules = idsToIgnoredRules; +exports.validatePoint = validatePoint; var _child_process = require('child_process'); @@ -74,3 +75,11 @@ function idsToIgnoredRules() { return ids; }, {}); } + +function validatePoint(textEditor, line, col) { + var buffer = textEditor.getBuffer(); + // Clip the given point to a valid one, and check if it equals the original + if (!buffer.clipPosition([line, col]).isEqual([line, col])) { + throw new Error(line + ':' + col + ' isn\'t a valid point!'); + } +} diff --git a/lib/main.js b/lib/main.js index 4d047634..d2e9e80d 100644 --- a/lib/main.js +++ b/lib/main.js @@ -167,6 +167,8 @@ module.exports = { var ruleId = _ref.ruleId; var column = _ref.column; var fix = _ref.fix; + var endLine = _ref.endLine; + var endColumn = _ref.endColumn; var textBuffer = textEditor.getBuffer(); var linterFix = null; @@ -178,8 +180,16 @@ module.exports = { }; } var range = void 0; + var msgLine = line - 1; + var msgCol = column ? column - 1 : column; try { - range = Helpers.rangeFromLineNumber(textEditor, line - 1, column ? column - 1 : column); + if (endColumn && endLine) { + (0, _helpers.validatePoint)(textEditor, msgLine, msgCol); + (0, _helpers.validatePoint)(textEditor, endLine - 1, endColumn - 1); + range = [[msgLine, msgCol], [endLine - 1, endColumn - 1]]; + } else { + range = Helpers.rangeFromLineNumber(textEditor, msgLine, msgCol); + } } catch (err) { throw new Error('Cannot mark location in editor for (' + ruleId + ') - (' + message + ')' + (' at line (' + line + ') column (' + column + ')')); } diff --git a/spec/fixtures/end-range/.eslintrc.js b/spec/fixtures/end-range/.eslintrc.js new file mode 100644 index 00000000..c4e73b57 --- /dev/null +++ b/spec/fixtures/end-range/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + root: true, + rules: { + 'no-unreachable': 'error' + } +}; diff --git a/spec/fixtures/end-range/no-unreachable.js b/spec/fixtures/end-range/no-unreachable.js new file mode 100644 index 00000000..1af8df64 --- /dev/null +++ b/spec/fixtures/end-range/no-unreachable.js @@ -0,0 +1,8 @@ +'use strict'; + +function foo() { + return 42; + + var a = 4; + return a + 2; +} diff --git a/spec/linter-eslint-spec.js b/spec/linter-eslint-spec.js index 0b264a8c..ff54cb61 100644 --- a/spec/linter-eslint-spec.js +++ b/spec/linter-eslint-spec.js @@ -6,21 +6,23 @@ import { tmpdir } from 'os' import rimraf from 'rimraf' import linter from '../lib/main' -const goodPath = path.join(__dirname, 'fixtures', 'files', 'good.js') -const badPath = path.join(__dirname, 'fixtures', 'files', 'bad.js') -const emptyPath = path.join(__dirname, 'fixtures', 'files', 'empty.js') -const fixPath = path.join(__dirname, 'fixtures', 'files', 'fix.js') -const configPath = path.join(__dirname, 'fixtures', 'configs', '.eslintrc.yml') -const importingpath = path.join(__dirname, 'fixtures', +const fixturesDir = path.join(__dirname, 'fixtures') + +const goodPath = path.join(fixturesDir, 'files', 'good.js') +const badPath = path.join(fixturesDir, 'files', 'bad.js') +const emptyPath = path.join(fixturesDir, 'files', 'empty.js') +const fixPath = path.join(fixturesDir, 'files', 'fix.js') +const configPath = path.join(fixturesDir, 'configs', '.eslintrc.yml') +const importingpath = path.join(fixturesDir, 'import-resolution', 'nested', 'importing.js') -const badImportPath = path.join(__dirname, 'fixtures', +const badImportPath = path.join(fixturesDir, 'import-resolution', 'nested', 'badImport.js') -const ignoredPath = path.join(__dirname, 'fixtures', - 'eslintignore', 'ignored.js') -const modifiedIgnorePath = path.join(__dirname, 'fixtures', +const ignoredPath = path.join(fixturesDir, 'eslintignore', 'ignored.js') +const modifiedIgnorePath = path.join(fixturesDir, 'modified-ignore-rule', 'foo.js') -const modifiedIgnoreSpacePath = path.join(__dirname, 'fixtures', +const modifiedIgnoreSpacePath = path.join(fixturesDir, 'modified-ignore-rule', 'foo-space.js') +const endRangePath = path.join(fixturesDir, 'end-range', 'no-unreachable.js') describe('The eslint provider for Linter', () => { const { spawnWorker } = require('../lib/helpers') @@ -288,4 +290,21 @@ describe('The eslint provider for Linter', () => { ) }) }) + + it('handles ranges in messages', () => + waitsForPromise(() => + atom.workspace.open(endRangePath).then(editor => + lint(editor).then((messages) => { + const expected = 'no-unreachable ' + + 'Unreachable code.' + expect(messages[0].type).toBe('Error') + expect(messages[0].text).not.toBeDefined() + expect(messages[0].html).toBe(expected) + expect(messages[0].filePath).toBe(endRangePath) + expect(messages[0].range).toEqual([[5, 2], [6, 15]]) + }) + ) + ) + ) }) diff --git a/src/helpers.js b/src/helpers.js index c6e26ec7..c3e89b50 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -56,3 +56,11 @@ export function idsToIgnoredRules(ruleIds = []) { return ids }, {}) } + +export function validatePoint(textEditor, line, col) { + const buffer = textEditor.getBuffer() + // Clip the given point to a valid one, and check if it equals the original + if (!buffer.clipPosition([line, col]).isEqual([line, col])) { + throw new Error(`${line}:${col} isn't a valid point!`) + } +} diff --git a/src/main.js b/src/main.js index bdee035d..ec0bb64d 100644 --- a/src/main.js +++ b/src/main.js @@ -6,7 +6,7 @@ import ruleURI from 'eslint-rule-documentation' // eslint-disable-next-line import/no-extraneous-dependencies, import/extensions import { CompositeDisposable, Range } from 'atom' -import { spawnWorker, showError, idsToIgnoredRules } from './helpers' +import { spawnWorker, showError, idsToIgnoredRules, validatePoint } from './helpers' // Configuration const scopes = [] @@ -150,7 +150,9 @@ module.exports = { */ return null } - return response.map(({ message, line, severity, ruleId, column, fix }) => { + return response.map(({ + message, line, severity, ruleId, column, fix, endLine, endColumn } + ) => { const textBuffer = textEditor.getBuffer() let linterFix = null if (fix) { @@ -164,10 +166,16 @@ module.exports = { } } let range + const msgLine = line - 1 + const msgCol = column ? column - 1 : column try { - range = Helpers.rangeFromLineNumber( - textEditor, line - 1, column ? column - 1 : column - ) + if (endColumn && endLine) { + validatePoint(textEditor, msgLine, msgCol) + validatePoint(textEditor, endLine - 1, endColumn - 1) + range = [[msgLine, msgCol], [endLine - 1, endColumn - 1]] + } else { + range = Helpers.rangeFromLineNumber(textEditor, msgLine, msgCol) + } } catch (err) { throw new Error( `Cannot mark location in editor for (${ruleId}) - (${message})` +