Ajout de promotion et de commande
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
Copyright JS Foundation and other contributors, https://js.foundation
|
||||
Copyright (C) 2012-2013 Yusuke Suzuki (twitter: @Constellation) and other contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+198
File diff suppressed because one or more lines are too long
+2339
File diff suppressed because it is too large
Load Diff
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @fileoverview Assertion utilities.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
/**
|
||||
* Throws an error if the given condition is not truthy.
|
||||
* @param {boolean} condition The condition to check.
|
||||
* @param {string} message The message to include with the error.
|
||||
* @returns {void}
|
||||
* @throws {Error} When the condition is not truthy.
|
||||
*/
|
||||
export function assert(condition, message = "Assertion failed.") {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import Variable from "./variable.js";
|
||||
|
||||
/**
|
||||
* @constructor Definition
|
||||
*/
|
||||
class Definition {
|
||||
constructor(type, name, node, parent, index, kind) {
|
||||
|
||||
/**
|
||||
* @member {string} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
|
||||
*/
|
||||
this.type = type;
|
||||
|
||||
/**
|
||||
* @member {espree.Identifier} Definition#name - the identifier AST node of the occurrence.
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* @member {espree.Node} Definition#node - the enclosing node of the identifier.
|
||||
*/
|
||||
this.node = node;
|
||||
|
||||
/**
|
||||
* @member {espree.Node?} Definition#parent - the enclosing statement node of the identifier.
|
||||
*/
|
||||
this.parent = parent;
|
||||
|
||||
/**
|
||||
* @member {number?} Definition#index - the index in the declaration statement.
|
||||
*/
|
||||
this.index = index;
|
||||
|
||||
/**
|
||||
* @member {string?} Definition#kind - the kind of the declaration statement.
|
||||
*/
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constructor ParameterDefinition
|
||||
*/
|
||||
class ParameterDefinition extends Definition {
|
||||
constructor(name, node, index, rest) {
|
||||
super(Variable.Parameter, name, node, null, index, null);
|
||||
|
||||
/**
|
||||
* Whether the parameter definition is a part of a rest parameter.
|
||||
* @member {boolean} ParameterDefinition#rest
|
||||
*/
|
||||
this.rest = rest;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
ParameterDefinition,
|
||||
Definition
|
||||
};
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Copyright (C) 2013 Alex Seville <hi@alexanderseville.com>
|
||||
Copyright (C) 2014 Thiago de Arruda <tpadilha84@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Escope (<a href="http://github.com/estools/escope">escope</a>) is an <a
|
||||
* href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>
|
||||
* scope analyzer extracted from the <a
|
||||
* href="http://github.com/estools/esmangle">esmangle project</a/>.
|
||||
* <p>
|
||||
* <em>escope</em> finds lexical scopes in a source program, i.e. areas of that
|
||||
* program where different occurrences of the same identifier refer to the same
|
||||
* variable. With each scope the contained variables are collected, and each
|
||||
* identifier reference in code is linked to its corresponding variable (if
|
||||
* possible).
|
||||
* <p>
|
||||
* <em>escope</em> works on a syntax tree of the parsed source code which has
|
||||
* to adhere to the <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API">
|
||||
* Mozilla Parser API</a>. E.g. <a href="https://github.com/eslint/espree">espree</a> is a parser
|
||||
* that produces such syntax trees.
|
||||
* <p>
|
||||
* The main interface is the {@link analyze} function.
|
||||
* @module escope
|
||||
*/
|
||||
|
||||
import { assert } from "./assert.js";
|
||||
|
||||
import ScopeManager from "./scope-manager.js";
|
||||
import Referencer from "./referencer.js";
|
||||
import Reference from "./reference.js";
|
||||
import Variable from "./variable.js";
|
||||
|
||||
import eslintScopeVersion from "./version.js";
|
||||
|
||||
/**
|
||||
* Set the default options
|
||||
* @returns {Object} options
|
||||
*/
|
||||
function defaultOptions() {
|
||||
return {
|
||||
optimistic: false,
|
||||
nodejsScope: false,
|
||||
impliedStrict: false,
|
||||
sourceType: "script", // one of ['script', 'module', 'commonjs']
|
||||
ecmaVersion: 5,
|
||||
childVisitorKeys: null,
|
||||
fallback: "iteration"
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Preform deep update on option object
|
||||
* @param {Object} target Options
|
||||
* @param {Object} override Updates
|
||||
* @returns {Object} Updated options
|
||||
*/
|
||||
function updateDeeply(target, override) {
|
||||
|
||||
/**
|
||||
* Is hash object
|
||||
* @param {Object} value Test value
|
||||
* @returns {boolean} Result
|
||||
*/
|
||||
function isHashObject(value) {
|
||||
return typeof value === "object" && value instanceof Object && !(value instanceof Array) && !(value instanceof RegExp);
|
||||
}
|
||||
|
||||
for (const key in override) {
|
||||
if (Object.hasOwn(override, key)) {
|
||||
const val = override[key];
|
||||
|
||||
if (isHashObject(val)) {
|
||||
if (isHashObject(target[key])) {
|
||||
updateDeeply(target[key], val);
|
||||
} else {
|
||||
target[key] = updateDeeply({}, val);
|
||||
}
|
||||
} else {
|
||||
target[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main interface function. Takes an Espree syntax tree and returns the
|
||||
* analyzed scopes.
|
||||
* @function analyze
|
||||
* @param {espree.Tree} tree Abstract Syntax Tree
|
||||
* @param {Object} providedOptions Options that tailor the scope analysis
|
||||
* @param {boolean} [providedOptions.optimistic=false] the optimistic flag
|
||||
* @param {boolean} [providedOptions.ignoreEval=false] whether to check 'eval()' calls
|
||||
* @param {boolean} [providedOptions.nodejsScope=false] whether the whole
|
||||
* script is executed under node.js environment. When enabled, escope adds
|
||||
* a function scope immediately following the global scope.
|
||||
* @param {boolean} [providedOptions.impliedStrict=false] implied strict mode
|
||||
* (if ecmaVersion >= 5).
|
||||
* @param {string} [providedOptions.sourceType='script'] the source type of the script. one of 'script', 'module', and 'commonjs'
|
||||
* @param {number} [providedOptions.ecmaVersion=5] which ECMAScript version is considered
|
||||
* @param {boolean} [providedOptions.jsx=false] support JSX references
|
||||
* @param {Object} [providedOptions.childVisitorKeys=null] Additional known visitor keys. See [esrecurse](https://github.com/estools/esrecurse)'s the `childVisitorKeys` option.
|
||||
* @param {string} [providedOptions.fallback='iteration'] A kind of the fallback in order to encounter with unknown node. See [esrecurse](https://github.com/estools/esrecurse)'s the `fallback` option.
|
||||
* @returns {ScopeManager} ScopeManager
|
||||
*/
|
||||
function analyze(tree, providedOptions) {
|
||||
const options = updateDeeply(defaultOptions(), providedOptions);
|
||||
const scopeManager = new ScopeManager(options);
|
||||
const referencer = new Referencer(options, scopeManager);
|
||||
|
||||
referencer.visit(tree);
|
||||
|
||||
assert(scopeManager.__currentScope === null, "currentScope should be null.");
|
||||
|
||||
return scopeManager;
|
||||
}
|
||||
|
||||
export {
|
||||
|
||||
/** @name module:escope.version */
|
||||
eslintScopeVersion as version,
|
||||
|
||||
/** @name module:escope.Reference */
|
||||
Reference,
|
||||
|
||||
/** @name module:escope.Variable */
|
||||
Variable,
|
||||
|
||||
/** @name module:escope.ScopeManager */
|
||||
ScopeManager,
|
||||
|
||||
/** @name module:escope.Referencer */
|
||||
Referencer,
|
||||
|
||||
analyze
|
||||
};
|
||||
|
||||
/** @name module:escope.Definition */
|
||||
export { Definition } from "./definition.js";
|
||||
|
||||
/** @name module:escope.PatternVisitor */
|
||||
export { default as PatternVisitor } from "./pattern-visitor.js";
|
||||
|
||||
/** @name module:escope.Scope */
|
||||
export { Scope } from "./scope.js";
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import estraverse from "estraverse";
|
||||
import esrecurse from "esrecurse";
|
||||
|
||||
const { Syntax } = estraverse;
|
||||
|
||||
/**
|
||||
* Get last array element
|
||||
* @param {Array} xs array
|
||||
* @returns {any} Last elment
|
||||
*/
|
||||
function getLast(xs) {
|
||||
return xs.at(-1) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visitor for destructuring patterns.
|
||||
*/
|
||||
class PatternVisitor extends esrecurse.Visitor {
|
||||
static isPattern(node) {
|
||||
const nodeType = node.type;
|
||||
|
||||
return (
|
||||
nodeType === Syntax.Identifier ||
|
||||
nodeType === Syntax.ObjectPattern ||
|
||||
nodeType === Syntax.ArrayPattern ||
|
||||
nodeType === Syntax.SpreadElement ||
|
||||
nodeType === Syntax.RestElement ||
|
||||
nodeType === Syntax.AssignmentPattern
|
||||
);
|
||||
}
|
||||
|
||||
constructor(options, rootPattern, callback) {
|
||||
super(null, options);
|
||||
this.rootPattern = rootPattern;
|
||||
this.callback = callback;
|
||||
this.assignments = [];
|
||||
this.rightHandNodes = [];
|
||||
this.restElements = [];
|
||||
}
|
||||
|
||||
Identifier(pattern) {
|
||||
const lastRestElement = getLast(this.restElements);
|
||||
|
||||
this.callback(pattern, {
|
||||
topLevel: pattern === this.rootPattern,
|
||||
rest: lastRestElement !== null && lastRestElement !== void 0 && lastRestElement.argument === pattern,
|
||||
assignments: this.assignments
|
||||
});
|
||||
}
|
||||
|
||||
Property(property) {
|
||||
|
||||
// Computed property's key is a right hand node.
|
||||
if (property.computed) {
|
||||
this.rightHandNodes.push(property.key);
|
||||
}
|
||||
|
||||
// If it's shorthand, its key is same as its value.
|
||||
// If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
|
||||
// If it's not shorthand, the name of new variable is its value's.
|
||||
this.visit(property.value);
|
||||
}
|
||||
|
||||
ArrayPattern(pattern) {
|
||||
for (let i = 0, iz = pattern.elements.length; i < iz; ++i) {
|
||||
const element = pattern.elements[i];
|
||||
|
||||
this.visit(element);
|
||||
}
|
||||
}
|
||||
|
||||
AssignmentPattern(pattern) {
|
||||
this.assignments.push(pattern);
|
||||
this.visit(pattern.left);
|
||||
this.rightHandNodes.push(pattern.right);
|
||||
this.assignments.pop();
|
||||
}
|
||||
|
||||
RestElement(pattern) {
|
||||
this.restElements.push(pattern);
|
||||
this.visit(pattern.argument);
|
||||
this.restElements.pop();
|
||||
}
|
||||
|
||||
MemberExpression(node) {
|
||||
|
||||
// Computed property's key is a right hand node.
|
||||
if (node.computed) {
|
||||
this.rightHandNodes.push(node.property);
|
||||
}
|
||||
|
||||
// the object is only read, write to its property.
|
||||
this.rightHandNodes.push(node.object);
|
||||
}
|
||||
|
||||
//
|
||||
// ForInStatement.left and AssignmentExpression.left are LeftHandSideExpression.
|
||||
// By spec, LeftHandSideExpression is Pattern or MemberExpression.
|
||||
// (see also: https://github.com/estree/estree/pull/20#issuecomment-74584758)
|
||||
// But espree 2.0 parses to ArrayExpression, ObjectExpression, etc...
|
||||
//
|
||||
|
||||
SpreadElement(node) {
|
||||
this.visit(node.argument);
|
||||
}
|
||||
|
||||
ArrayExpression(node) {
|
||||
node.elements.forEach(this.visit, this);
|
||||
}
|
||||
|
||||
AssignmentExpression(node) {
|
||||
this.assignments.push(node);
|
||||
this.visit(node.left);
|
||||
this.rightHandNodes.push(node.right);
|
||||
this.assignments.pop();
|
||||
}
|
||||
|
||||
CallExpression(node) {
|
||||
|
||||
// arguments are right hand nodes.
|
||||
node.arguments.forEach(a => {
|
||||
this.rightHandNodes.push(a);
|
||||
});
|
||||
this.visit(node.callee);
|
||||
}
|
||||
}
|
||||
|
||||
export default PatternVisitor;
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
const READ = 0x1;
|
||||
const WRITE = 0x2;
|
||||
const RW = READ | WRITE;
|
||||
|
||||
/**
|
||||
* A Reference represents a single occurrence of an identifier in code.
|
||||
* @constructor Reference
|
||||
*/
|
||||
class Reference {
|
||||
constructor(ident, scope, flag, writeExpr, maybeImplicitGlobal, partial, init) {
|
||||
|
||||
/**
|
||||
* Identifier syntax node.
|
||||
* @member {espreeIdentifier} Reference#identifier
|
||||
*/
|
||||
this.identifier = ident;
|
||||
|
||||
/**
|
||||
* Reference to the enclosing Scope.
|
||||
* @member {Scope} Reference#from
|
||||
*/
|
||||
this.from = scope;
|
||||
|
||||
/**
|
||||
* Whether the reference comes from a dynamic scope (such as 'eval',
|
||||
* 'with', etc.), and may be trapped by dynamic scopes.
|
||||
* @member {boolean} Reference#tainted
|
||||
*/
|
||||
this.tainted = false;
|
||||
|
||||
/**
|
||||
* The variable this reference is resolved with.
|
||||
* @member {Variable} Reference#resolved
|
||||
*/
|
||||
this.resolved = null;
|
||||
|
||||
/**
|
||||
* The read-write mode of the reference. (Value is one of {@link
|
||||
* Reference.READ}, {@link Reference.RW}, {@link Reference.WRITE}).
|
||||
* @member {number} Reference#flag
|
||||
* @private
|
||||
*/
|
||||
this.flag = flag;
|
||||
if (this.isWrite()) {
|
||||
|
||||
/**
|
||||
* If reference is writeable, this is the tree being written to it.
|
||||
* @member {espreeNode} Reference#writeExpr
|
||||
*/
|
||||
this.writeExpr = writeExpr;
|
||||
|
||||
/**
|
||||
* Whether the Reference might refer to a partial value of writeExpr.
|
||||
* @member {boolean} Reference#partial
|
||||
*/
|
||||
this.partial = partial;
|
||||
|
||||
/**
|
||||
* Whether the Reference is to write of initialization.
|
||||
* @member {boolean} Reference#init
|
||||
*/
|
||||
this.init = init;
|
||||
}
|
||||
this.__maybeImplicitGlobal = maybeImplicitGlobal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is static.
|
||||
* @function Reference#isStatic
|
||||
* @returns {boolean} static
|
||||
*/
|
||||
isStatic() {
|
||||
return !this.tainted && this.resolved && this.resolved.scope.isStatic();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is writeable.
|
||||
* @function Reference#isWrite
|
||||
* @returns {boolean} write
|
||||
*/
|
||||
isWrite() {
|
||||
return !!(this.flag & Reference.WRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is readable.
|
||||
* @function Reference#isRead
|
||||
* @returns {boolean} read
|
||||
*/
|
||||
isRead() {
|
||||
return !!(this.flag & Reference.READ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is read-only.
|
||||
* @function Reference#isReadOnly
|
||||
* @returns {boolean} read only
|
||||
*/
|
||||
isReadOnly() {
|
||||
return this.flag === Reference.READ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is write-only.
|
||||
* @function Reference#isWriteOnly
|
||||
* @returns {boolean} write only
|
||||
*/
|
||||
isWriteOnly() {
|
||||
return this.flag === Reference.WRITE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the reference is read-write.
|
||||
* @function Reference#isReadWrite
|
||||
* @returns {boolean} read write
|
||||
*/
|
||||
isReadWrite() {
|
||||
return this.flag === Reference.RW;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @constant Reference.READ
|
||||
* @private
|
||||
*/
|
||||
Reference.READ = READ;
|
||||
|
||||
/**
|
||||
* @constant Reference.WRITE
|
||||
* @private
|
||||
*/
|
||||
Reference.WRITE = WRITE;
|
||||
|
||||
/**
|
||||
* @constant Reference.RW
|
||||
* @private
|
||||
*/
|
||||
Reference.RW = RW;
|
||||
|
||||
export default Reference;
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+708
File diff suppressed because it is too large
Load Diff
+253
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import {
|
||||
BlockScope,
|
||||
CatchScope,
|
||||
ClassFieldInitializerScope,
|
||||
ClassStaticBlockScope,
|
||||
ClassScope,
|
||||
ForScope,
|
||||
FunctionExpressionNameScope,
|
||||
FunctionScope,
|
||||
GlobalScope,
|
||||
ModuleScope,
|
||||
SwitchScope,
|
||||
WithScope
|
||||
} from "./scope.js";
|
||||
import { assert } from "./assert.js";
|
||||
|
||||
/**
|
||||
* @constructor ScopeManager
|
||||
*/
|
||||
class ScopeManager {
|
||||
constructor(options) {
|
||||
this.scopes = [];
|
||||
this.globalScope = null;
|
||||
this.__nodeToScope = new WeakMap();
|
||||
this.__currentScope = null;
|
||||
this.__options = options;
|
||||
this.__declaredVariables = new WeakMap();
|
||||
}
|
||||
|
||||
__isOptimistic() {
|
||||
return this.__options.optimistic;
|
||||
}
|
||||
|
||||
__ignoreEval() {
|
||||
return this.__options.ignoreEval;
|
||||
}
|
||||
|
||||
__isJSXEnabled() {
|
||||
return this.__options.jsx === true;
|
||||
}
|
||||
|
||||
isGlobalReturn() {
|
||||
return this.__options.nodejsScope || this.__options.sourceType === "commonjs";
|
||||
}
|
||||
|
||||
isModule() {
|
||||
return this.__options.sourceType === "module";
|
||||
}
|
||||
|
||||
isImpliedStrict() {
|
||||
return this.__options.impliedStrict;
|
||||
}
|
||||
|
||||
isStrictModeSupported() {
|
||||
return this.__options.ecmaVersion >= 5;
|
||||
}
|
||||
|
||||
// Returns appropriate scope for this node.
|
||||
__get(node) {
|
||||
return this.__nodeToScope.get(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get variables that are declared by the node.
|
||||
*
|
||||
* "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
|
||||
* If the node declares nothing, this method returns an empty array.
|
||||
* CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
|
||||
* @param {Espree.Node} node a node to get.
|
||||
* @returns {Variable[]} variables that declared by the node.
|
||||
*/
|
||||
getDeclaredVariables(node) {
|
||||
return this.__declaredVariables.get(node) || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* acquire scope from node.
|
||||
* @function ScopeManager#acquire
|
||||
* @param {Espree.Node} node node for the acquired scope.
|
||||
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
|
||||
* @returns {Scope?} Scope from node
|
||||
*/
|
||||
acquire(node, inner) {
|
||||
|
||||
/**
|
||||
* predicate
|
||||
* @param {Scope} testScope scope to test
|
||||
* @returns {boolean} predicate
|
||||
*/
|
||||
function predicate(testScope) {
|
||||
if (testScope.type === "function" && testScope.functionExpressionScope) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const scopes = this.__get(node);
|
||||
|
||||
if (!scopes || scopes.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Heuristic selection from all scopes.
|
||||
// If you would like to get all scopes, please use ScopeManager#acquireAll.
|
||||
if (scopes.length === 1) {
|
||||
return scopes[0];
|
||||
}
|
||||
|
||||
if (inner) {
|
||||
for (let i = scopes.length - 1; i >= 0; --i) {
|
||||
const scope = scopes[i];
|
||||
|
||||
if (predicate(scope)) {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0, iz = scopes.length; i < iz; ++i) {
|
||||
const scope = scopes[i];
|
||||
|
||||
if (predicate(scope)) {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* acquire all scopes from node.
|
||||
* @function ScopeManager#acquireAll
|
||||
* @param {Espree.Node} node node for the acquired scope.
|
||||
* @returns {Scopes?} Scope array
|
||||
*/
|
||||
acquireAll(node) {
|
||||
return this.__get(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* release the node.
|
||||
* @function ScopeManager#release
|
||||
* @param {Espree.Node} node releasing node.
|
||||
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
|
||||
* @returns {Scope?} upper scope for the node.
|
||||
*/
|
||||
release(node, inner) {
|
||||
const scopes = this.__get(node);
|
||||
|
||||
if (scopes && scopes.length) {
|
||||
const scope = scopes[0].upper;
|
||||
|
||||
if (!scope) {
|
||||
return null;
|
||||
}
|
||||
return this.acquire(scope.block, inner);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
attach() { } // eslint-disable-line class-methods-use-this -- Desired as instance method
|
||||
|
||||
detach() { } // eslint-disable-line class-methods-use-this -- Desired as instance method
|
||||
|
||||
__nestScope(scope) {
|
||||
if (scope instanceof GlobalScope) {
|
||||
assert(this.__currentScope === null);
|
||||
this.globalScope = scope;
|
||||
}
|
||||
this.__currentScope = scope;
|
||||
return scope;
|
||||
}
|
||||
|
||||
__nestGlobalScope(node) {
|
||||
return this.__nestScope(new GlobalScope(this, node));
|
||||
}
|
||||
|
||||
__nestBlockScope(node) {
|
||||
return this.__nestScope(new BlockScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestFunctionScope(node, isMethodDefinition) {
|
||||
return this.__nestScope(new FunctionScope(this, this.__currentScope, node, isMethodDefinition));
|
||||
}
|
||||
|
||||
__nestForScope(node) {
|
||||
return this.__nestScope(new ForScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestCatchScope(node) {
|
||||
return this.__nestScope(new CatchScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestWithScope(node) {
|
||||
return this.__nestScope(new WithScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestClassScope(node) {
|
||||
return this.__nestScope(new ClassScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestClassFieldInitializerScope(node) {
|
||||
return this.__nestScope(new ClassFieldInitializerScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestClassStaticBlockScope(node) {
|
||||
return this.__nestScope(new ClassStaticBlockScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestSwitchScope(node) {
|
||||
return this.__nestScope(new SwitchScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestModuleScope(node) {
|
||||
return this.__nestScope(new ModuleScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__nestFunctionExpressionNameScope(node) {
|
||||
return this.__nestScope(new FunctionExpressionNameScope(this, this.__currentScope, node));
|
||||
}
|
||||
|
||||
__isES6() {
|
||||
return this.__options.ecmaVersion >= 6;
|
||||
}
|
||||
}
|
||||
|
||||
export default ScopeManager;
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+793
File diff suppressed because it is too large
Load Diff
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Variable represents a locally scoped identifier. These include arguments to
|
||||
* functions.
|
||||
* @constructor Variable
|
||||
*/
|
||||
class Variable {
|
||||
constructor(name, scope) {
|
||||
|
||||
/**
|
||||
* The variable name, as given in the source code.
|
||||
* @member {string} Variable#name
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* List of defining occurrences of this variable (like in 'var ...'
|
||||
* statements or as parameter), as AST nodes.
|
||||
* @member {espree.Identifier[]} Variable#identifiers
|
||||
*/
|
||||
this.identifiers = [];
|
||||
|
||||
/**
|
||||
* List of {@link Reference|references} of this variable (excluding parameter entries)
|
||||
* in its defining scope and all nested scopes. For defining
|
||||
* occurrences only see {@link Variable#defs}.
|
||||
* @member {Reference[]} Variable#references
|
||||
*/
|
||||
this.references = [];
|
||||
|
||||
/**
|
||||
* List of defining occurrences of this variable (like in 'var ...'
|
||||
* statements or as parameter), as custom objects.
|
||||
* @member {Definition[]} Variable#defs
|
||||
*/
|
||||
this.defs = [];
|
||||
|
||||
this.tainted = false;
|
||||
|
||||
/**
|
||||
* Whether this is a stack variable.
|
||||
* @member {boolean} Variable#stack
|
||||
*/
|
||||
this.stack = true;
|
||||
|
||||
/**
|
||||
* Reference to the enclosing Scope.
|
||||
* @member {Scope} Variable#scope
|
||||
*/
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
Variable.CatchClause = "CatchClause";
|
||||
Variable.Parameter = "Parameter";
|
||||
Variable.FunctionName = "FunctionName";
|
||||
Variable.ClassName = "ClassName";
|
||||
Variable.Variable = "Variable";
|
||||
Variable.ImportBinding = "ImportBinding";
|
||||
Variable.ImplicitGlobalVariable = "ImplicitGlobalVariable";
|
||||
|
||||
export default Variable;
|
||||
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
const version = "8.4.0";
|
||||
|
||||
export default version;
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "eslint-scope",
|
||||
"description": "ECMAScript scope analyzer for ESLint",
|
||||
"homepage": "https://github.com/eslint/js/blob/main/packages/eslint-scope/README.md",
|
||||
"main": "./dist/eslint-scope.cjs",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/index.js",
|
||||
"require": "./dist/eslint-scope.cjs"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"version": "8.4.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/eslint/js.git",
|
||||
"directory": "packages/eslint-scope"
|
||||
},
|
||||
"funding": "https://opencollective.com/eslint",
|
||||
"keywords": [
|
||||
"eslint"
|
||||
],
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/js/issues"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"build:update-version": "node tools/update-version.js",
|
||||
"prepublishOnly": "npm run build:update-version && npm run build",
|
||||
"pretest": "npm run build",
|
||||
"release:generate:latest": "eslint-generate-release",
|
||||
"release:generate:alpha": "eslint-generate-prerelease alpha",
|
||||
"release:generate:beta": "eslint-generate-prerelease beta",
|
||||
"release:generate:rc": "eslint-generate-prerelease rc",
|
||||
"release:publish": "eslint-publish-release",
|
||||
"test": "node Makefile.js test"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"lib",
|
||||
"dist/eslint-scope.cjs"
|
||||
],
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/parser": "^8.7.0",
|
||||
"chai": "^4.3.4",
|
||||
"eslint-release": "^3.2.0",
|
||||
"eslint-visitor-keys": "^4.2.1",
|
||||
"espree": "^10.4.0",
|
||||
"npm-license": "^0.3.3",
|
||||
"rollup": "^2.52.7",
|
||||
"shelljs": "^0.8.5",
|
||||
"typescript": "^5.4.2"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user