From 05c3935048577bd7b025d6b833d8503807f02189 Mon Sep 17 00:00:00 2001 From: Ben Mosher Date: Wed, 16 Jan 2019 07:18:43 -0500 Subject: [PATCH] repair `no-deprecated` for ESLint* 5 * technically espree v5 - also technically it doesn't support comma-first anymore but that seems reasonable --- src/ExportMap.js | 48 +++++++++++++++++++++++++++++---------- tests/files/deprecated.js | 6 ++--- tests/src/core/parse.js | 2 ++ utils/parse.js | 6 +++-- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/ExportMap.js b/src/ExportMap.js index 563ff9e8c..c8335d9c8 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -4,6 +4,8 @@ import doctrine from 'doctrine' import debug from 'debug' +import SourceCode from 'eslint/lib/util/source-code' + import parse from 'eslint-module-utils/parse' import resolve from 'eslint-module-utils/resolve' import isIgnored, { hasValidExtension } from 'eslint-module-utils/ignore' @@ -193,22 +195,28 @@ export default class ExportMap { * @param {...[type]} nodes [description] * @return {{doc: object}} */ -function captureDoc(docStyleParsers) { +function captureDoc(source, docStyleParsers) { const metadata = {} , nodes = Array.prototype.slice.call(arguments, 1) // 'some' short-circuits on first 'true' nodes.some(n => { - if (!n.leadingComments) return false - - for (let name in docStyleParsers) { - const doc = docStyleParsers[name](n.leadingComments) - if (doc) { - metadata.doc = doc + try { + // n.leadingComments is legacy `attachComments` behavior + let leadingComments = n.leadingComments || source.getCommentsBefore(n) + if (leadingComments.length === 0) return false + + for (let name in docStyleParsers) { + const doc = docStyleParsers[name](leadingComments) + if (doc) { + metadata.doc = doc + } } - } - return true + return true + } catch (err) { + return false + } }) return metadata @@ -338,6 +346,8 @@ ExportMap.parse = function (path, content, context) { docStyleParsers[style] = availableDocStyleParsers[style] }) + const source = makeSourceCode(content, ast) + // attempt to collect module doc if (ast.comments) { ast.comments.some(c => { @@ -405,7 +415,7 @@ ExportMap.parse = function (path, content, context) { ast.body.forEach(function (n) { if (n.type === 'ExportDefaultDeclaration') { - const exportMeta = captureDoc(docStyleParsers, n) + const exportMeta = captureDoc(source, docStyleParsers, n) if (n.declaration.type === 'Identifier') { addNamespace(exportMeta, n.declaration) } @@ -441,12 +451,12 @@ ExportMap.parse = function (path, content, context) { case 'TSInterfaceDeclaration': case 'TSAbstractClassDeclaration': case 'TSModuleDeclaration': - m.namespace.set(n.declaration.id.name, captureDoc(docStyleParsers, n)) + m.namespace.set(n.declaration.id.name, captureDoc(source, docStyleParsers, n)) break case 'VariableDeclaration': n.declaration.declarations.forEach((d) => recursivePatternCapture(d.id, - id => m.namespace.set(id.name, captureDoc(docStyleParsers, d, n)))) + id => m.namespace.set(id.name, captureDoc(source, docStyleParsers, d, n)))) break } } @@ -531,3 +541,17 @@ function childContext(path, context) { path, } } + + +/** + * sometimes legacy support isn't _that_ hard... right? + */ +function makeSourceCode(text, ast) { + if (SourceCode.length > 1) { + // ESLint 3 + return new SourceCode(text, ast) + } else { + // ESLint 4, 5 + return new SourceCode({ text, ast }) + } +} diff --git a/tests/files/deprecated.js b/tests/files/deprecated.js index 10e81dc91..f5229f59b 100644 --- a/tests/files/deprecated.js +++ b/tests/files/deprecated.js @@ -27,18 +27,18 @@ export const MY_TERRIBLE_ACTION = "ugh" * @deprecated this chain is awful * @type {String} */ -export const CHAIN_A = "a" +export const CHAIN_A = "a", /** * @deprecated so awful * @type {String} */ - , CHAIN_B = "b" + CHAIN_B = "b", /** * @deprecated still terrible * @type {String} */ - , CHAIN_C = "C" + CHAIN_C = "C" /** * this one is fine diff --git a/tests/src/core/parse.js b/tests/src/core/parse.js index 9cc153ae3..4b0f12c62 100644 --- a/tests/src/core/parse.js +++ b/tests/src/core/parse.js @@ -38,6 +38,8 @@ describe('parse(content, { settings, ecmaFeatures })', function () { .that.is.eql(parserOptions.ecmaFeatures) .and.is.not.equal(parserOptions.ecmaFeatures) expect(parseSpy.args[0][1], 'custom parser to get parserOptions.attachComment equal to true').to.have.property('attachComment', true) + expect(parseSpy.args[0][1], 'custom parser to get parserOptions.tokens equal to true').to.have.property('tokens', true) + expect(parseSpy.args[0][1], 'custom parser to get parserOptions.range equal to true').to.have.property('range', true) expect(parseSpy.args[0][1], 'custom parser to get parserOptions.filePath equal to the full path of the source file').to.have.property('filePath', path) }) diff --git a/utils/parse.js b/utils/parse.js index 5bafdba49..2946047ad 100644 --- a/utils/parse.js +++ b/utils/parse.js @@ -19,12 +19,14 @@ exports.default = function parse(path, content, context) { parserOptions = Object.assign({}, parserOptions) parserOptions.ecmaFeatures = Object.assign({}, parserOptions.ecmaFeatures) - // always include and attach comments + // always include comments and tokens (for doc parsing) parserOptions.comment = true - parserOptions.attachComment = true + parserOptions.attachComment = true // keeping this for backward-compat with older parsers + parserOptions.tokens = true // attach node locations parserOptions.loc = true + parserOptions.range = true // provide the `filePath` like eslint itself does, in `parserOptions` // https://github.com/eslint/eslint/blob/3ec436ee/lib/linter.js#L637