init source

This commit is contained in:
Le Viet
2022-03-07 22:07:57 +07:00
parent e4376f3777
commit 8aba590a8d
11240 changed files with 1012977 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
# Change Log
All notable changes to this module will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
## Unreleased
## v2.4.1 - 2019-07-19
### Fixed
- Improve parse perf when using `@typescript-eslint/parser` ([#1409], thanks [@bradzacher])
- Improve support for Typescript declare structures ([#1356], thanks [@christophercurrie])
## v2.4.0 - 2019-04-13
### Added
- no-useless-path-segments: Add noUselessIndex option ([#1290], thanks [@timkraut])
### Fixed
- Fix overwriting of dynamic import() CallExpression ([`no-cycle`], [`no-relative-parent-import`], [`no-unresolved`], [`no-useless-path-segments`]) ([#1218], [#1166], [#1035], thanks [@vikr01])
## v2.3.0 - 2019-01-22
### Fixed
- use `process.hrtime()` for cache dates ([#1160], thanks [@hulkish])
## v2.2.0 - 2018-03-29
### Changed
- `parse`: attach node locations by default.
- `moduleVisitor`: visitor now gets the full `import` statement node as a second
argument, so rules may report against the full statement / `require` call instead
of only the string literal node.
## v2.1.1 - 2017-06-22
Re-releasing v2.1.0 after vetting (again) and unable to reproduce issue.
## v2.1.0 - 2017-06-02 [YANKED]
Yanked due to critical issue with cache key resulting from #839.
### Added
- `parse` now additionally passes `filePath` to `parser` in `parserOptions` like `eslint` core does
## v2.0.0 - 2016-11-07
### Changed
- `unambiguous` no longer exposes fast test regex
### Fixed
- `unambiguous.test()` regex is now properly in multiline mode
[#1409]: https://github.com/benmosher/eslint-plugin-import/pull/1409
[#1356]: https://github.com/benmosher/eslint-plugin-import/pull/1356
[#1290]: https://github.com/benmosher/eslint-plugin-import/pull/1290
[#1218]: https://github.com/benmosher/eslint-plugin-import/pull/1218
[#1166]: https://github.com/benmosher/eslint-plugin-import/issues/1166
[#1160]: https://github.com/benmosher/eslint-plugin-import/pull/1160
[#1035]: https://github.com/benmosher/eslint-plugin-import/issues/1035
[@hulkish]: https://github.com/hulkish
[@timkraut]: https://github.com/timkraut
[@vikr01]: https://github.com/vikr01
[@bradzacher]: https://github.com/bradzacher
[@christophercurrie]: https://github.com/christophercurrie
+47
View File
@@ -0,0 +1,47 @@
"use strict"
exports.__esModule = true
const log = require('debug')('eslint-module-utils:ModuleCache')
class ModuleCache {
constructor(map) {
this.map = map || new Map()
}
/**
* returns value for returning inline
* @param {[type]} cacheKey [description]
* @param {[type]} result [description]
*/
set(cacheKey, result) {
this.map.set(cacheKey, { result, lastSeen: process.hrtime() })
log('setting entry for', cacheKey)
return result
}
get(cacheKey, settings) {
if (this.map.has(cacheKey)) {
const f = this.map.get(cacheKey)
// check fresness
if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result
} else log('cache miss for', cacheKey)
// cache miss
return undefined
}
}
ModuleCache.getSettings = function (settings) {
const cacheSettings = Object.assign({
lifetime: 30, // seconds
}, settings['import/cache'])
// parse infinity
if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
cacheSettings.lifetime = Infinity
}
return cacheSettings
}
exports.default = ModuleCache
+14
View File
@@ -0,0 +1,14 @@
"use strict"
exports.__esModule = true
exports.default = function declaredScope(context, name) {
let references = context.getScope().references
, i
for (i = 0; i < references.length; i++) {
if (references[i].identifier.name === name) {
break
}
}
if (!references[i]) return undefined
return references[i].resolved.scope.type
}
+59
View File
@@ -0,0 +1,59 @@
/**
* utilities for hashing config objects.
* basically iteratively updates hash with a JSON-like format
*/
"use strict"
exports.__esModule = true
const createHash = require('crypto').createHash
const stringify = JSON.stringify
function hashify(value, hash) {
if (!hash) hash = createHash('sha256')
if (value instanceof Array) {
hashArray(value, hash)
} else if (value instanceof Object) {
hashObject(value, hash)
} else {
hash.update(stringify(value) || 'undefined')
}
return hash
}
exports.default = hashify
function hashArray(array, hash) {
if (!hash) hash = createHash('sha256')
hash.update('[')
for (let i = 0; i < array.length; i++) {
hashify(array[i], hash)
hash.update(',')
}
hash.update(']')
return hash
}
hashify.array = hashArray
exports.hashArray = hashArray
function hashObject(object, hash) {
if (!hash) hash = createHash('sha256')
hash.update("{")
Object.keys(object).sort().forEach(key => {
hash.update(stringify(key))
hash.update(':')
hashify(object[key], hash)
hash.update(",")
})
hash.update('}')
return hash
}
hashify.object = hashObject
exports.hashObject = hashObject
+60
View File
@@ -0,0 +1,60 @@
'use strict'
exports.__esModule = true
const extname = require('path').extname
const log = require('debug')('eslint-plugin-import:utils:ignore')
// one-shot memoized
let cachedSet, lastSettings
function validExtensions(context) {
if (cachedSet && context.settings === lastSettings) {
return cachedSet
}
lastSettings = context.settings
cachedSet = makeValidExtensionSet(context.settings)
return cachedSet
}
function makeValidExtensionSet(settings) {
// start with explicit JS-parsed extensions
const exts = new Set(settings['import/extensions'] || [ '.js' ])
// all alternate parser extensions are also valid
if ('import/parsers' in settings) {
for (let parser in settings['import/parsers']) {
const parserSettings = settings['import/parsers'][parser]
if (!Array.isArray(parserSettings)) {
throw new TypeError('"settings" for ' + parser + ' must be an array')
}
parserSettings.forEach(ext => exts.add(ext))
}
}
return exts
}
exports.getFileExtensions = makeValidExtensionSet
exports.default = function ignore(path, context) {
// check extension whitelist first (cheap)
if (!hasValidExtension(path, context)) return true
if (!('import/ignore' in context.settings)) return false
const ignoreStrings = context.settings['import/ignore']
for (let i = 0; i < ignoreStrings.length; i++) {
const regex = new RegExp(ignoreStrings[i])
if (regex.test(path)) {
log(`ignoring ${path}, matched pattern /${ignoreStrings[i]}/`)
return true
}
}
return false
}
function hasValidExtension(path, context) {
return validExtensions(context).has(extname(path))
}
exports.hasValidExtension = hasValidExtension
+30
View File
@@ -0,0 +1,30 @@
"use strict"
exports.__esModule = true
const Module = require('module')
const path = require('path')
// borrowed from babel-eslint
function createModule(filename) {
const mod = new Module(filename)
mod.filename = filename
mod.paths = Module._nodeModulePaths(path.dirname(filename))
return mod
}
exports.default = function moduleRequire(p) {
try {
// attempt to get espree relative to eslint
const eslintPath = require.resolve('eslint')
const eslintModule = createModule(eslintPath)
return require(Module._resolveFilename(p, eslintModule))
} catch(err) { /* ignore */ }
try {
// try relative to entry point
return require.main.require(p)
} catch(err) { /* ignore */ }
// finally, try from here
return require(p)
}
+141
View File
@@ -0,0 +1,141 @@
'use strict'
exports.__esModule = true
/**
* Returns an object of node visitors that will call
* 'visitor' with every discovered module path.
*
* todo: correct function prototype for visitor
* @param {Function(String)} visitor [description]
* @param {[type]} options [description]
* @return {object}
*/
exports.default = function visitModules(visitor, options) {
// if esmodule is not explicitly disabled, it is assumed to be enabled
options = Object.assign({ esmodule: true }, options)
let ignoreRegExps = []
if (options.ignore != null) {
ignoreRegExps = options.ignore.map(p => new RegExp(p))
}
function checkSourceValue(source, importer) {
if (source == null) return //?
// handle ignore
if (ignoreRegExps.some(re => re.test(source.value))) return
// fire visitor
visitor(source, importer)
}
// for import-y declarations
function checkSource(node) {
checkSourceValue(node.source, node)
}
// for esmodule dynamic `import()` calls
function checkImportCall(node) {
if (node.callee.type !== 'Import') return
if (node.arguments.length !== 1) return
const modulePath = node.arguments[0]
if (modulePath.type !== 'Literal') return
if (typeof modulePath.value !== 'string') return
checkSourceValue(modulePath, node)
}
// for CommonJS `require` calls
// adapted from @mctep: http://git.io/v4rAu
function checkCommon(call) {
if (call.callee.type !== 'Identifier') return
if (call.callee.name !== 'require') return
if (call.arguments.length !== 1) return
const modulePath = call.arguments[0]
if (modulePath.type !== 'Literal') return
if (typeof modulePath.value !== 'string') return
checkSourceValue(modulePath, call)
}
function checkAMD(call) {
if (call.callee.type !== 'Identifier') return
if (call.callee.name !== 'require' &&
call.callee.name !== 'define') return
if (call.arguments.length !== 2) return
const modules = call.arguments[0]
if (modules.type !== 'ArrayExpression') return
for (let element of modules.elements) {
if (element.type !== 'Literal') continue
if (typeof element.value !== 'string') continue
if (element.value === 'require' ||
element.value === 'exports') continue // magic modules: http://git.io/vByan
checkSourceValue(element, element)
}
}
const visitors = {}
if (options.esmodule) {
Object.assign(visitors, {
'ImportDeclaration': checkSource,
'ExportNamedDeclaration': checkSource,
'ExportAllDeclaration': checkSource,
'CallExpression': checkImportCall,
})
}
if (options.commonjs || options.amd) {
const currentCallExpression = visitors['CallExpression']
visitors['CallExpression'] = function (call) {
if (currentCallExpression) currentCallExpression(call)
if (options.commonjs) checkCommon(call)
if (options.amd) checkAMD(call)
}
}
return visitors
}
/**
* make an options schema for the module visitor, optionally
* adding extra fields.
*/
function makeOptionsSchema(additionalProperties) {
const base = {
'type': 'object',
'properties': {
'commonjs': { 'type': 'boolean' },
'amd': { 'type': 'boolean' },
'esmodule': { 'type': 'boolean' },
'ignore': {
'type': 'array',
'minItems': 1,
'items': { 'type': 'string' },
'uniqueItems': true,
},
},
'additionalProperties': false,
}
if (additionalProperties){
for (let key in additionalProperties) {
base.properties[key] = additionalProperties[key]
}
}
return base
}
exports.makeOptionsSchema = makeOptionsSchema
/**
* json schema object for options parameter. can be used to build
* rule options schema object.
* @type {Object}
*/
exports.optionsSchema = makeOptionsSchema()
+63
View File
@@ -0,0 +1,63 @@
{
"_args": [
[
"eslint-module-utils@2.4.1",
"/home/app"
]
],
"_development": true,
"_from": "eslint-module-utils@2.4.1",
"_id": "eslint-module-utils@2.4.1",
"_inBundle": false,
"_integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==",
"_location": "/eslint-module-utils",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "eslint-module-utils@2.4.1",
"name": "eslint-module-utils",
"escapedName": "eslint-module-utils",
"rawSpec": "2.4.1",
"saveSpec": null,
"fetchSpec": "2.4.1"
},
"_requiredBy": [
"/eslint-plugin-import"
],
"_resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz",
"_spec": "2.4.1",
"_where": "/home/app",
"author": {
"name": "Ben Mosher",
"email": "me@benmosher.com"
},
"bugs": {
"url": "https://github.com/benmosher/eslint-plugin-import/issues"
},
"dependencies": {
"debug": "^2.6.8",
"pkg-dir": "^2.0.0"
},
"description": "Core utilities to support eslint-plugin-import and other module-related plugins.",
"engines": {
"node": ">=4"
},
"homepage": "https://github.com/benmosher/eslint-plugin-import#readme",
"keywords": [
"eslint-plugin-import",
"eslint",
"modules",
"esmodules"
],
"license": "MIT",
"name": "eslint-module-utils",
"repository": {
"type": "git",
"url": "git+https://github.com/benmosher/eslint-plugin-import.git"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"version": "2.4.1"
}
+62
View File
@@ -0,0 +1,62 @@
"use strict"
exports.__esModule = true
const moduleRequire = require('./module-require').default
const extname = require('path').extname
const log = require('debug')('eslint-plugin-import:parse')
exports.default = function parse(path, content, context) {
if (context == null) throw new Error('need context to parse properly')
let parserOptions = context.parserOptions
const parserPath = getParserPath(path, context)
if (!parserPath) throw new Error('parserPath is required!')
// hack: espree blows up with frozen options
parserOptions = Object.assign({}, parserOptions)
parserOptions.ecmaFeatures = Object.assign({}, parserOptions.ecmaFeatures)
// always include comments and tokens (for doc parsing)
parserOptions.comment = 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
parserOptions.filePath = path
// @typescript-eslint/parser will parse the entire project with typechecking if you provide
// "project" or "projects" in parserOptions. Removing these options means the parser will
// only parse one file in isolate mode, which is much, much faster.
// https://github.com/benmosher/eslint-plugin-import/issues/1408#issuecomment-509298962
delete parserOptions.project;
delete parserOptions.projects;
// require the parser relative to the main module (i.e., ESLint)
const parser = moduleRequire(parserPath)
return parser.parse(content, parserOptions)
}
function getParserPath(path, context) {
const parsers = context.settings['import/parsers']
if (parsers != null) {
const extension = extname(path)
for (let parserPath in parsers) {
if (parsers[parserPath].indexOf(extension) > -1) {
// use this alternate parser
log('using alt parser:', parserPath)
return parserPath
}
}
}
// default to use ESLint parser
return context.parserPath
}
+206
View File
@@ -0,0 +1,206 @@
"use strict"
exports.__esModule = true
const pkgDir = require('pkg-dir')
const fs = require('fs')
const path = require('path')
const hashObject = require('./hash').hashObject
, ModuleCache = require('./ModuleCache').default
const CASE_SENSITIVE_FS = !fs.existsSync(path.join(__dirname, 'reSOLVE.js'))
exports.CASE_SENSITIVE_FS = CASE_SENSITIVE_FS
const fileExistsCache = new ModuleCache()
function tryRequire(target) {
let resolved;
try {
// Check if the target exists
resolved = require.resolve(target);
} catch(e) {
// If the target does not exist then just return undefined
return undefined;
}
// If the target exists then return the loaded module
return require(resolved);
}
// http://stackoverflow.com/a/27382838
exports.fileExistsWithCaseSync = function fileExistsWithCaseSync(filepath, cacheSettings) {
// don't care if the FS is case-sensitive
if (CASE_SENSITIVE_FS) return true
// null means it resolved to a builtin
if (filepath === null) return true
if (filepath.toLowerCase() === process.cwd().toLowerCase()) return true
const parsedPath = path.parse(filepath)
, dir = parsedPath.dir
let result = fileExistsCache.get(filepath, cacheSettings)
if (result != null) return result
// base case
if (dir === '' || parsedPath.root === filepath) {
result = true
} else {
const filenames = fs.readdirSync(dir)
if (filenames.indexOf(parsedPath.base) === -1) {
result = false
} else {
result = fileExistsWithCaseSync(dir, cacheSettings)
}
}
fileExistsCache.set(filepath, result)
return result
}
function relative(modulePath, sourceFile, settings) {
return fullResolve(modulePath, sourceFile, settings).path
}
function fullResolve(modulePath, sourceFile, settings) {
// check if this is a bonus core module
const coreSet = new Set(settings['import/core-modules'])
if (coreSet != null && coreSet.has(modulePath)) return { found: true, path: null }
const sourceDir = path.dirname(sourceFile)
, cacheKey = sourceDir + hashObject(settings).digest('hex') + modulePath
const cacheSettings = ModuleCache.getSettings(settings)
const cachedPath = fileExistsCache.get(cacheKey, cacheSettings)
if (cachedPath !== undefined) return { found: true, path: cachedPath }
function cache(resolvedPath) {
fileExistsCache.set(cacheKey, resolvedPath)
}
function withResolver(resolver, config) {
function v1() {
try {
const resolved = resolver.resolveImport(modulePath, sourceFile, config)
if (resolved === undefined) return { found: false }
return { found: true, path: resolved }
} catch (err) {
return { found: false }
}
}
function v2() {
return resolver.resolve(modulePath, sourceFile, config)
}
switch (resolver.interfaceVersion) {
case 2:
return v2()
default:
case 1:
return v1()
}
}
const configResolvers = (settings['import/resolver']
|| { 'node': settings['import/resolve'] }) // backward compatibility
const resolvers = resolverReducer(configResolvers, new Map())
for (let pair of resolvers) {
let name = pair[0]
, config = pair[1]
const resolver = requireResolver(name, sourceFile)
, resolved = withResolver(resolver, config)
if (!resolved.found) continue
// else, counts
cache(resolved.path)
return resolved
}
// failed
// cache(undefined)
return { found: false }
}
exports.relative = relative
function resolverReducer(resolvers, map) {
if (resolvers instanceof Array) {
resolvers.forEach(r => resolverReducer(r, map))
return map
}
if (typeof resolvers === 'string') {
map.set(resolvers, null)
return map
}
if (typeof resolvers === 'object') {
for (let key in resolvers) {
map.set(key, resolvers[key])
}
return map
}
throw new Error('invalid resolver config')
}
function getBaseDir(sourceFile) {
return pkgDir.sync(sourceFile) || process.cwd()
}
function requireResolver(name, sourceFile) {
// Try to resolve package with conventional name
let resolver = tryRequire(`eslint-import-resolver-${name}`) ||
tryRequire(name) ||
tryRequire(path.resolve(getBaseDir(sourceFile), name))
if (!resolver) {
throw new Error(`unable to load resolver "${name}".`)
}
if (!isResolverValid(resolver)) {
throw new Error(`${name} with invalid interface loaded as resolver`)
}
return resolver
}
function isResolverValid(resolver) {
if (resolver.interfaceVersion === 2) {
return resolver.resolve && typeof resolver.resolve === 'function'
} else {
return resolver.resolveImport && typeof resolver.resolveImport === 'function'
}
}
const erroredContexts = new Set()
/**
* Given
* @param {string} p - module path
* @param {object} context - ESLint context
* @return {string} - the full module filesystem path;
* null if package is core;
* undefined if not found
*/
function resolve(p, context) {
try {
return relative( p
, context.getFilename()
, context.settings
)
} catch (err) {
if (!erroredContexts.has(context)) {
context.report({
message: `Resolve error: ${err.message}`,
loc: { line: 1, column: 0 },
})
erroredContexts.add(context)
}
}
}
resolve.relative = relative
exports.default = resolve
+30
View File
@@ -0,0 +1,30 @@
'use strict'
exports.__esModule = true
const pattern = /(^|;)\s*(export|import)((\s+\w)|(\s*[{*=]))/m
/**
* detect possible imports/exports without a full parse.
*
* A negative test means that a file is definitely _not_ a module.
* A positive test means it _could_ be.
*
* Not perfect, just a fast way to disqualify large non-ES6 modules and
* avoid a parse.
* @type {RegExp}
*/
exports.test = function isMaybeUnambiguousModule(content) {
return pattern.test(content)
}
// future-/Babel-proof at the expense of being a little loose
const unambiguousNodeType = /^(?:(?:Exp|Imp)ort.*Declaration|TSExportAssignment)$/
/**
* Given an AST, return true if the AST unambiguously represents a module.
* @param {Program node} ast
* @return {Boolean}
*/
exports.isModule = function isUnambiguousModule(ast) {
return ast.body.some(node => unambiguousNodeType.test(node.type))
}