Skip to content

Commit 237eac4

Browse files
authored
Fix the wrong location when using with @typescript-eslint/scope-manager (#87)
* Fix the wrong location when using with `@typescript-eslint/scope-manager` * Update * update
1 parent bd916f5 commit 237eac4

File tree

10 files changed

+92
-26
lines changed

10 files changed

+92
-26
lines changed

.eslintrc.yml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
extends:
22
- plugin:@mysticatea/es2015
33
- plugin:@mysticatea/+node
4-
4+
globals: {
5+
root: "off"
6+
}
57
overrides:
8+
- files: "**/*.ts"
9+
parser: "@typescript-eslint/parser"
610
- files: "typings/**"
711
rules:
812
node/no-missing-import:

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@
2121
"lodash": "^4.17.15"
2222
},
2323
"devDependencies": {
24-
"@mysticatea/eslint-plugin": "^11.0.0",
24+
"@mysticatea/eslint-plugin": "^13.0.0",
2525
"@types/debug": "0.0.30",
2626
"@types/estree": "0.0.38",
2727
"@types/lodash": "^4.14.120",
2828
"@types/mocha": "^5.2.4",
2929
"@types/node": "^10.12.21",
30-
"@typescript-eslint/parser": "^2.31.0",
30+
"@typescript-eslint/parser": "^4.7.0",
3131
"babel-eslint": "^10.0.1",
3232
"chokidar": "^2.0.4",
3333
"codecov": "^3.1.0",
@@ -44,7 +44,7 @@
4444
"rollup-plugin-node-resolve": "^4.0.0",
4545
"rollup-plugin-sourcemaps": "^0.4.2",
4646
"ts-node": "^8.1.0",
47-
"typescript": "~3.4.4",
47+
"typescript": "~4.0.5",
4848
"wait-on": "^3.2.0",
4949
"warun": "^1.0.0"
5050
},
@@ -59,6 +59,7 @@
5959
"pretest": "run-s build lint",
6060
"test": "npm run -s test:mocha",
6161
"test:mocha": "nyc mocha \"test/*.js\" --reporter dot --timeout 10000",
62+
"test:debug": "mocha --inspect --require ts-node/register \"test/*.js\" --reporter dot --timeout 10000",
6263
"preupdate-fixtures": "npm run -s build",
6364
"update-fixtures": "node scripts/update-fixtures-ast.js && node scripts/update-fixtures-document-fragment.js",
6465
"preversion": "npm test",

src/ast/nodes.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ export interface ESLintImportDeclaration extends HasLocation, HasParent {
280280
specifiers: (
281281
| ESLintImportSpecifier
282282
| ESLintImportDefaultSpecifier
283-
| ESLintImportNamespaceSpecifier)[]
283+
| ESLintImportNamespaceSpecifier
284+
)[]
284285
source: ESLintLiteral
285286
}
286287

@@ -375,7 +376,8 @@ export interface ESLintObjectExpression extends HasLocation, HasParent {
375376
properties: (
376377
| ESLintProperty
377378
| ESLintSpreadElement
378-
| ESLintLegacySpreadProperty)[]
379+
| ESLintLegacySpreadProperty
380+
)[]
379381
}
380382

381383
export interface ESLintProperty extends HasLocation, HasParent {
@@ -570,7 +572,8 @@ export interface ESLintObjectPattern extends HasLocation, HasParent {
570572
properties: (
571573
| ESLintAssignmentProperty
572574
| ESLintRestElement
573-
| ESLintLegacyRestProperty)[]
575+
| ESLintLegacyRestProperty
576+
)[]
574577
}
575578

576579
export interface ESLintAssignmentProperty extends ESLintProperty {

src/common/location-calculator.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export class LocationCalculator {
3636
gapOffsets: number[],
3737
ltOffsets: number[],
3838
baseOffset?: number,
39-
shiftOffset: number = 0,
39+
shiftOffset = 0,
4040
) {
4141
this.gapOffsets = gapOffsets
4242
this.ltOffsets = ltOffsets
@@ -76,6 +76,15 @@ export class LocationCalculator {
7676
)
7777
}
7878

79+
/**
80+
* Calculate the location of the given index.
81+
* @param index The index to calculate their location.
82+
* @returns The location of the index.
83+
*/
84+
public getLocFromIndex(index: number): Location {
85+
return this._getLocation(index)
86+
}
87+
7988
/**
8089
* Calculate the location of the given offset.
8190
* @param offset The offset to calculate their location.

src/external/token-store/utils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ function getStartLocation(token: { range: number[] }): number {
2626
*/
2727
export function search(tokens: HasLocation[], location: number): number {
2828
return sortedIndexBy(
29-
tokens,
30-
{range: [location]},
31-
getStartLocation
29+
tokens as { range: number[] }[],
30+
{ range: [location] },
31+
getStartLocation,
3232
)
3333
}
3434

src/html/tokenizer.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ export class Tokenizer {
527527
"Invalid state: the provisional token was not found.",
528528
)
529529

530-
const token = this.provisionalToken as Token
530+
const token = this.provisionalToken
531531
this.provisionalToken = null
532532

533533
if (token.range[0] < token.range[1]) {
@@ -542,10 +542,10 @@ export class Tokenizer {
542542
assert(this.currentToken != null)
543543
assert(this.provisionalToken != null)
544544

545-
const token = this.currentToken as Token
545+
const token = this.currentToken
546546
debug("[html] rollback token: %d %s", token.range[0], token.type)
547547

548-
this.currentToken = this.provisionalToken as Token
548+
this.currentToken = this.provisionalToken
549549
this.provisionalToken = null
550550
}
551551

@@ -1808,7 +1808,7 @@ export class Tokenizer {
18081808

18091809
// The this.buffer.length is not new length since it includes surrogate pairs.
18101810
// Calculate new length.
1811-
const token = this.currentToken as Token
1811+
const token = this.currentToken
18121812
const len0 = token.value.length
18131813
for (const cp1 of this.buffer) {
18141814
this.appendTokenValue(cp1, null)

src/script/espree.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,20 @@ export interface ESLintCustomParser {
1515
parseForESLint?(code: string, options: any): ESLintCustomParserResult
1616
}
1717

18-
const createRequire: (filename: string) => (filename: string) => any =
18+
const createRequire: (filename: string) => (modname: string) => any =
1919
// Added in v12.2.0
2020
(Module as any).createRequire ||
2121
// Added in v10.12.0, but deprecated in v12.2.0.
22+
// eslint-disable-next-line @mysticatea/node/no-deprecated-api
2223
Module.createRequireFromPath ||
2324
// Polyfill - This is not executed on the tests on node@>=10.
2425
/* istanbul ignore next */
25-
(filename => {
26-
const mod = new Module(filename)
26+
(modname => {
27+
const mod = new Module(modname)
2728

28-
mod.filename = filename
29-
mod.paths = (Module as any)._nodeModulePaths(path.dirname(filename))
30-
;(mod as any)._compile("module.exports = require;", filename)
29+
mod.filename = modname
30+
mod.paths = (Module as any)._nodeModulePaths(path.dirname(modname))
31+
;(mod as any)._compile("module.exports = require;", modname)
3132
return mod.exports
3233
})
3334

src/script/index.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import {
3131
VForExpression,
3232
VOnExpression,
3333
VSlotScopeExpression,
34+
OffsetRange,
35+
LocationRange,
3436
} from "../ast"
3537
import { debug } from "../common/debug"
3638
import { LocationCalculator } from "../common/location-calculator"
@@ -66,7 +68,7 @@ function postprocess(
6668
): void {
6769
// There are cases which the same node instance appears twice in the tree.
6870
// E.g. `let {a} = {}` // This `a` appears twice at `Property#key` and `Property#value`.
69-
const traversed = new Set<Node | number[]>()
71+
const traversed = new Set<Node | number[] | LocationRange>()
7072

7173
traverseNodes(result.ast, {
7274
visitorKeys: result.visitorKeys,
@@ -78,9 +80,22 @@ function postprocess(
7880

7981
// `babel-eslint@8` has shared `Node#range` with multiple nodes.
8082
// See also: https://github.com/vuejs/eslint-plugin-vue/issues/208
81-
if (!traversed.has(node.range)) {
82-
traversed.add(node.range)
83+
if (traversed.has(node.range)) {
84+
if (!traversed.has(node.loc)) {
85+
// However, `Node#loc` may not be shared.
86+
// See also: https://github.com/vuejs/vue-eslint-parser/issues/84
87+
node.loc.start = locationCalculator.getLocFromIndex(
88+
node.range[0],
89+
)
90+
node.loc.end = locationCalculator.getLocFromIndex(
91+
node.range[1],
92+
)
93+
traversed.add(node.loc)
94+
}
95+
} else {
8396
locationCalculator.fixLocation(node)
97+
traversed.add(node.range)
98+
traversed.add(node.loc)
8499
}
85100
}
86101
},
@@ -139,7 +154,7 @@ function normalizeLeft(
139154
*/
140155
function getCommaTokenBeforeNode(tokens: Token[], node: Node): Token | null {
141156
let tokenIndex = sortedIndexBy(
142-
tokens,
157+
tokens as { range: OffsetRange }[],
143158
{ range: node.range },
144159
t => t.range[0],
145160
)
@@ -563,7 +578,6 @@ export function parseScript(
563578
require(parserOptions.parser)
564579
: getEspree()
565580
const result: any =
566-
// eslint-disable-next-line @mysticatea/ts/unbound-method
567581
typeof parser.parseForESLint === "function"
568582
? parser.parseForESLint(code, parserOptions)
569583
: parser.parse(code, parserOptions)

test/fixtures/ts-scope-manager.vue

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<template>
2+
<p>Hello World!</p>
3+
</template>
4+
5+
<script>
6+
import Vue from 'vue';
7+
// the error should be reported at line 8
8+
import Button from './Button.vue';
9+
10+
export default Vue.extend({});
11+
</script>

test/index.js

+23
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,29 @@ describe("Basic tests", () => {
340340
})
341341
})
342342

343+
describe("About fixtures/ts-scope-manager.vue", () => {
344+
it("should calculate the correct location with '@typescript-eslint/parser'", () => {
345+
const cli = new CLIEngine({
346+
cwd: FIXTURE_DIR,
347+
envs: ["es6", "node"],
348+
parser: PARSER_PATH,
349+
parserOptions: {
350+
parser: "@typescript-eslint/parser",
351+
},
352+
rules: { "no-unused-vars": ["error"] },
353+
useEslintrc: false,
354+
})
355+
const report = cli.executeOnFiles(["ts-scope-manager.vue"])
356+
const messages = report.results[0].messages
357+
358+
assert.strictEqual(messages.length, 1)
359+
assert.deepStrictEqual(messages[0].line, 8)
360+
assert.deepStrictEqual(messages[0].column, 8)
361+
assert.deepStrictEqual(messages[0].endLine, 8)
362+
assert.deepStrictEqual(messages[0].endColumn, 14)
363+
})
364+
})
365+
343366
describe("About fixtures/svg-attrs.vue", () => {
344367
it("parses attributes with colons", () => {
345368
const cli = new CLIEngine({

0 commit comments

Comments
 (0)