Permalink
Browse files

Ignore home config from disableWhenNoEslintConfig (#778)

* Ignore home config from disableWhenNoEslintConfig

* Move isConfigAtHomeRoot to its own file

It needs to be used in both worker and non-worker, so it’s easiest
to just put it in its own file for now until we re-structure.

* Extract copyFileToTempDir as test helper function

* Move temp dir creation to `copyFileToTempDir`
  • Loading branch information...
1 parent 321dc54 commit fe0551bac59ff8775df377f83ce58ff74f53478e @IanVS IanVS committed on GitHub Jan 18, 2017
Showing with 155 additions and 6 deletions.
  1. +28 −0 lib/is-config-at-home-root.js
  2. +4 −1 lib/main.js
  3. +4 −1 lib/worker.js
  4. +2 −1 package.json
  5. +3 −0 spec/fixtures/files/badInline.js
  6. +91 −0 spec/linter-eslint-spec.js
  7. +16 −0 src/is-config-at-home-root.js
  8. +4 −2 src/main.js
  9. +3 −1 src/worker.js
@@ -0,0 +1,28 @@
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+ value: true
+});
+exports.isConfigAtHomeRoot = isConfigAtHomeRoot;
+
+var _userHome = require('user-home');
+
+var _userHome2 = _interopRequireDefault(_userHome);
+
+var _path = require('path');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+/**
+ * Check if a config is directly inside a user's home directory.
+ * Such config files are used by ESLint as a fallback, only for situations
+ * when there is no other config file between a file being linted and root.
+ *
+ * @param {string} configPath - The path of the config file being checked
+ * @return {Boolean} True if the file is directly in the current user's home
+ */
+/* eslint-disable import/prefer-default-export */
+
+function isConfigAtHomeRoot(configPath) {
+ return (0, _path.dirname)(configPath) === _userHome2.default;
+}
View
@@ -11,6 +11,8 @@ var _helpers = require('./helpers');
var _workerHelpers = require('./worker-helpers');
+var _isConfigAtHomeRoot = require('./is-config-at-home-root');
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
@@ -58,7 +60,8 @@ module.exports = {
// Do not try to fix if linting should be disabled
const fileDir = _path2.default.dirname(filePath);
const configPath = (0, _workerHelpers.getConfigPath)(fileDir);
- if (configPath === null && disableWhenNoEslintConfig) return;
+ const noProjectConfig = configPath === null || (0, _isConfigAtHomeRoot.isConfigAtHomeRoot)(configPath);
+ if (noProjectConfig && disableWhenNoEslintConfig) return;
this.worker.request('job', {
type: 'fix',
View
@@ -15,6 +15,8 @@ var _workerHelpers = require('./worker-helpers');
var Helpers = _interopRequireWildcard(_workerHelpers);
+var _isConfigAtHomeRoot = require('./is-config-at-home-root');
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -32,7 +34,8 @@ const ignoredMessages = [
'File ignored by default. Use a negated ignore pattern (like "--ignore-pattern \'!<relative' + '/path/to/filename>\'") to override.', 'File ignored by default. Use "--ignore-pattern \'!node_modules/*\'" to override.', 'File ignored by default. Use "--ignore-pattern \'!bower_components/*\'" to override.'];
function lintJob(argv, contents, eslint, configPath, config) {
- if (configPath === null && config.disableWhenNoEslintConfig) {
+ const noProjectConfig = configPath === null || (0, _isConfigAtHomeRoot.isConfigAtHomeRoot)(configPath);
+ if (noProjectConfig && config.disableWhenNoEslintConfig) {
return [];
}
eslint.execute(argv, contents);
View
@@ -111,7 +111,8 @@
"eslint": "^3.6.0",
"eslint-rule-documentation": "^1.0.0",
"process-communication": "^1.1.0",
- "resolve-env": "^1.0.0"
+ "resolve-env": "^1.0.0",
+ "user-home": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.18.0",
@@ -0,0 +1,3 @@
+/* eslint no-undef: error */
+
+foo = 42;
@@ -10,6 +10,7 @@ const fixturesDir = path.join(__dirname, 'fixtures')
const goodPath = path.join(fixturesDir, 'files', 'good.js')
const badPath = path.join(fixturesDir, 'files', 'bad.js')
+const badInlinePath = path.join(fixturesDir, 'files', 'badInline.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')
@@ -24,6 +25,20 @@ const modifiedIgnoreSpacePath = path.join(fixturesDir,
'modified-ignore-rule', 'foo-space.js')
const endRangePath = path.join(fixturesDir, 'end-range', 'no-unreachable.js')
+function copyFileToTempDir(fileToCopyPath) {
+ return new Promise((resolve) => {
+ const tempFixtureDir = fs.mkdtempSync(tmpdir() + path.sep)
+ const tempFixturePath = path.join(tempFixtureDir, path.basename(fileToCopyPath))
+ const wr = fs.createWriteStream(tempFixturePath)
+ wr.on('close', () =>
+ atom.workspace.open(tempFixturePath).then((openEditor) => {
+ resolve({ openEditor, tempDir: tempFixtureDir })
+ })
+ )
+ fs.createReadStream(fileToCopyPath).pipe(wr)
+ })
+}
+
describe('The eslint provider for Linter', () => {
const { spawnWorker } = require('../lib/helpers')
@@ -361,4 +376,80 @@ describe('The eslint provider for Linter', () => {
)
)
)
+
+ describe('when setting `disableWhenNoEslintConfig` is false', () => {
+ let editor
+ let didError
+ let gotLintingErrors
+ let tempFixtureDir
+
+ beforeEach(() => {
+ atom.config.set('linter-eslint.disableWhenNoEslintConfig', false)
+
+ waitsForPromise(() =>
+ copyFileToTempDir(badInlinePath, tempFixtureDir)
+ .then(({ openEditor, tempDir }) => {
+ editor = openEditor
+ tempFixtureDir = tempDir
+ })
+ )
+ })
+
+ afterEach(() => {
+ rimraf.sync(tempFixtureDir)
+ })
+
+ it('errors when no config file is found', () => {
+ lint(editor)
+ .then((messages) => {
+ // Older versions of ESLint will report an error
+ // (or if current user running tests has a config in their home directory)
+ const expectedHtml = '<a href=http://eslint.org/docs/rules/no-undef ' +
+ 'class="badge badge-flexible eslint">no-undef</a> &#39;foo&#39; is not defined.'
+ expect(messages.length).toBe(1)
+ expect(messages[0].html).toBe(expectedHtml)
+ gotLintingErrors = true
+ })
+ .catch((err) => {
+ // Newer versions of ESLint will throw an exception
+ expect(err.message).toBe('No ESLint configuration found.')
+ didError = true
+ })
+
+ waitsFor(
+ () => didError || gotLintingErrors,
+ 'An error should have been thrown or linting performed'
+ )
+ })
+ })
+
+ describe('when `disableWhenNoEslintConfig` is true', () => {
+ let editor
+ let tempFixtureDir
+
+ beforeEach(() => {
+ atom.config.set('linter-eslint.disableWhenNoEslintConfig', true)
+
+ waitsForPromise(() =>
+ copyFileToTempDir(badInlinePath)
+ .then(({ openEditor, tempDir }) => {
+ editor = openEditor
+ tempFixtureDir = tempDir
+ })
+ )
+ })
+
+ afterEach(() => {
+ rimraf.sync(tempFixtureDir)
+ })
+
+ it('does not report errors when no config file is found', () =>
+ waitsForPromise(() =>
+ lint(editor)
+ .then((messages) => {
+ expect(messages.length).toBe(0)
+ })
+ )
+ )
+ })
})
@@ -0,0 +1,16 @@
+/* eslint-disable import/prefer-default-export */
+
+import userHome from 'user-home'
+import { dirname } from 'path'
+
+/**
+ * Check if a config is directly inside a user's home directory.
+ * Such config files are used by ESLint as a fallback, only for situations
+ * when there is no other config file between a file being linted and root.
+ *
+ * @param {string} configPath - The path of the config file being checked
+ * @return {Boolean} True if the file is directly in the current user's home
+ */
+export function isConfigAtHomeRoot(configPath) {
+ return (dirname(configPath) === userHome)
+}
View
@@ -6,9 +6,10 @@ import { CompositeDisposable, } from 'atom'
import {
spawnWorker, showError, idsToIgnoredRules, processESLintMessages,
- generateDebugString
+ generateDebugString,
} from './helpers'
import { getConfigPath } from './worker-helpers'
+import { isConfigAtHomeRoot } from './is-config-at-home-root'
// Configuration
const scopes = []
@@ -54,7 +55,8 @@ module.exports = {
// Do not try to fix if linting should be disabled
const fileDir = Path.dirname(filePath)
const configPath = getConfigPath(fileDir)
- if (configPath === null && disableWhenNoEslintConfig) return
+ const noProjectConfig = (configPath === null || isConfigAtHomeRoot(configPath))
+ if (noProjectConfig && disableWhenNoEslintConfig) return
this.worker.request('job', {
type: 'fix',
View
@@ -6,6 +6,7 @@ import Path from 'path'
import { create } from 'process-communication'
import { FindCache, findCached } from 'atom-linter'
import * as Helpers from './worker-helpers'
+import { isConfigAtHomeRoot } from './is-config-at-home-root'
process.title = 'linter-eslint helper'
@@ -24,7 +25,8 @@ const ignoredMessages = [
]
function lintJob(argv, contents, eslint, configPath, config) {
- if (configPath === null && config.disableWhenNoEslintConfig) {
+ const noProjectConfig = (configPath === null || isConfigAtHomeRoot(configPath))
+ if (noProjectConfig && config.disableWhenNoEslintConfig) {
return []
}
eslint.execute(argv, contents)

0 comments on commit fe0551b

Please sign in to comment.