File size: 8,240 Bytes
bc20498 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseForESLint = parseForESLint;
const visitor_keys_1 = require("../visitor-keys");
const context_1 = require("../context");
const eslint_scope_1 = require("eslint-scope");
const script_1 = require("./script");
const sort_1 = require("./sort");
const template_1 = require("./template");
const analyze_scope_1 = require("./analyze-scope");
const errors_1 = require("../errors");
const typescript_1 = require("./typescript");
const scope_1 = require("../scope");
const style_context_1 = require("./style-context");
const globals_1 = require("./globals");
const parser_options_1 = require("./parser-options");
const compat_1 = require("./compat");
const svelte_parse_context_1 = require("./svelte-parse-context");
const svelte_config_1 = require("../svelte-config");
/**
* Parse source code
*/
function parseForESLint(code, options) {
const svelteConfig = (0, svelte_config_1.resolveSvelteConfigFromOption)(options);
const parserOptions = (0, parser_options_1.normalizeParserOptions)(options);
if ((0, svelte_parse_context_1.isEnableRunes)(svelteConfig, parserOptions) &&
parserOptions.filePath &&
!parserOptions.filePath.endsWith(".svelte") &&
// If no `filePath` is set in ESLint, "<input>" will be specified.
parserOptions.filePath !== "<input>") {
const trimmed = code.trim();
if (!trimmed.startsWith("<") && !trimmed.endsWith(">")) {
const svelteParseContext = (0, svelte_parse_context_1.resolveSvelteParseContextForSvelteScript)(svelteConfig, parserOptions);
return parseAsScript(code, parserOptions, svelteParseContext);
}
}
return parseAsSvelte(code, svelteConfig, parserOptions);
}
/**
* Parse source code as svelte component
*/
function parseAsSvelte(code, svelteConfig, parserOptions) {
const ctx = new context_1.Context(code, parserOptions);
const resultTemplate = (0, template_1.parseTemplate)(ctx.sourceCode.template, ctx, parserOptions);
const svelteParseContext = (0, svelte_parse_context_1.resolveSvelteParseContextForSvelte)(svelteConfig, parserOptions, resultTemplate.svelteAst);
const scripts = ctx.sourceCode.scripts;
const resultScript = ctx.isTypeScript()
? (0, typescript_1.parseTypeScriptInSvelte)(scripts.getCurrentVirtualCodeInfo(), scripts.attrs, parserOptions, { slots: ctx.slots, svelteParseContext })
: (0, script_1.parseScriptInSvelte)(scripts.getCurrentVirtualCode(), scripts.attrs, parserOptions);
ctx.scriptLet.restore(resultScript);
ctx.tokens.push(...resultScript.ast.tokens);
ctx.comments.push(...resultScript.ast.comments);
(0, sort_1.sortNodes)(ctx.comments);
(0, sort_1.sortNodes)(ctx.tokens);
extractTokens(ctx);
(0, analyze_scope_1.analyzeStoreScope)(resultScript.scopeManager);
(0, analyze_scope_1.analyzeReactiveScope)(resultScript.scopeManager);
(0, analyze_scope_1.analyzeStoreScope)(resultScript.scopeManager); // for reactive vars
(0, analyze_scope_1.analyzeSnippetsScope)(ctx.snippets, resultScript.scopeManager);
// Add $$xxx variable
addGlobalVariables(resultScript.scopeManager, (0, globals_1.getGlobalsForSvelte)(svelteParseContext));
const ast = resultTemplate.ast;
const statements = [...resultScript.ast.body];
ast.sourceType = resultScript.ast.sourceType;
const scriptElements = ast.body.filter((b) => b.type === "SvelteScriptElement");
for (let index = 0; index < scriptElements.length; index++) {
const body = scriptElements[index];
let statement = statements[0];
while (statement &&
body.range[0] <= statement.range[0] &&
(statement.range[1] <= body.range[1] ||
index === scriptElements.length - 1)) {
statement.parent = body;
body.body.push(statement);
statements.shift();
statement = statements[0];
}
if (!body.startTag.attributes.some((attr) => attr.type === "SvelteAttribute" &&
attr.key.name === "context" &&
attr.value.length === 1 &&
attr.value[0].type === "SvelteLiteral" &&
attr.value[0].value === "module")) {
(0, analyze_scope_1.analyzePropsScope)(body, resultScript.scopeManager, svelteParseContext);
}
}
if (statements.length) {
throw new errors_1.ParseError("The script is unterminated", statements[0].range[1], ctx);
}
const styleElement = ast.body.find((b) => b.type === "SvelteStyleElement");
let styleContext = null;
resultScript.ast = ast;
resultScript.services = Object.assign(resultScript.services || {}, {
isSvelte: true,
isSvelteScript: false,
getSvelteHtmlAst() {
return (0, compat_1.getFragmentFromRoot)(resultTemplate.svelteAst);
},
getStyleContext() {
if (styleContext === null) {
styleContext = (0, style_context_1.parseStyleContext)(styleElement, ctx);
}
return styleContext;
},
styleNodeLoc: style_context_1.styleNodeLoc,
styleNodeRange: style_context_1.styleNodeRange,
svelteParseContext,
});
resultScript.visitorKeys = Object.assign({}, visitor_keys_1.KEYS, resultScript.visitorKeys);
return resultScript;
}
/**
* Parse source code as script
*/
function parseAsScript(code, parserOptions, svelteParseContext) {
var _a;
const lang = (_a = parserOptions.filePath) === null || _a === void 0 ? void 0 : _a.split(".").pop();
const resultScript = (0, parser_options_1.isTypeScript)(parserOptions, lang)
? (0, typescript_1.parseTypeScript)(code, { lang }, parserOptions, svelteParseContext)
: (0, script_1.parseScript)(code, { lang }, parserOptions);
// Add $$xxx variable
addGlobalVariables(resultScript.scopeManager, (0, globals_1.getGlobalsForSvelteScript)(svelteParseContext));
resultScript.services = Object.assign(resultScript.services || {}, {
isSvelte: false,
isSvelteScript: true,
svelteParseContext,
});
resultScript.visitorKeys = Object.assign({}, visitor_keys_1.KEYS, resultScript.visitorKeys);
return resultScript;
}
function addGlobalVariables(scopeManager, globals) {
const globalScope = scopeManager.globalScope;
for (const globalName of globals) {
if (globalScope.set.has(globalName))
continue;
const variable = new eslint_scope_1.Variable();
variable.name = globalName;
variable.scope = globalScope;
globalScope.variables.push(variable);
globalScope.set.set(globalName, variable);
globalScope.through = globalScope.through.filter((reference) => {
if (reference.identifier.name === globalName) {
// Links the variable and the reference.
// And this reference is removed from `Scope#through`.
reference.resolved = variable;
(0, scope_1.addReference)(variable.references, reference);
return false;
}
return true;
});
}
}
/** Extract tokens */
function extractTokens(ctx) {
const useRanges = (0, sort_1.sortNodes)([...ctx.tokens, ...ctx.comments]).map((t) => t.range);
let range = useRanges.shift();
for (let index = 0; index < ctx.sourceCode.template.length; index++) {
while (range && range[1] <= index) {
range = useRanges.shift();
}
if (range && range[0] <= index) {
index = range[1] - 1;
continue;
}
const c = ctx.sourceCode.template[index];
if (!c.trim()) {
continue;
}
if (isPunctuator(c)) {
ctx.addToken("Punctuator", { start: index, end: index + 1 });
}
else {
// unknown
// It is may be a bug.
ctx.addToken("Identifier", { start: index, end: index + 1 });
}
}
(0, sort_1.sortNodes)(ctx.comments);
(0, sort_1.sortNodes)(ctx.tokens);
/**
* Checks if the given char is punctuator
*/
function isPunctuator(c) {
return /^[^\w$]$/iu.test(c);
}
}
|