2020-08-25 23:57:08 +00:00
/ *
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 > ) i s a n < 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 < / e m > f i n d s l e x i c a l s c o p e s i n a s o u r c e p r o g r a m , i . e . a r e a s o f t h a t
* 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 < / e m > w o r k s o n a s y n t a x t r e e o f t h e p a r s e d s o u r c e c o d e w h i c h h a s
* 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 > i s a p a r s e r
* that produces such syntax trees .
* < p >
* The main interface is the { @ link analyze } function .
* @ module escope
* /
/* eslint no-underscore-dangle: ["error", { "allow": ["__currentScope"] }] */
2022-11-10 10:43:16 +00:00
import assert from "assert" ;
import ScopeManager from "./scope-manager.js" ;
import Referencer from "./referencer.js" ;
import Reference from "./reference.js" ;
import Variable from "./variable.js" ;
2020-08-25 23:57:08 +00:00
2022-11-10 10:43:16 +00:00
import eslintScopeVersion from "./version.js" ;
2020-08-25 23:57:08 +00:00
/ * *
* Set the default options
* @ returns { Object } options
* /
function defaultOptions ( ) {
return {
optimistic : false ,
directive : false ,
nodejsScope : false ,
impliedStrict : false ,
2022-11-10 10:43:16 +00:00
sourceType : "script" , // one of ['script', 'module', 'commonjs']
2020-08-25 23:57:08 +00:00
ecmaVersion : 5 ,
childVisitorKeys : null ,
fallback : "iteration"
} ;
}
/ * *
* Preform deep update on option object
2022-11-10 10:43:16 +00:00
* @ param { Object } target Options
* @ param { Object } override Updates
2020-08-25 23:57:08 +00:00
* @ returns { Object } Updated options
* /
function updateDeeply ( target , override ) {
/ * *
* Is hash object
2022-11-10 10:43:16 +00:00
* @ param { Object } value Test value
2020-08-25 23:57:08 +00:00
* @ 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 . prototype . hasOwnProperty . call ( 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
2022-11-10 10:43:16 +00:00
* @ 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 . directive = false ] the directive flag
* @ param { boolean } [ providedOptions . ignoreEval = false ] whether to check 'eval()' calls
* @ param { boolean } [ providedOptions . nodejsScope = false ] whether the whole
2020-08-25 23:57:08 +00:00
* script is executed under node . js environment . When enabled , escope adds
* a function scope immediately following the global scope .
2022-11-10 10:43:16 +00:00
* @ param { boolean } [ providedOptions . impliedStrict = false ] implied strict mode
2020-08-25 23:57:08 +00:00
* ( if ecmaVersion >= 5 ) .
2022-11-10 10:43:16 +00:00
* @ 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 { 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.
2020-08-25 23:57:08 +00:00
* @ 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 ;
}
2022-11-10 10:43:16 +00:00
export {
2020-08-25 23:57:08 +00:00
/** @name module:escope.version */
2022-11-10 10:43:16 +00:00
eslintScopeVersion as version ,
2020-08-25 23:57:08 +00:00
/** @name module:escope.Reference */
Reference ,
/** @name module:escope.Variable */
Variable ,
/** @name module:escope.ScopeManager */
ScopeManager ,
2022-11-10 10:43:16 +00:00
/** @name module:escope.Referencer */
Referencer ,
2020-08-25 23:57:08 +00:00
analyze
} ;
2022-11-10 10:43:16 +00:00
/** @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" ;
2020-08-25 23:57:08 +00:00
/* vim: set sw=4 ts=4 et tw=80 : */