From fe6225a333dfc53dacdae2bc5ba9eec61a34aefd Mon Sep 17 00:00:00 2001 From: ota-meshi Date: Mon, 22 Jan 2024 11:07:33 +0900 Subject: [PATCH] test: add scope test --- scripts/update-fixtures-ast.js | 144 ++------------------------------- test/ast.js | 53 +++++------- test/test-utils.js | 140 ++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 172 deletions(-) create mode 100644 test/test-utils.js diff --git a/scripts/update-fixtures-ast.js b/scripts/update-fixtures-ast.js index 8990574..cb32843 100644 --- a/scripts/update-fixtures-ast.js +++ b/scripts/update-fixtures-ast.js @@ -12,8 +12,13 @@ const fs = require("fs") const path = require("path") const parser = require("../src") -const escope = require("eslint-scope") const semver = require("semver") +const { + scopeToJSON, + analyze, + replacer, + getAllTokens, +} = require("../test/test-utils") //------------------------------------------------------------------------------ // Helpers @@ -30,40 +35,6 @@ const PARSER_OPTIONS = { eslintScopeManager: true, } -/** - * Remove `parent` proeprties from the given AST. - * @param {string} key The key. - * @param {any} value The value of the key. - * @returns {any} The value of the key to output. - */ -function replacer(key, value) { - if (key === "parent") { - return undefined - } - if (key === "errors" && Array.isArray(value)) { - return value.map((e) => ({ - message: e.message, - index: e.index, - lineNumber: e.lineNumber, - column: e.column, - })) - } - return value -} - -/** - * Get all tokens of the given AST. - * @param {ASTNode} ast The root node of AST. - * @returns {Token[]} Tokens. - */ -function getAllTokens(ast) { - const tokenArrays = [ast.tokens, ast.comments] - if (ast.templateBody != null) { - tokenArrays.push(ast.templateBody.tokens, ast.templateBody.comments) - } - return Array.prototype.concat.apply([], tokenArrays) -} - /** * Create simple tree. * @param {string} source The source code. @@ -98,109 +69,6 @@ function getTree(source, ast) { return root.children } -function scopeToJSON(scopeManager) { - return JSON.stringify(normalizeScope(scopeManager.globalScope), replacer, 4) - - function normalizeScope(scope) { - return { - type: scope.type, - variables: scope.variables.map(normalizeVar), - references: scope.references.map(normalizeReference), - childScopes: scope.childScopes.map(normalizeScope), - through: scope.through.map(normalizeReference), - } - } - - function normalizeVar(v) { - return { - name: v.name, - identifiers: v.identifiers.map(normalizeId), - defs: v.defs.map(normalizeDef), - references: v.references.map(normalizeReference), - } - } - - function normalizeReference(reference) { - return { - identifier: normalizeId(reference.identifier), - from: reference.from.type, - resolved: normalizeId( - reference.resolved && - reference.resolved.defs && - reference.resolved.defs[0] && - reference.resolved.defs[0].name, - ), - init: reference.init || null, - vueUsedInTemplate: reference.vueUsedInTemplate - ? reference.vueUsedInTemplate - : undefined, - } - } - - function normalizeDef(def) { - return { - type: def.type, - node: normalizeDefNode(def.node), - name: def.name.name, - } - } - - function normalizeId(identifier) { - return ( - identifier && { - type: identifier.type, - name: identifier.name, - loc: identifier.loc, - } - ) - } - - function normalizeDefNode(node) { - return { - type: node.type, - loc: node.loc, - } - } -} - -/** - * Analyze scope - */ -function analyze(ast, parserOptions) { - const ecmaVersion = parserOptions.ecmaVersion || 2017 - const ecmaFeatures = parserOptions.ecmaFeatures || {} - const sourceType = parserOptions.sourceType || "script" - const result = escope.analyze(ast, { - ignoreEval: true, - nodejsScope: false, - impliedStrict: ecmaFeatures.impliedStrict, - ecmaVersion, - sourceType, - fallback: getFallbackKeys, - }) - - return result - - function getFallbackKeys(node) { - return Object.keys(node).filter(fallbackKeysFilter, node) - } - - function fallbackKeysFilter(key) { - const value = null - return ( - key !== "comments" && - key !== "leadingComments" && - key !== "loc" && - key !== "parent" && - key !== "range" && - key !== "tokens" && - key !== "trailingComments" && - typeof value === "object" && - (typeof value.type === "string" || Array.isArray(value)) - ) - } -} - //------------------------------------------------------------------------------ // Main //------------------------------------------------------------------------------ diff --git a/test/ast.js b/test/ast.js index c5e946a..31bc8e3 100644 --- a/test/ast.js +++ b/test/ast.js @@ -16,6 +16,7 @@ const lodash = require("lodash") const parser = require("../src") const Linter = require("./fixtures/eslint").Linter const semver = require("semver") +const { scopeToJSON, analyze, replacer, getAllTokens } = require("./test-utils") //------------------------------------------------------------------------------ // Helpers @@ -30,40 +31,7 @@ const PARSER_OPTIONS = { loc: true, range: true, tokens: true, -} - -/** - * Remove `parent` proeprties from the given AST. - * @param {string} key The key. - * @param {any} value The value of the key. - * @returns {any} The value of the key to output. - */ -function replacer(key, value) { - if (key === "parent") { - return undefined - } - if (key === "errors" && Array.isArray(value)) { - return value.map((e) => ({ - message: e.message, - index: e.index, - lineNumber: e.lineNumber, - column: e.column, - })) - } - return value -} - -/** - * Get all tokens of the given AST. - * @param {ASTNode} ast The root node of AST. - * @returns {Token[]} Tokens. - */ -function getAllTokens(ast) { - const tokenArrays = [ast.tokens, ast.comments] - if (ast.templateBody != null) { - tokenArrays.push(ast.templateBody.tokens, ast.templateBody.comments) - } - return Array.prototype.concat.apply([], tokenArrays) + eslintScopeManager: true, } /** @@ -305,6 +273,23 @@ describe("Template AST", () => { assert.strictEqual(actualText, expectedText) }) + it("should scope in the correct.", () => { + const version = require(`eslint/package.json`).version + if (!semver.satisfies(version, ">=8")) { + return + } + const resultPath = path.join(ROOT, `${name}/scope.json`) + if (!fs.existsSync(resultPath)) { + return + } + const expectedText = fs.readFileSync(resultPath, "utf8") + const actualText = scopeToJSON( + actual.scopeManager || analyze(actual.ast, options), + ) + + assert.strictEqual(actualText, expectedText) + }) + it("should have correct parent properties.", () => { validateParent(source, parserOptions) }) diff --git a/test/test-utils.js b/test/test-utils.js new file mode 100644 index 0000000..9373502 --- /dev/null +++ b/test/test-utils.js @@ -0,0 +1,140 @@ +const escope = require("eslint-scope") + +module.exports = { replacer, getAllTokens, scopeToJSON, analyze } + +/** + * Remove `parent` properties from the given AST. + * @param {string} key The key. + * @param {any} value The value of the key. + * @returns {any} The value of the key to output. + */ +function replacer(key, value) { + if (key === "parent") { + return undefined + } + if (key === "errors" && Array.isArray(value)) { + return value.map((e) => ({ + message: e.message, + index: e.index, + lineNumber: e.lineNumber, + column: e.column, + })) + } + return value +} + +/** + * Get all tokens of the given AST. + * @param {ASTNode} ast The root node of AST. + * @returns {Token[]} Tokens. + */ +function getAllTokens(ast) { + const tokenArrays = [ast.tokens, ast.comments] + if (ast.templateBody != null) { + tokenArrays.push(ast.templateBody.tokens, ast.templateBody.comments) + } + return Array.prototype.concat.apply([], tokenArrays) +} + +function scopeToJSON(scopeManager) { + return JSON.stringify(normalizeScope(scopeManager.globalScope), replacer, 4) + + function normalizeScope(scope) { + return { + type: scope.type, + variables: scope.variables.map(normalizeVar), + references: scope.references.map(normalizeReference), + childScopes: scope.childScopes.map(normalizeScope), + through: scope.through.map(normalizeReference), + } + } + + function normalizeVar(v) { + return { + name: v.name, + identifiers: v.identifiers.map(normalizeId), + defs: v.defs.map(normalizeDef), + references: v.references.map(normalizeReference), + } + } + + function normalizeReference(reference) { + return { + identifier: normalizeId(reference.identifier), + from: reference.from.type, + resolved: normalizeId( + reference.resolved && + reference.resolved.defs && + reference.resolved.defs[0] && + reference.resolved.defs[0].name, + ), + init: reference.init || null, + vueUsedInTemplate: reference.vueUsedInTemplate + ? reference.vueUsedInTemplate + : undefined, + } + } + + function normalizeDef(def) { + return { + type: def.type, + node: normalizeDefNode(def.node), + name: def.name.name, + } + } + + function normalizeId(identifier) { + return ( + identifier && { + type: identifier.type, + name: identifier.name, + loc: identifier.loc, + } + ) + } + + function normalizeDefNode(node) { + return { + type: node.type, + loc: node.loc, + } + } +} + +/** + * Analyze scope + */ +function analyze(ast, parserOptions) { + const ecmaVersion = parserOptions.ecmaVersion || 2017 + const ecmaFeatures = parserOptions.ecmaFeatures || {} + const sourceType = parserOptions.sourceType || "script" + const result = escope.analyze(ast, { + ignoreEval: true, + nodejsScope: false, + impliedStrict: ecmaFeatures.impliedStrict, + ecmaVersion, + sourceType, + fallback: getFallbackKeys, + }) + + return result + + function getFallbackKeys(node) { + return Object.keys(node).filter(fallbackKeysFilter, node) + } + + function fallbackKeysFilter(key) { + const value = null + return ( + key !== "comments" && + key !== "leadingComments" && + key !== "loc" && + key !== "parent" && + key !== "range" && + key !== "tokens" && + key !== "trailingComments" && + typeof value === "object" && + (typeof value.type === "string" || Array.isArray(value)) + ) + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy