astro-eslint-parser 0.0.16 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -7
- package/lib/ast/astro.d.ts +49 -0
- package/lib/{ast.js → ast/astro.js} +0 -0
- package/lib/ast/base.d.ts +6 -0
- package/lib/ast/base.js +2 -0
- package/lib/ast/index.d.ts +8 -0
- package/lib/ast/index.js +18 -0
- package/lib/ast/jsx.d.ts +91 -0
- package/lib/ast/jsx.js +2 -0
- package/lib/astro/index.js +2 -4
- package/lib/astro-tools/index.d.ts +21 -0
- package/lib/astro-tools/index.js +26 -0
- package/lib/context/index.d.ts +13 -8
- package/lib/context/index.js +51 -100
- package/lib/context/parser-options.d.ts +8 -0
- package/lib/context/parser-options.js +71 -0
- package/lib/{parser → context/resolve-parser}/espree.d.ts +1 -1
- package/lib/{parser → context/resolve-parser}/espree.js +1 -1
- package/lib/context/resolve-parser/index.d.ts +5 -0
- package/lib/{parser/resolve-parser.js → context/resolve-parser/index.js} +0 -0
- package/lib/context/script.d.ts +1 -1
- package/lib/context/script.js +16 -18
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/parser/astro-parser/astrojs-compiler-service.d.ts +2 -4
- package/lib/parser/astro-parser/astrojs-compiler-service.js +3 -12
- package/lib/parser/astro-parser/astrojs-compiler-worker.d.ts +1 -0
- package/lib/parser/astro-parser/astrojs-compiler-worker.js +11 -0
- package/lib/parser/astro-parser/parse.js +11 -51
- package/lib/parser/index.d.ts +0 -17
- package/lib/parser/index.js +6 -31
- package/lib/parser/lru-cache.d.ts +7 -0
- package/lib/parser/lru-cache.js +32 -0
- package/lib/parser/process-template.js +87 -48
- package/lib/parser/script.d.ts +3 -2
- package/lib/parser/script.js +12 -11
- package/lib/parser/template.d.ts +10 -0
- package/lib/parser/template.js +102 -0
- package/lib/types.d.ts +21 -0
- package/lib/types.js +2 -0
- package/lib/visitor-keys.js +1 -2
- package/package.json +14 -11
- package/lib/ast.d.ts +0 -53
- package/lib/parser/astro-parser/wasm_exec.d.ts +0 -35
- package/lib/parser/astro-parser/wasm_exec.js +0 -470
- package/lib/parser/resolve-parser.d.ts +0 -16
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# astro-eslint-parser
|
|
2
2
|
|
|
3
|
-
[Astro] parser for [ESLint].
|
|
3
|
+
[Astro] component parser for [ESLint].
|
|
4
4
|
You can check it on [Online DEMO](https://ota-meshi.github.io/astro-eslint-parser/playground).
|
|
5
5
|
|
|
6
|
+
[](https://github.com/sponsors/ota-meshi)
|
|
7
|
+
|
|
6
8
|
[](https://www.npmjs.com/package/astro-eslint-parser)
|
|
7
9
|
[](https://www.npmjs.com/package/astro-eslint-parser)
|
|
8
10
|
[](http://www.npmtrends.com/astro-eslint-parser)
|
|
@@ -17,8 +19,6 @@ This parser is in the ***experimental stages*** of development.
|
|
|
17
19
|
|
|
18
20
|
At least it works fine with a [fork of the `astro.build` repository](https://github.com/ota-meshi/astro.build/tree/eslint).
|
|
19
21
|
|
|
20
|
-
⚠ Currently this parser relies heavily on the internal API of [@astrojs/compiler]. It may stop working in a future update of [@astrojs/compiler]. ⚠
|
|
21
|
-
|
|
22
22
|
[@astrojs/compiler]: https://github.com/withastro/compiler
|
|
23
23
|
|
|
24
24
|
<!--
|
|
@@ -26,7 +26,7 @@ At least it works fine with a [fork of the `astro.build` repository](https://git
|
|
|
26
26
|
|
|
27
27
|
#### [@ota-meshi/eslint-plugin-astro](https://ota-meshi.github.io/eslint-plugin-astro/)
|
|
28
28
|
|
|
29
|
-
ESLint plugin for Astro.
|
|
29
|
+
ESLint plugin for Astro component.
|
|
30
30
|
It provides many unique check rules by using the template AST.
|
|
31
31
|
-->
|
|
32
32
|
|
|
@@ -143,17 +143,16 @@ Example **.vscode/settings.json**:
|
|
|
143
143
|
}
|
|
144
144
|
```
|
|
145
145
|
|
|
146
|
-
## Compatibility With Existing ESLint Rules
|
|
146
|
+
## :handshake: Compatibility With Existing ESLint Rules
|
|
147
147
|
|
|
148
148
|
Most of the rules in the ESLint core work for the script part, but some rules are incompatible.
|
|
149
149
|
This parser will generate a JSX compatible AST for most of the HTML part of the Astro component. Therefore, some rules of [eslint-plugin-react] may work.
|
|
150
150
|
For example, the [react/jsx-no-target-blank] rule works fine.
|
|
151
151
|
|
|
152
|
-
[semi]: https://eslint.org/docs/rules/semi
|
|
153
152
|
[eslint-plugin-react]: https://github.com/jsx-eslint/eslint-plugin-react/
|
|
154
153
|
[react/jsx-no-target-blank]: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/jsx-no-target-blank.md
|
|
155
154
|
|
|
156
|
-
## Usage for Custom Rules / Plugins
|
|
155
|
+
## :hammer_and_wrench: Usage for Custom Rules / Plugins
|
|
157
156
|
|
|
158
157
|
- TBA
|
|
159
158
|
- You can check the AST in the [Online DEMO](https://ota-meshi.github.io/astro-eslint-parser/). However, AST is subject to major changes in the future.
|
|
@@ -167,6 +166,12 @@ Welcome contributing!
|
|
|
167
166
|
|
|
168
167
|
Please use GitHub's Issues/PRs.
|
|
169
168
|
|
|
169
|
+
## :heart: Supporting
|
|
170
|
+
|
|
171
|
+
If you are willing to see that this package continues to be maintained, please consider sponsoring me.
|
|
172
|
+
|
|
173
|
+
[](https://github.com/sponsors/ota-meshi)
|
|
174
|
+
|
|
170
175
|
## :lock: License
|
|
171
176
|
|
|
172
177
|
See the [LICENSE](LICENSE) file for license rights and limitations (MIT).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { JSXAttribute, JSXElement, JSXExpression, JSXExpressionContainer, JSXFragment, JSXText } from "./jsx";
|
|
2
|
+
import type { TSESTree as ES } from "@typescript-eslint/types";
|
|
3
|
+
import type { BaseNode } from "./base";
|
|
4
|
+
export declare type AstroNode = AstroProgram | AstroFragment | AstroHTMLComment | AstroDoctype | AstroShorthandAttribute | AstroTemplateLiteralAttribute | AstroRawText;
|
|
5
|
+
export declare type AstroChild = JSXElement | JSXFragment | JSXExpression | JSXText | AstroHTMLComment;
|
|
6
|
+
export declare type AstroParentNode = JSXElement | JSXFragment | AstroFragment;
|
|
7
|
+
/** Node of Astro program root */
|
|
8
|
+
export interface AstroProgram extends Omit<ES.Program, "type" | "body"> {
|
|
9
|
+
type: "Program";
|
|
10
|
+
body: (ES.Program["body"][number] | AstroFragment)[];
|
|
11
|
+
sourceType: "script" | "module";
|
|
12
|
+
comments: ES.Comment[];
|
|
13
|
+
tokens: ES.Token[];
|
|
14
|
+
parent?: undefined;
|
|
15
|
+
}
|
|
16
|
+
/** Node of Astro fragment */
|
|
17
|
+
export interface AstroFragment extends BaseNode {
|
|
18
|
+
type: "AstroFragment";
|
|
19
|
+
children: AstroChild[];
|
|
20
|
+
parent?: AstroParentNode;
|
|
21
|
+
}
|
|
22
|
+
/** Node of Astro html comment */
|
|
23
|
+
export interface AstroHTMLComment extends BaseNode {
|
|
24
|
+
type: "AstroHTMLComment";
|
|
25
|
+
value: string;
|
|
26
|
+
parent?: AstroParentNode;
|
|
27
|
+
}
|
|
28
|
+
/** Node of Astro doctype */
|
|
29
|
+
export interface AstroDoctype extends BaseNode {
|
|
30
|
+
type: "AstroDoctype";
|
|
31
|
+
parent?: AstroFragment;
|
|
32
|
+
}
|
|
33
|
+
/** Node of Astro shorthand attribute */
|
|
34
|
+
export interface AstroShorthandAttribute extends Omit<JSXAttribute, "type"> {
|
|
35
|
+
type: "AstroShorthandAttribute";
|
|
36
|
+
value: JSXExpressionContainer;
|
|
37
|
+
}
|
|
38
|
+
/** Node of Astro template-literal attribute */
|
|
39
|
+
export interface AstroTemplateLiteralAttribute extends Omit<JSXAttribute, "type"> {
|
|
40
|
+
type: "AstroTemplateLiteralAttribute";
|
|
41
|
+
value: JSXExpressionContainer & {
|
|
42
|
+
expression: ES.TemplateLiteral;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** Node of Astro raw text */
|
|
46
|
+
export interface AstroRawText extends Omit<JSXText, "type"> {
|
|
47
|
+
type: "AstroRawText";
|
|
48
|
+
parent?: JSXElement;
|
|
49
|
+
}
|
|
File without changes
|
package/lib/ast/base.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from "./astro";
|
|
2
|
+
export * from "./jsx";
|
|
3
|
+
import type { TSESTree } from "@typescript-eslint/types";
|
|
4
|
+
export declare type Comment = TSESTree.Comment;
|
|
5
|
+
export declare type Token = TSESTree.Token;
|
|
6
|
+
export declare type SourceLocation = TSESTree.SourceLocation;
|
|
7
|
+
export declare type Range = TSESTree.Range;
|
|
8
|
+
export declare type Position = TSESTree.Position;
|
package/lib/ast/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./astro"), exports);
|
|
18
|
+
__exportStar(require("./jsx"), exports);
|
package/lib/ast/jsx.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { TSESTree as ES } from "@typescript-eslint/types";
|
|
2
|
+
import type { AstroFragment, AstroHTMLComment, AstroShorthandAttribute, AstroTemplateLiteralAttribute } from "./astro";
|
|
3
|
+
import type { BaseNode } from "./base";
|
|
4
|
+
export declare type JSXNode = JSXAttribute | JSXClosingElement | JSXClosingFragment | JSXElement | JSXEmptyExpression | JSXExpressionContainer | JSXFragment | JSXIdentifier | JSXMemberExpression | JSXNamespacedName | JSXOpeningElement | JSXOpeningFragment | JSXSpreadAttribute | JSXSpreadChild | JSXText;
|
|
5
|
+
export declare type JSXChild = JSXElement | JSXFragment | JSXExpression | JSXText | AstroHTMLComment;
|
|
6
|
+
export declare type JSXParentNode = JSXElement | JSXFragment | AstroFragment;
|
|
7
|
+
export interface JSXElement extends BaseNode {
|
|
8
|
+
type: "JSXElement";
|
|
9
|
+
openingElement: JSXOpeningElement;
|
|
10
|
+
closingElement: JSXClosingElement | null;
|
|
11
|
+
children: JSXChild[];
|
|
12
|
+
parent?: JSXParentNode;
|
|
13
|
+
}
|
|
14
|
+
export interface JSXFragment extends BaseNode {
|
|
15
|
+
type: "JSXFragment";
|
|
16
|
+
openingFragment: JSXOpeningFragment;
|
|
17
|
+
closingFragment: JSXClosingFragment;
|
|
18
|
+
children: JSXChild[];
|
|
19
|
+
parent?: JSXParentNode;
|
|
20
|
+
}
|
|
21
|
+
export interface JSXOpeningElement extends BaseNode {
|
|
22
|
+
type: "JSXOpeningElement";
|
|
23
|
+
typeParameters?: ES.TSTypeParameterInstantiation;
|
|
24
|
+
selfClosing: boolean;
|
|
25
|
+
name: JSXTagNameExpression;
|
|
26
|
+
attributes: (JSXAttribute | JSXSpreadAttribute | AstroShorthandAttribute | AstroTemplateLiteralAttribute)[];
|
|
27
|
+
parent?: JSXElement;
|
|
28
|
+
}
|
|
29
|
+
export interface JSXClosingElement extends BaseNode {
|
|
30
|
+
type: "JSXClosingElement";
|
|
31
|
+
name: JSXTagNameExpression;
|
|
32
|
+
parent?: JSXElement;
|
|
33
|
+
}
|
|
34
|
+
export interface JSXClosingFragment extends BaseNode {
|
|
35
|
+
type: "JSXClosingFragment";
|
|
36
|
+
parent?: JSXFragment;
|
|
37
|
+
}
|
|
38
|
+
export interface JSXOpeningFragment extends BaseNode {
|
|
39
|
+
type: "JSXOpeningFragment";
|
|
40
|
+
parent?: JSXFragment;
|
|
41
|
+
}
|
|
42
|
+
export interface JSXAttribute extends BaseNode {
|
|
43
|
+
type: "JSXAttribute";
|
|
44
|
+
name: JSXIdentifier | JSXNamespacedName;
|
|
45
|
+
value: JSXExpression | ES.Literal | null;
|
|
46
|
+
parent?: JSXOpeningElement;
|
|
47
|
+
}
|
|
48
|
+
export interface JSXSpreadAttribute extends BaseNode {
|
|
49
|
+
type: "JSXSpreadAttribute";
|
|
50
|
+
argument: ES.Expression;
|
|
51
|
+
parent?: JSXOpeningElement;
|
|
52
|
+
}
|
|
53
|
+
export declare type JSXTagNameExpression = JSXIdentifier | JSXMemberExpression | JSXNamespacedName;
|
|
54
|
+
export interface JSXIdentifier extends BaseNode {
|
|
55
|
+
type: "JSXIdentifier";
|
|
56
|
+
name: string;
|
|
57
|
+
parent?: JSXAttribute | AstroShorthandAttribute | AstroTemplateLiteralAttribute | JSXMemberExpression | JSXNamespacedName | JSXOpeningElement | JSXClosingElement;
|
|
58
|
+
}
|
|
59
|
+
export interface JSXMemberExpression extends BaseNode {
|
|
60
|
+
type: "JSXMemberExpression";
|
|
61
|
+
object: JSXTagNameExpression;
|
|
62
|
+
property: JSXIdentifier;
|
|
63
|
+
parent?: JSXMemberExpression | JSXOpeningElement | JSXClosingElement;
|
|
64
|
+
}
|
|
65
|
+
export interface JSXNamespacedName extends BaseNode {
|
|
66
|
+
type: "JSXNamespacedName";
|
|
67
|
+
namespace: JSXIdentifier;
|
|
68
|
+
name: JSXIdentifier;
|
|
69
|
+
parent?: JSXAttribute | AstroShorthandAttribute | AstroTemplateLiteralAttribute | JSXMemberExpression | JSXOpeningElement | JSXClosingElement;
|
|
70
|
+
}
|
|
71
|
+
export declare type JSXExpression = JSXExpressionContainer | JSXSpreadChild;
|
|
72
|
+
export interface JSXExpressionContainer extends BaseNode {
|
|
73
|
+
type: "JSXExpressionContainer";
|
|
74
|
+
expression: ES.Expression | JSXEmptyExpression;
|
|
75
|
+
parent?: JSXAttribute | AstroShorthandAttribute | AstroTemplateLiteralAttribute | JSXParentNode;
|
|
76
|
+
}
|
|
77
|
+
export interface JSXSpreadChild extends BaseNode {
|
|
78
|
+
type: "JSXSpreadChild";
|
|
79
|
+
expression: ES.Expression;
|
|
80
|
+
parent?: JSXAttribute | JSXParentNode;
|
|
81
|
+
}
|
|
82
|
+
export interface JSXEmptyExpression extends BaseNode {
|
|
83
|
+
type: "JSXEmptyExpression";
|
|
84
|
+
parent?: JSXExpressionContainer;
|
|
85
|
+
}
|
|
86
|
+
export interface JSXText extends BaseNode {
|
|
87
|
+
type: "JSXText";
|
|
88
|
+
value: string;
|
|
89
|
+
raw: string;
|
|
90
|
+
parent?: JSXParentNode;
|
|
91
|
+
}
|
package/lib/ast/jsx.js
ADDED
package/lib/astro/index.js
CHANGED
|
@@ -116,8 +116,7 @@ exports.calcAttributeValueStartOffset = calcAttributeValueStartOffset;
|
|
|
116
116
|
* Get end offset of tag
|
|
117
117
|
*/
|
|
118
118
|
function getEndOffset(node, ctx) {
|
|
119
|
-
|
|
120
|
-
if (((_a = node.position.end) === null || _a === void 0 ? void 0 : _a.offset) != null) {
|
|
119
|
+
if (node.position.end?.offset != null) {
|
|
121
120
|
return node.position.end.offset;
|
|
122
121
|
}
|
|
123
122
|
if (isTag(node))
|
|
@@ -323,8 +322,7 @@ exports.skipSpaces = skipSpaces;
|
|
|
323
322
|
* Get children
|
|
324
323
|
*/
|
|
325
324
|
function getSortedChildren(parent, code) {
|
|
326
|
-
|
|
327
|
-
if (parent.type === "root" && ((_a = parent.children[0]) === null || _a === void 0 ? void 0 : _a.type) === "frontmatter") {
|
|
325
|
+
if (parent.type === "root" && parent.children[0]?.type === "frontmatter") {
|
|
328
326
|
// The order of comments and frontmatter may be changed.
|
|
329
327
|
const children = [...parent.children];
|
|
330
328
|
if (children.every((n) => n.position)) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ParseResult } from "@astrojs/compiler";
|
|
2
|
+
import type { AttributeNode, Node, ParentNode } from "@astrojs/compiler/types";
|
|
3
|
+
export interface ParseTemplateResult {
|
|
4
|
+
result: ParseResult;
|
|
5
|
+
getEndOffset: (node: Node) => number;
|
|
6
|
+
calcAttributeValueStartOffset: (node: AttributeNode) => number;
|
|
7
|
+
calcAttributeEndOffset: (node: AttributeNode) => number;
|
|
8
|
+
walk: (parent: ParentNode, enter: (n: Node | AttributeNode, parents: ParentNode[]) => void, leave?: (n: Node | AttributeNode, parents: ParentNode[]) => void) => void;
|
|
9
|
+
getLocFromIndex: (index: number) => {
|
|
10
|
+
line: number;
|
|
11
|
+
column: number;
|
|
12
|
+
};
|
|
13
|
+
getIndexFromLoc: (loc: {
|
|
14
|
+
line: number;
|
|
15
|
+
column: number;
|
|
16
|
+
}) => number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse the astro component template.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseTemplate(code: string): ParseTemplateResult;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseTemplate = void 0;
|
|
4
|
+
const template_1 = require("../parser/template");
|
|
5
|
+
const astro_1 = require("../astro");
|
|
6
|
+
/**
|
|
7
|
+
* Parse the astro component template.
|
|
8
|
+
*/
|
|
9
|
+
function parseTemplate(code) {
|
|
10
|
+
const parsed = (0, template_1.parseTemplate)(code);
|
|
11
|
+
return {
|
|
12
|
+
result: parsed.result,
|
|
13
|
+
getEndOffset: (node) => (0, astro_1.getEndOffset)(node, parsed.context),
|
|
14
|
+
calcAttributeValueStartOffset: (node) => (0, astro_1.calcAttributeValueStartOffset)(node, parsed.context),
|
|
15
|
+
calcAttributeEndOffset: (node) => (0, astro_1.calcAttributeEndOffset)(node, parsed.context),
|
|
16
|
+
walk(parent, enter, leave) {
|
|
17
|
+
(0, astro_1.walk)(parent, code, enter, leave ||
|
|
18
|
+
(() => {
|
|
19
|
+
/* noop */
|
|
20
|
+
}));
|
|
21
|
+
},
|
|
22
|
+
getLocFromIndex: (index) => parsed.context.getLocFromIndex(index),
|
|
23
|
+
getIndexFromLoc: (loc) => parsed.context.locs.getIndexFromLoc(loc),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.parseTemplate = parseTemplate;
|
package/lib/context/index.d.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { TSESTree } from "@typescript-eslint/types";
|
|
2
|
-
import type { ESLintExtendedProgram } from "../parser";
|
|
3
2
|
declare type RangeAndLoc = {
|
|
4
3
|
range: TSESTree.Range;
|
|
5
4
|
loc: TSESTree.SourceLocation;
|
|
6
5
|
};
|
|
7
6
|
export declare class Context {
|
|
8
7
|
readonly code: string;
|
|
9
|
-
readonly parserOptions: any;
|
|
10
8
|
readonly locs: LinesAndColumns;
|
|
11
9
|
private readonly locsMap;
|
|
12
10
|
private readonly state;
|
|
13
|
-
constructor(code: string
|
|
11
|
+
constructor(code: string);
|
|
14
12
|
getLocFromIndex(index: number): {
|
|
15
13
|
line: number;
|
|
16
14
|
column: number;
|
|
@@ -27,15 +25,12 @@ export declare class Context {
|
|
|
27
25
|
* get text
|
|
28
26
|
*/
|
|
29
27
|
getText(range: TSESTree.Range): string;
|
|
30
|
-
isTypeScript(): boolean;
|
|
31
|
-
remapCR({ ast, visitorKeys }: ESLintExtendedProgram): void;
|
|
32
28
|
get originalAST(): any;
|
|
33
29
|
set originalAST(originalAST: any);
|
|
34
30
|
}
|
|
35
31
|
export declare class LinesAndColumns {
|
|
36
|
-
readonly code: string;
|
|
37
|
-
private readonly crs;
|
|
38
32
|
private readonly lineStartIndices;
|
|
33
|
+
private readonly normalizedLineFeed;
|
|
39
34
|
constructor(origCode: string);
|
|
40
35
|
getLocFromIndex(index: number): {
|
|
41
36
|
line: number;
|
|
@@ -45,6 +40,16 @@ export declare class LinesAndColumns {
|
|
|
45
40
|
line: number;
|
|
46
41
|
column: number;
|
|
47
42
|
}): number;
|
|
48
|
-
|
|
43
|
+
getNormalizedLineFeed(): NormalizedLineFeed;
|
|
44
|
+
}
|
|
45
|
+
export declare class NormalizedLineFeed {
|
|
46
|
+
readonly code: string;
|
|
47
|
+
private readonly offsets;
|
|
48
|
+
get needRemap(): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Remap index
|
|
51
|
+
*/
|
|
52
|
+
readonly remapIndex: (index: number) => number;
|
|
53
|
+
constructor(code: string, offsets: number[]);
|
|
49
54
|
}
|
|
50
55
|
export {};
|
package/lib/context/index.js
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.LinesAndColumns = exports.Context = void 0;
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const resolve_parser_1 = require("../parser/resolve-parser");
|
|
10
|
-
const traverse_1 = require("../traverse");
|
|
3
|
+
exports.NormalizedLineFeed = exports.LinesAndColumns = exports.Context = void 0;
|
|
11
4
|
class Context {
|
|
12
|
-
constructor(code
|
|
5
|
+
constructor(code) {
|
|
13
6
|
this.locsMap = new Map();
|
|
14
7
|
this.state = {};
|
|
15
8
|
this.locs = new LinesAndColumns(code);
|
|
16
|
-
this.code =
|
|
17
|
-
this.parserOptions = parserOptions;
|
|
9
|
+
this.code = code;
|
|
18
10
|
}
|
|
19
11
|
getLocFromIndex(index) {
|
|
20
12
|
let loc = this.locsMap.get(index);
|
|
@@ -43,7 +35,11 @@ class Context {
|
|
|
43
35
|
* Build token
|
|
44
36
|
*/
|
|
45
37
|
buildToken(type, range) {
|
|
46
|
-
return
|
|
38
|
+
return {
|
|
39
|
+
type,
|
|
40
|
+
value: this.getText(range),
|
|
41
|
+
...this.getLocations(...range),
|
|
42
|
+
};
|
|
47
43
|
}
|
|
48
44
|
/**
|
|
49
45
|
* get text
|
|
@@ -51,84 +47,6 @@ class Context {
|
|
|
51
47
|
getText(range) {
|
|
52
48
|
return this.code.slice(range[0], range[1]);
|
|
53
49
|
}
|
|
54
|
-
isTypeScript() {
|
|
55
|
-
var _a, _b;
|
|
56
|
-
if (this.state.isTypeScript != null) {
|
|
57
|
-
return this.state.isTypeScript;
|
|
58
|
-
}
|
|
59
|
-
const parserName = (0, resolve_parser_1.getParserName)({}, (_a = this.parserOptions) === null || _a === void 0 ? void 0 : _a.parser);
|
|
60
|
-
if (parserName === "@typescript-eslint/parser") {
|
|
61
|
-
return (this.state.isTypeScript = true);
|
|
62
|
-
}
|
|
63
|
-
if (parserName.includes("@typescript-eslint/parser")) {
|
|
64
|
-
let targetPath = parserName;
|
|
65
|
-
while (targetPath) {
|
|
66
|
-
const pkgPath = path_1.default.join(targetPath, "package.json");
|
|
67
|
-
if (fs_1.default.existsSync(pkgPath)) {
|
|
68
|
-
try {
|
|
69
|
-
return (this.state.isTypeScript =
|
|
70
|
-
((_b = JSON.parse(fs_1.default.readFileSync(pkgPath, "utf-8"))) === null || _b === void 0 ? void 0 : _b.name) === "@typescript-eslint/parser");
|
|
71
|
-
}
|
|
72
|
-
catch (_c) {
|
|
73
|
-
return (this.state.isTypeScript = false);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
const parent = path_1.default.dirname(targetPath);
|
|
77
|
-
if (targetPath === parent) {
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
targetPath = parent;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return (this.state.isTypeScript = false);
|
|
84
|
-
}
|
|
85
|
-
remapCR({ ast, visitorKeys }) {
|
|
86
|
-
const crs = this.locs.getCRs();
|
|
87
|
-
if (!crs.length) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const cache = {};
|
|
91
|
-
/**
|
|
92
|
-
* Remap index
|
|
93
|
-
*/
|
|
94
|
-
function remapIndex(index) {
|
|
95
|
-
let result = cache[index];
|
|
96
|
-
if (result != null) {
|
|
97
|
-
return result;
|
|
98
|
-
}
|
|
99
|
-
result = index;
|
|
100
|
-
for (const cr of crs) {
|
|
101
|
-
if (cr < result) {
|
|
102
|
-
result++;
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return (cache[index] = result);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Remap range
|
|
112
|
-
*/
|
|
113
|
-
function remapRange(range) {
|
|
114
|
-
return [remapIndex(range[0]), remapIndex(range[1])];
|
|
115
|
-
}
|
|
116
|
-
(0, traverse_1.traverseNodes)(ast, {
|
|
117
|
-
visitorKeys,
|
|
118
|
-
enterNode(node) {
|
|
119
|
-
node.range = remapRange(node.range);
|
|
120
|
-
},
|
|
121
|
-
leaveNode() {
|
|
122
|
-
// ignore
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
for (const token of ast.tokens || []) {
|
|
126
|
-
token.range = remapRange(token.range);
|
|
127
|
-
}
|
|
128
|
-
for (const comment of ast.comments || []) {
|
|
129
|
-
comment.range = remapRange(comment.range);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
50
|
get originalAST() {
|
|
133
51
|
return this.state.originalAST;
|
|
134
52
|
}
|
|
@@ -142,30 +60,31 @@ class LinesAndColumns {
|
|
|
142
60
|
const len = origCode.length;
|
|
143
61
|
const lineStartIndices = [0];
|
|
144
62
|
const crs = [];
|
|
145
|
-
let
|
|
63
|
+
let normalizedCode = "";
|
|
146
64
|
for (let index = 0; index < len;) {
|
|
147
65
|
const c = origCode[index++];
|
|
148
66
|
if (c === "\r") {
|
|
149
67
|
const next = origCode[index++] || "";
|
|
150
68
|
if (next === "\n") {
|
|
151
|
-
|
|
69
|
+
normalizedCode += next;
|
|
152
70
|
crs.push(index - 2);
|
|
71
|
+
lineStartIndices.push(index);
|
|
153
72
|
}
|
|
154
73
|
else {
|
|
155
|
-
|
|
74
|
+
normalizedCode += `\n${next}`;
|
|
75
|
+
lineStartIndices.push(index - 1);
|
|
156
76
|
}
|
|
157
|
-
lineStartIndices.push(code.length);
|
|
158
77
|
}
|
|
159
78
|
else {
|
|
160
|
-
|
|
79
|
+
normalizedCode += c;
|
|
161
80
|
if (c === "\n") {
|
|
162
|
-
lineStartIndices.push(
|
|
81
|
+
lineStartIndices.push(index);
|
|
163
82
|
}
|
|
164
83
|
}
|
|
165
84
|
}
|
|
166
85
|
this.lineStartIndices = lineStartIndices;
|
|
167
|
-
|
|
168
|
-
this.
|
|
86
|
+
//
|
|
87
|
+
this.normalizedLineFeed = new NormalizedLineFeed(normalizedCode, crs);
|
|
169
88
|
}
|
|
170
89
|
getLocFromIndex(index) {
|
|
171
90
|
const lineNumber = sortedLastIndex(this.lineStartIndices, index);
|
|
@@ -179,11 +98,43 @@ class LinesAndColumns {
|
|
|
179
98
|
const positionIndex = lineStartIndex + loc.column;
|
|
180
99
|
return positionIndex;
|
|
181
100
|
}
|
|
182
|
-
|
|
183
|
-
return this.
|
|
101
|
+
getNormalizedLineFeed() {
|
|
102
|
+
return this.normalizedLineFeed;
|
|
184
103
|
}
|
|
185
104
|
}
|
|
186
105
|
exports.LinesAndColumns = LinesAndColumns;
|
|
106
|
+
class NormalizedLineFeed {
|
|
107
|
+
constructor(code, offsets) {
|
|
108
|
+
this.code = code;
|
|
109
|
+
this.offsets = offsets;
|
|
110
|
+
if (offsets.length) {
|
|
111
|
+
const cache = {};
|
|
112
|
+
this.remapIndex = (index) => {
|
|
113
|
+
let result = cache[index];
|
|
114
|
+
if (result != null) {
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
result = index;
|
|
118
|
+
for (const offset of offsets) {
|
|
119
|
+
if (offset < result) {
|
|
120
|
+
result++;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return (cache[index] = result);
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
this.remapIndex = (i) => i;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
get needRemap() {
|
|
134
|
+
return this.offsets.length > 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
exports.NormalizedLineFeed = NormalizedLineFeed;
|
|
187
138
|
/**
|
|
188
139
|
* Uses a binary search to determine the highest index at which value should be inserted into array in order to maintain its sort order.
|
|
189
140
|
*/
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ParserOptionsContext = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const resolve_parser_1 = require("./resolve-parser");
|
|
10
|
+
class ParserOptionsContext {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.state = {};
|
|
13
|
+
const parserOptions = {
|
|
14
|
+
ecmaVersion: 2020,
|
|
15
|
+
sourceType: "module",
|
|
16
|
+
loc: true,
|
|
17
|
+
range: true,
|
|
18
|
+
raw: true,
|
|
19
|
+
tokens: true,
|
|
20
|
+
comment: true,
|
|
21
|
+
eslintVisitorKeys: true,
|
|
22
|
+
eslintScopeManager: true,
|
|
23
|
+
...(options || {}),
|
|
24
|
+
};
|
|
25
|
+
parserOptions.ecmaFeatures = {
|
|
26
|
+
...(parserOptions.ecmaFeatures || {}),
|
|
27
|
+
jsx: true,
|
|
28
|
+
};
|
|
29
|
+
parserOptions.sourceType = "module";
|
|
30
|
+
if (parserOptions.ecmaVersion <= 5 ||
|
|
31
|
+
parserOptions.ecmaVersion == null) {
|
|
32
|
+
parserOptions.ecmaVersion = 2015;
|
|
33
|
+
}
|
|
34
|
+
this.parserOptions = parserOptions;
|
|
35
|
+
}
|
|
36
|
+
getParser() {
|
|
37
|
+
return (0, resolve_parser_1.getParser)({}, this.parserOptions.parser);
|
|
38
|
+
}
|
|
39
|
+
isTypeScript() {
|
|
40
|
+
if (this.state.isTypeScript != null) {
|
|
41
|
+
return this.state.isTypeScript;
|
|
42
|
+
}
|
|
43
|
+
const parserName = (0, resolve_parser_1.getParserName)({}, this.parserOptions?.parser);
|
|
44
|
+
if (parserName === "@typescript-eslint/parser") {
|
|
45
|
+
return (this.state.isTypeScript = true);
|
|
46
|
+
}
|
|
47
|
+
if (parserName.includes("@typescript-eslint/parser")) {
|
|
48
|
+
let targetPath = parserName;
|
|
49
|
+
while (targetPath) {
|
|
50
|
+
const pkgPath = path_1.default.join(targetPath, "package.json");
|
|
51
|
+
if (fs_1.default.existsSync(pkgPath)) {
|
|
52
|
+
try {
|
|
53
|
+
return (this.state.isTypeScript =
|
|
54
|
+
JSON.parse(fs_1.default.readFileSync(pkgPath, "utf-8"))
|
|
55
|
+
?.name === "@typescript-eslint/parser");
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return (this.state.isTypeScript = false);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const parent = path_1.default.dirname(targetPath);
|
|
62
|
+
if (targetPath === parent) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
targetPath = parent;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return (this.state.isTypeScript = false);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.ParserOptionsContext = ParserOptionsContext;
|