From 5d9fe7b2c2bedf138bf3505a908ad870cbe8e158 Mon Sep 17 00:00:00 2001 From: Steven Hobson-Campbell Date: Mon, 24 Apr 2017 18:55:33 -0700 Subject: [PATCH 1/4] Fixing bug where the worker thread would hang if there wasn't a tslint.json file --- lib/worker.js | 13 +++++++++---- spec/fixtures/no-config/noConfig.ts | 2 ++ spec/linter-tslint-spec.js | 9 ++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 spec/fixtures/no-config/noConfig.ts diff --git a/lib/worker.js b/lib/worker.js index 3061832d..0ede3e89 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -123,8 +123,8 @@ async function lint(content, filePath, options) { return path.join(configurationDir, dir); }); - if (rulesDirectory) { - rulesDirectory.push(rulesDirectory); + if (config.rulesDirectory) { + rulesDirectory.push(config.rulesDirectory); } } @@ -133,8 +133,13 @@ async function lint(content, filePath, options) { rulesDirectory, }, options)); - linter.lint(filePath, content, configuration); - const lintResult = linter.getResult(); + let lintResult; + try { + linter.lint(filePath, content, configuration); + lintResult = linter.getResult(); + } catch (err) { + lintResult = {}; + } if ( // tslint@<5 diff --git a/spec/fixtures/no-config/noConfig.ts b/spec/fixtures/no-config/noConfig.ts new file mode 100644 index 00000000..129e7f10 --- /dev/null +++ b/spec/fixtures/no-config/noConfig.ts @@ -0,0 +1,2 @@ +const foo = 42; +export default foo; diff --git a/spec/linter-tslint-spec.js b/spec/linter-tslint-spec.js index 03146a55..205b7c47 100644 --- a/spec/linter-tslint-spec.js +++ b/spec/linter-tslint-spec.js @@ -2,8 +2,9 @@ import * as path from 'path'; -const validPath = path.join(__dirname, 'fixtures', 'valid', 'valid.ts'); const invalidPath = path.join(__dirname, 'fixtures', 'invalid', 'invalid.ts'); +const noConfigPath = path.join(__dirname, 'fixtures', 'no-config', 'noConfig.ts'); +const validPath = path.join(__dirname, 'fixtures', 'valid', 'valid.ts'); describe('The TSLint provider for Linter', () => { const lint = require('../lib/main.js').provideLinter().lint; @@ -47,4 +48,10 @@ describe('The TSLint provider for Linter', () => { }), ); }); + + it('validates even when there is no tslint.json', () => { + waitsForPromise(() => + atom.workspace.open(noConfigPath).then(editor => lint(editor)), + ); + }); }); From 07b5725b18465dd24afe823d276069ed1dd44a28 Mon Sep 17 00:00:00 2001 From: Steven Hobson-Campbell Date: Tue, 25 Apr 2017 13:11:52 -0700 Subject: [PATCH 2/4] Logging worker error to console. Making specs async. --- lib/worker.js | 1 + package.json | 3 +- spec/linter-tslint-spec.js | 77 +++++++++++++++++--------------------- 3 files changed, 37 insertions(+), 44 deletions(-) diff --git a/lib/worker.js b/lib/worker.js index 0ede3e89..60133e13 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -138,6 +138,7 @@ async function lint(content, filePath, options) { linter.lint(filePath, content, configuration); lintResult = linter.getResult(); } catch (err) { + console.error(err); // eslint-disable-line no-console lintResult = {}; } diff --git a/package.json b/package.json index dd8e9824..fa628bf6 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "devDependencies": { "eslint": "^3.16.1", "eslint-config-airbnb-base": "^11.1.1", - "eslint-plugin-import": "^2.2.0" + "eslint-plugin-import": "^2.2.0", + "jasmine-fix": "^1.0.1" }, "eslintConfig": { "extends": "airbnb-base", diff --git a/spec/linter-tslint-spec.js b/spec/linter-tslint-spec.js index 205b7c47..2f0dc89f 100644 --- a/spec/linter-tslint-spec.js +++ b/spec/linter-tslint-spec.js @@ -1,57 +1,48 @@ 'use babel'; import * as path from 'path'; +import { beforeEach, it } from 'jasmine-fix'; // eslint-disable-line import/no-extraneous-dependencies +import linterTslint from '../lib/main'; const invalidPath = path.join(__dirname, 'fixtures', 'invalid', 'invalid.ts'); const noConfigPath = path.join(__dirname, 'fixtures', 'no-config', 'noConfig.ts'); const validPath = path.join(__dirname, 'fixtures', 'valid', 'valid.ts'); describe('The TSLint provider for Linter', () => { - const lint = require('../lib/main.js').provideLinter().lint; + const lint = linterTslint.provideLinter().lint; - beforeEach(() => { - atom.workspace.destroyActivePaneItem(); - - waitsForPromise(() => - Promise.all([ - atom.packages.activatePackage('linter-tslint'), - ]), - ); - }); - - it('finds nothing wrong with a valid file', () => { - waitsForPromise(() => - atom.workspace.open(validPath).then(editor => lint(editor)).then((messages) => { - expect(messages.length).toBe(0); - }), - ); - }); - - it('handles messages from TSLint', () => { - const expectedMsg = 'semicolon - Missing semicolon'; - waitsForPromise(() => - atom.workspace.open(invalidPath).then(editor => lint(editor)).then((messages) => { - expect(messages.length).toBe(1); - expect(messages[0].type).toBe('warning'); - expect(messages[0].html).not.toBeDefined(); - expect(messages[0].text).toBe(expectedMsg); - expect(messages[0].filePath).toBe(invalidPath); - expect(messages[0].range).toEqual([[0, 14], [0, 14]]); - }), - ); - }); - - it('handles undefined filepath', () => { - waitsForPromise(() => - atom.workspace.open().then(editor => lint(editor)).then((result) => { - expect(result).toBeNull(); - }), - ); + beforeEach(async () => { + await atom.packages.activatePackage('linter-tslint'); }); - it('validates even when there is no tslint.json', () => { - waitsForPromise(() => - atom.workspace.open(noConfigPath).then(editor => lint(editor)), - ); + describe('When the package is activated', () => { + it('finds nothing wrong with a valid file', async () => { + const editor = await atom.workspace.open(validPath); + const messages = await lint(editor); + expect(messages.length).toBe(0); + }); + + it('handles messages from TSLint', async () => { + const expectedMsg = 'semicolon - Missing semicolon'; + const editor = await atom.workspace.open(invalidPath); + const messages = await lint(editor); + expect(messages.length).toBe(1); + expect(messages[0].type).toBe('warning'); + expect(messages[0].html).not.toBeDefined(); + expect(messages[0].text).toBe(expectedMsg); + expect(messages[0].filePath).toBe(invalidPath); + expect(messages[0].range).toEqual([[0, 14], [0, 14]]); + }); + + it('handles undefined filepath', async () => { + const editor = await atom.workspace.open(); + const result = await lint(editor); + expect(result).toBeNull(); + }); + + it('finishes validatation even when there is no tslint.json', async () => { + const editor = await atom.workspace.open(noConfigPath); + await lint(editor); + }); }); }); From 6601b34bd7feef321a86ea588bbfa8de86f85fba Mon Sep 17 00:00:00 2001 From: Steven Hobson-Campbell Date: Tue, 25 Apr 2017 14:59:23 -0700 Subject: [PATCH 3/4] Adding note about 'fit'. Adding check for 'configurationPath' --- lib/worker.js | 2 +- spec/linter-tslint-spec.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/worker.js b/lib/worker.js index 60133e13..16efda86 100644 --- a/lib/worker.js +++ b/lib/worker.js @@ -111,7 +111,7 @@ async function lint(content, filePath, options) { const configuration = Linter.loadConfigurationFromPath(configurationPath); let { rulesDirectory } = configuration; - if (rulesDirectory) { + if (rulesDirectory && configurationPath) { const configurationDir = path.dirname(configurationPath); if (!Array.isArray(rulesDirectory)) { rulesDirectory = [rulesDirectory]; diff --git a/spec/linter-tslint-spec.js b/spec/linter-tslint-spec.js index 2f0dc89f..f5adad72 100644 --- a/spec/linter-tslint-spec.js +++ b/spec/linter-tslint-spec.js @@ -1,6 +1,7 @@ 'use babel'; import * as path from 'path'; +// NOTE: If using 'fit' you must add it to the list below! import { beforeEach, it } from 'jasmine-fix'; // eslint-disable-line import/no-extraneous-dependencies import linterTslint from '../lib/main'; From 52490b31e04ceaa5d135fc0f9d26068f02f3b0fb Mon Sep 17 00:00:00 2001 From: Steven Hobson-Campbell Date: Tue, 25 Apr 2017 15:27:10 -0700 Subject: [PATCH 4/4] Merging master --- spec/linter-tslint-spec.js | 128 +++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 70 deletions(-) diff --git a/spec/linter-tslint-spec.js b/spec/linter-tslint-spec.js index 0587c323..8b819ae7 100644 --- a/spec/linter-tslint-spec.js +++ b/spec/linter-tslint-spec.js @@ -5,9 +5,12 @@ import * as path from 'path'; import { beforeEach, it } from 'jasmine-fix'; // eslint-disable-line import/no-extraneous-dependencies import linterTslint from '../lib/main'; +// Fixture paths const invalidPath = path.join(__dirname, 'fixtures', 'invalid', 'invalid.ts'); const noConfigPath = path.join(__dirname, 'fixtures', 'no-config', 'noConfig.ts'); const validPath = path.join(__dirname, 'fixtures', 'valid', 'valid.ts'); +const validTypecheckedPath = path.join(__dirname, 'fixtures', 'valid-typechecked', 'valid-typechecked.ts'); +const invalidTypecheckedPath = path.join(__dirname, 'fixtures', 'invalid-typechecked', 'invalid-typechecked.ts'); describe('The TSLint provider for Linter', () => { const lint = linterTslint.provideLinter().lint; @@ -17,78 +20,63 @@ describe('The TSLint provider for Linter', () => { }); describe('When the package is activated', () => { - it('finds nothing wrong with a valid file', async () => { - const editor = await atom.workspace.open(validPath); - const messages = await lint(editor); - expect(messages.length).toBe(0); - }); - - it('handles messages from TSLint', async () => { - const expectedMsg = 'semicolon - Missing semicolon'; - const editor = await atom.workspace.open(invalidPath); - const messages = await lint(editor); - expect(messages.length).toBe(1); - expect(messages[0].type).toBe('warning'); - expect(messages[0].html).not.toBeDefined(); - expect(messages[0].text).toBe(expectedMsg); - expect(messages[0].filePath).toBe(invalidPath); - expect(messages[0].range).toEqual([[0, 14], [0, 14]]); - }); - - it('handles undefined filepath', async () => { - const editor = await atom.workspace.open(); - const result = await lint(editor); - expect(result).toBeNull(); + describe('When dealing with typechecking off (no semantic rules)', () => { + it('finds nothing wrong with a valid file', async () => { + const editor = await atom.workspace.open(validPath); + const result = await lint(editor); + expect(result.length).toBe(0); + }); + + it('handles messages from TSLint', async () => { + const expectedMsg = 'semicolon - Missing semicolon'; + const editor = await atom.workspace.open(invalidPath); + const result = await lint(editor); + expect(result.length).toBe(1); + expect(result[0].type).toBe('warning'); + expect(result[0].html).not.toBeDefined(); + expect(result[0].text).toBe(expectedMsg); + expect(result[0].filePath).toBe(invalidPath); + expect(result[0].range).toEqual([[0, 14], [0, 14]]); + }); + + it('handles undefined filepath', async () => { + const editor = await atom.workspace.open(); + const result = await lint(editor); + expect(result).toBeNull(); + }); + + it('finishes validatation even when there is no tslint.json', async () => { + const editor = await atom.workspace.open(noConfigPath); + await lint(editor); + }); }); - it('finishes validatation even when there is no tslint.json', async () => { - const editor = await atom.workspace.open(noConfigPath); - await lint(editor); + describe('When dealing with typechecking on (with semantic rules)', () => { + beforeEach(() => { + atom.config.set('linter-tslint.enableSemanticRules', true); + }); + + afterEach(() => { + atom.config.set('linter-tslint.enableSemanticRules', false); + }); + + it('finds nothing wrong with a valid file', async () => { + const editor = await atom.workspace.open(validTypecheckedPath); + const result = await lint(editor); + expect(result.length).toBe(0); + }); + + it('handles messages from TSLint', async () => { + const expectedMsg = 'no-boolean-literal-compare - This expression is unnecessarily compared to a boolean. Just use it directly.'; + const editor = await atom.workspace.open(invalidTypecheckedPath); + const result = await lint(editor); + expect(result.length).toBe(1); + expect(result[0].type).toBe('error'); + expect(result[0].html).not.toBeDefined(); + expect(result[0].text).toBe(expectedMsg); + expect(result[0].filePath).toBe(invalidTypecheckedPath); + expect(result[0].range).toEqual([[1, 0], [1, 1]]); + }); }); }); }); - -const validTypecheckedPath = path.join(__dirname, 'fixtures', 'valid-typechecked', 'valid-typechecked.ts'); -const invalidTypecheckedPath = path.join(__dirname, 'fixtures', 'invalid-typechecked', 'invalid-typechecked.ts'); - -describe('The TSLint provider for Linter (with semantic rules)', () => { - const lint = require('../lib/main.js').provideLinter().lint; - - beforeEach(() => { - atom.workspace.destroyActivePaneItem(); - - waitsForPromise(() => - Promise.all([ - atom.packages.activatePackage('linter-tslint'), - ]), - ); - - atom.config.set('linter-tslint.enableSemanticRules', true); - }); - - afterEach(() => { - atom.config.set('linter-tslint.enableSemanticRules', false); - }); - - it('finds nothing wrong with a valid file', () => { - waitsForPromise(() => - atom.workspace.open(validTypecheckedPath).then(editor => lint(editor)).then((messages) => { - expect(messages.length).toBe(0); - }), - ); - }); - - it('handles messages from TSLint', () => { - const expectedMsg = 'no-boolean-literal-compare - This expression is unnecessarily compared to a boolean. Just use it directly.'; - waitsForPromise(() => - atom.workspace.open(invalidTypecheckedPath).then(editor => lint(editor)).then((messages) => { - expect(messages.length).toBe(1); - expect(messages[0].type).toBe('error'); - expect(messages[0].html).not.toBeDefined(); - expect(messages[0].text).toBe(expectedMsg); - expect(messages[0].filePath).toBe(invalidTypecheckedPath); - expect(messages[0].range).toEqual([[1, 0], [1, 1]]); - }), - ); - }); -});