Skip to content

Commit d31e2fa

Browse files
committed
fix
1 parent da6ce38 commit d31e2fa

File tree

15 files changed

+331
-2912
lines changed

15 files changed

+331
-2912
lines changed

src/context/index.ts

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import fs from "fs";
2-
import path from "path";
31
import type {
42
Comment,
53
Locations,
@@ -15,19 +13,13 @@ import type ESTree from "estree";
1513
import type * as SvAST from "../parser/svelte-ast-types";
1614
import { ScriptLetContext } from "./script-let";
1715
import { LetDirectiveCollections } from "./let-directive-collection";
18-
import { getParserForLang } from "../parser/resolve-parser";
1916
import type { AttributeToken } from "../parser/html";
2017
import { parseAttributes } from "../parser/html";
21-
import {
22-
isTSESLintParserObject,
23-
maybeTSESLintParserObject,
24-
} from "../parser/parser-object";
2518
import { sortedLastIndex } from "../utils";
26-
27-
const TS_PARSER_NAMES = [
28-
"@typescript-eslint/parser",
29-
"typescript-eslint-parser-for-extra-files",
30-
];
19+
import {
20+
isTypeScript,
21+
type NormalizedParserOptions,
22+
} from "../parser/parser-options";
3123

3224
export class ScriptsSourceCode {
3325
private raw: string;
@@ -116,7 +108,7 @@ export type ContextSourceCode = {
116108
export class Context {
117109
public readonly code: string;
118110

119-
public readonly parserOptions: any;
111+
public readonly parserOptions: NormalizedParserOptions;
120112

121113
// ----- Source Code ------
122114
public readonly sourceCode: ContextSourceCode;
@@ -155,7 +147,7 @@ export class Context {
155147

156148
private readonly blocks: Block[] = [];
157149

158-
public constructor(code: string, parserOptions: any) {
150+
public constructor(code: string, parserOptions: NormalizedParserOptions) {
159151
this.code = code;
160152
this.parserOptions = parserOptions;
161153
this.locs = new LinesAndColumns(code);
@@ -287,44 +279,7 @@ export class Context {
287279
return this.state.isTypeScript;
288280
}
289281
const lang = this.sourceCode.scripts.attrs.lang;
290-
if (!lang) {
291-
return (this.state.isTypeScript = false);
292-
}
293-
const parserValue = getParserForLang(
294-
this.sourceCode.scripts.attrs,
295-
this.parserOptions?.parser,
296-
);
297-
if (typeof parserValue !== "string") {
298-
return (this.state.isTypeScript =
299-
maybeTSESLintParserObject(parserValue) ||
300-
isTSESLintParserObject(parserValue));
301-
}
302-
const parserName = parserValue;
303-
if (TS_PARSER_NAMES.includes(parserName)) {
304-
return (this.state.isTypeScript = true);
305-
}
306-
if (TS_PARSER_NAMES.some((nm) => parserName.includes(nm))) {
307-
let targetPath = parserName;
308-
while (targetPath) {
309-
const pkgPath = path.join(targetPath, "package.json");
310-
if (fs.existsSync(pkgPath)) {
311-
try {
312-
return (this.state.isTypeScript = TS_PARSER_NAMES.includes(
313-
JSON.parse(fs.readFileSync(pkgPath, "utf-8"))?.name,
314-
));
315-
} catch {
316-
return (this.state.isTypeScript = false);
317-
}
318-
}
319-
const parent = path.dirname(targetPath);
320-
if (targetPath === parent) {
321-
break;
322-
}
323-
targetPath = parent;
324-
}
325-
}
326-
327-
return (this.state.isTypeScript = false);
282+
return (this.state.isTypeScript = isTypeScript(this.parserOptions, lang));
328283
}
329284

330285
public stripScriptCode(start: number, end: number): void {

src/parser/analyze-scope.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ import { getFallbackKeys } from "../traverse";
55
import type { SvelteReactiveStatement, SvelteScriptElement } from "../ast";
66
import { addReference, addVariable } from "../scope";
77
import { addElementToSortedArray } from "../utils";
8+
import type { NormalizedParserOptions } from "./parser-options";
89
/**
910
* Analyze scope
1011
*/
1112
export function analyzeScope(
1213
node: ESTree.Node,
13-
parserOptions: any = {},
14+
parserOptions: NormalizedParserOptions,
1415
): ScopeManager {
1516
const ecmaVersion = parserOptions.ecmaVersion || 2020;
1617
const ecmaFeatures = parserOptions.ecmaFeatures || {};

src/parser/globals.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
import { svelteVersion } from "./svelte-version";
22

3-
const globalsForSvelte4: Readonly<string[]> = [
4-
"$$slots",
5-
"$$props",
6-
"$$restProps",
7-
] as const;
3+
const globalsForSvelte4 = ["$$slots", "$$props", "$$restProps"] as const;
84
export const globalsForRunes = [
95
"$state",
106
"$derived",

src/parser/index.ts

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
analyzeStoreScope,
2121
} from "./analyze-scope";
2222
import { ParseError } from "../errors";
23-
import { parseTypeScript } from "./typescript";
23+
import { parseTypeScript, parseTypeScriptInSvelte } from "./typescript";
2424
import { addReference } from "../scope";
2525
import {
2626
parseStyleContext,
@@ -34,6 +34,8 @@ import {
3434
} from "./style-context";
3535
import { globals, globalsForSvelteScript } from "./globals";
3636
import { svelteVersion } from "./svelte-version";
37+
import type { NormalizedParserOptions } from "./parser-options";
38+
import { isTypeScript, normalizeParserOptions } from "./parser-options";
3739

3840
export {
3941
StyleContext,
@@ -111,7 +113,7 @@ function parseAsSvelte(
111113

112114
const scripts = ctx.sourceCode.scripts;
113115
const resultScript = ctx.isTypeScript()
114-
? parseTypeScript(
116+
? parseTypeScriptInSvelte(
115117
scripts.getCurrentVirtualCodeInfo(),
116118
scripts.attrs,
117119
parserOptions,
@@ -231,8 +233,10 @@ function parseAsScript(
231233
code: string,
232234
parserOptions: NormalizedParserOptions,
233235
): ParseResult {
234-
const lang = parserOptions.filePath?.split(".").pop() || "js";
235-
const resultScript = parseScript(code, { lang }, parserOptions);
236+
const lang = parserOptions.filePath?.split(".").pop();
237+
const resultScript = isTypeScript(parserOptions, lang)
238+
? parseTypeScript(code, { lang }, parserOptions)
239+
: parseScript(code, { lang }, parserOptions);
236240

237241
// Add $$xxx variable
238242
const globalScope = resultScript.scopeManager!.globalScope;
@@ -263,41 +267,6 @@ function parseAsScript(
263267
return resultScript as any;
264268
}
265269

266-
type NormalizedParserOptions = {
267-
ecmaVersion: number | "latest";
268-
sourceType: "module" | "script";
269-
loc: boolean;
270-
range: boolean;
271-
raw: boolean;
272-
tokens: boolean;
273-
comment: boolean;
274-
eslintVisitorKeys: boolean;
275-
eslintScopeManager: boolean;
276-
filePath?: string;
277-
};
278-
279-
/** Normalize parserOptions */
280-
function normalizeParserOptions(options: any): NormalizedParserOptions {
281-
const parserOptions = {
282-
ecmaVersion: 2020,
283-
sourceType: "module",
284-
loc: true,
285-
range: true,
286-
raw: true,
287-
tokens: true,
288-
comment: true,
289-
eslintVisitorKeys: true,
290-
eslintScopeManager: true,
291-
...(options || {}),
292-
};
293-
parserOptions.sourceType = "module";
294-
if (parserOptions.ecmaVersion <= 5 || parserOptions.ecmaVersion == null) {
295-
parserOptions.ecmaVersion = 2015;
296-
}
297-
298-
return parserOptions;
299-
}
300-
301270
/** Extract tokens */
302271
function extractTokens(ctx: Context) {
303272
const useRanges = sortNodes([...ctx.tokens, ...ctx.comments]).map(

src/parser/parser-options.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import fs from "fs";
2+
import path from "path";
3+
import {
4+
isTSESLintParserObject,
5+
maybeTSESLintParserObject,
6+
} from "./parser-object";
7+
import { getParserForLang, type UserOptionParser } from "./resolve-parser";
8+
9+
export type NormalizedParserOptions = {
10+
parser?: UserOptionParser;
11+
project?: string | string[] | null;
12+
13+
ecmaVersion: number | "latest";
14+
sourceType: "module" | "script";
15+
ecmaFeatures?: {
16+
globalReturn?: boolean | undefined;
17+
impliedStrict?: boolean | undefined;
18+
jsx?: boolean | undefined;
19+
experimentalObjectRestSpread?: boolean | undefined;
20+
[key: string]: any;
21+
};
22+
loc: boolean;
23+
range: boolean;
24+
raw: boolean;
25+
tokens: boolean;
26+
comment: boolean;
27+
eslintVisitorKeys: boolean;
28+
eslintScopeManager: boolean;
29+
filePath?: string;
30+
};
31+
32+
/** Normalize parserOptions */
33+
export function normalizeParserOptions(options: any): NormalizedParserOptions {
34+
const parserOptions = {
35+
ecmaVersion: 2020,
36+
sourceType: "module",
37+
loc: true,
38+
range: true,
39+
raw: true,
40+
tokens: true,
41+
comment: true,
42+
eslintVisitorKeys: true,
43+
eslintScopeManager: true,
44+
...(options || {}),
45+
};
46+
parserOptions.sourceType = "module";
47+
if (parserOptions.ecmaVersion <= 5 || parserOptions.ecmaVersion == null) {
48+
parserOptions.ecmaVersion = 2015;
49+
}
50+
51+
return parserOptions;
52+
}
53+
54+
const TS_PARSER_NAMES = [
55+
"@typescript-eslint/parser",
56+
"typescript-eslint-parser-for-extra-files",
57+
];
58+
59+
export function isTypeScript(
60+
parserOptions: NormalizedParserOptions,
61+
lang: string | undefined,
62+
): boolean {
63+
if (!lang) {
64+
return false;
65+
}
66+
const parserValue = getParserForLang(lang, parserOptions?.parser);
67+
if (typeof parserValue !== "string") {
68+
return (
69+
maybeTSESLintParserObject(parserValue) ||
70+
isTSESLintParserObject(parserValue)
71+
);
72+
}
73+
const parserName = parserValue;
74+
if (TS_PARSER_NAMES.includes(parserName)) {
75+
return true;
76+
}
77+
if (TS_PARSER_NAMES.some((nm) => parserName.includes(nm))) {
78+
let targetPath = parserName;
79+
while (targetPath) {
80+
const pkgPath = path.join(targetPath, "package.json");
81+
if (fs.existsSync(pkgPath)) {
82+
try {
83+
return TS_PARSER_NAMES.includes(
84+
JSON.parse(fs.readFileSync(pkgPath, "utf-8"))?.name,
85+
);
86+
} catch {
87+
return false;
88+
}
89+
}
90+
const parent = path.dirname(targetPath);
91+
if (targetPath === parent) {
92+
break;
93+
}
94+
targetPath = parent;
95+
}
96+
}
97+
98+
return false;
99+
}

src/parser/resolve-parser.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,23 @@ import { getEspree } from "./espree";
22
import type { ParserObject } from "./parser-object";
33
import { isParserObject } from "./parser-object";
44

5-
type UserOptionParser =
5+
export type UserOptionParser =
66
| string
77
| ParserObject
88
| Record<string, string | ParserObject | undefined>
99
| undefined;
1010

1111
/** Get parser for script lang */
1212
export function getParserForLang(
13-
attrs: Record<string, string | undefined>,
13+
lang: string | undefined | null,
1414
parser: UserOptionParser,
1515
): string | ParserObject {
1616
if (parser) {
1717
if (typeof parser === "string" || isParserObject(parser)) {
1818
return parser;
1919
}
2020
if (typeof parser === "object") {
21-
const value = parser[attrs.lang || "js"];
21+
const value = parser[lang || "js"];
2222
if (typeof value === "string" || isParserObject(value)) {
2323
return value;
2424
}
@@ -32,7 +32,7 @@ export function getParser(
3232
attrs: Record<string, string | undefined>,
3333
parser: UserOptionParser,
3434
): ParserObject {
35-
const parserValue = getParserForLang(attrs, parser);
35+
const parserValue = getParserForLang(attrs.lang, parser);
3636
if (isParserObject(parserValue)) {
3737
return parserValue;
3838
}

src/parser/script.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import { analyzeScope } from "./analyze-scope";
33
import { traverseNodes } from "../traverse";
44
import { getParser } from "./resolve-parser";
55
import { isEnhancedParserObject } from "./parser-object";
6+
import type { NormalizedParserOptions } from "./parser-options";
67

78
/**
89
* Parse for <script>
910
*/
1011
export function parseScriptInSvelte(
1112
code: string,
1213
attrs: Record<string, string | undefined>,
13-
parserOptions: any = {},
14+
parserOptions: NormalizedParserOptions,
1415
): ESLintExtendedProgram {
1516
const result = parseScript(code, attrs, parserOptions);
1617

@@ -39,7 +40,7 @@ export function parseScriptInSvelte(
3940
export function parseScript(
4041
code: string,
4142
attrs: Record<string, string | undefined>,
42-
parserOptions: any = {},
43+
parserOptions: NormalizedParserOptions,
4344
): ESLintExtendedProgram {
4445
const result = parseScriptWithoutAnalyzeScopeFromVCode(
4546
code,
@@ -61,7 +62,7 @@ export function parseScript(
6162
export function parseScriptWithoutAnalyzeScope(
6263
code: string,
6364
attrs: Record<string, string | undefined>,
64-
options: any,
65+
options: NormalizedParserOptions,
6566
): ESLintExtendedProgram {
6667
const parser = getParser(attrs, options.parser);
6768

@@ -81,7 +82,7 @@ export function parseScriptWithoutAnalyzeScope(
8182
function parseScriptWithoutAnalyzeScopeFromVCode(
8283
code: string,
8384
attrs: Record<string, string | undefined>,
84-
options: any,
85+
options: NormalizedParserOptions,
8586
): ESLintExtendedProgram {
8687
const result = parseScriptWithoutAnalyzeScope(code, attrs, options);
8788
result._virtualScriptCode = code;

src/parser/template.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import { convertSvelteRoot } from "./converts/index";
66
import { sortNodes } from "./sort";
77
import type { SvelteProgram } from "../ast";
88
import { ParseError } from "..";
9+
import type { NormalizedParserOptions } from "./parser-options";
910

1011
/**
1112
* Parse for template
1213
*/
1314
export function parseTemplate(
1415
code: string,
1516
ctx: Context,
16-
parserOptions: any = {},
17+
parserOptions: NormalizedParserOptions,
1718
): {
1819
ast: SvelteProgram;
1920
svelteAst: SvAST.Ast;

0 commit comments

Comments
 (0)