-
-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6234993
commit 27a275f
Showing
4 changed files
with
133 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import Module from "module" | ||
import path from "path" | ||
import { ESLintExtendedProgram, ESLintProgram } from "../ast" | ||
|
||
/** | ||
* The interface of a result of ESLint custom parser. | ||
*/ | ||
export type ESLintCustomParserResult = ESLintProgram | ESLintExtendedProgram | ||
|
||
/** | ||
* The interface of ESLint custom parsers. | ||
*/ | ||
export interface ESLintCustomParser { | ||
parse(code: string, options: any): ESLintCustomParserResult | ||
parseForESLint?(code: string, options: any): ESLintCustomParserResult | ||
} | ||
|
||
const createRequire: (filename: string) => (filename: string) => any = | ||
// Added in v12.2.0 | ||
(Module as any).createRequire || | ||
// Added in v10.12.0, but deprecated in v12.2.0. | ||
Module.createRequireFromPath || | ||
// Polyfill - This is not executed on the tests on node@>=10. | ||
/* istanbul ignore next */ | ||
(filename => { | ||
const mod = new Module(filename) | ||
|
||
mod.filename = filename | ||
mod.paths = (Module as any)._nodeModulePaths(path.dirname(filename)) | ||
;(mod as any)._compile("module.exports = require;", filename) | ||
return mod.exports | ||
}) | ||
|
||
let espreeCache: ESLintCustomParser | null = null | ||
|
||
function isLinterPath(p: string): boolean { | ||
return ( | ||
// ESLint 6 and above | ||
p.includes( | ||
`eslint${path.sep}lib${path.sep}linter${path.sep}linter.js`, | ||
) || | ||
// ESLint 5 | ||
p.includes(`eslint${path.sep}lib${path.sep}linter.js`) | ||
) | ||
} | ||
|
||
/** | ||
* Load `espree` from the loaded ESLint. | ||
* If the loaded ESLint was not found, just returns `require("espree")`. | ||
*/ | ||
export function getEspree(): ESLintCustomParser { | ||
if (!espreeCache) { | ||
// Lookup the loaded eslint | ||
const linterPath = Object.keys(require.cache).find(isLinterPath) | ||
if (linterPath) { | ||
try { | ||
espreeCache = createRequire(linterPath)("espree") | ||
} catch { | ||
// ignore | ||
} | ||
} | ||
if (!espreeCache) { | ||
//eslint-disable-next-line @mysticatea/ts/no-require-imports | ||
espreeCache = require("espree") | ||
} | ||
} | ||
|
||
return espreeCache! | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use strict" | ||
|
||
const path = require("path") | ||
|
||
/** | ||
* Spawn a child process to run `childMain()`. | ||
*/ | ||
function parentMain() { | ||
const { spawn } = require("child_process") | ||
|
||
describe("Loading espree from ESLint", () => { | ||
it("should load espree from the ESLint location.", done => { | ||
spawn(process.execPath, [__filename, "--child"], { | ||
stdio: "inherit", | ||
}) | ||
.on("error", done) | ||
.on("exit", code => | ||
code | ||
? done(new Error(`Exited with non-zero: ${code}`)) | ||
: done() | ||
) | ||
}) | ||
}) | ||
} | ||
|
||
/** | ||
* Check this parser loads the `espree` from the location of the loaded ESLint. | ||
*/ | ||
function childMain() { | ||
const assert = require("assert") | ||
const { Linter } = require("./fixtures/eslint") | ||
const linter = new Linter() | ||
linter.defineParser("vue-eslint-parser", require("../src")) | ||
|
||
const beforeEsprees = Object.keys(require.cache).filter(isEspreePath) | ||
|
||
linter.verify( | ||
"<script>'hello'</script>", | ||
{ parser: "vue-eslint-parser" }, | ||
{ filename: "a.vue" } | ||
) | ||
|
||
const afterEsprees = Object.keys(require.cache).filter(isEspreePath) | ||
|
||
assert.strictEqual( | ||
afterEsprees.length, | ||
beforeEsprees.length, | ||
"espree should be loaded from the expected place" | ||
) | ||
} | ||
|
||
function isEspreePath(p) { | ||
return p.includes(`${path.sep}node_modules${path.sep}espree${path.sep}`) | ||
} | ||
|
||
if (process.argv.includes("--child")) { | ||
childMain() | ||
} else { | ||
parentMain() | ||
} |