/** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ import type { ScopeManager, Scope } from "eslint-scope" import type { ESLintBlockStatement, ESLintExportNamedDeclaration, ESLintExportSpecifier, ESLintExtendedProgram, ESLintIdentifier, ESLintModuleDeclaration, ESLintNode, ESLintProgram, ESLintStatement, Token, VElement, } from "../ast/index" import { ParseError, traverseNodes } from "../ast/index" import { fixErrorLocation, fixLocation, fixLocations, fixNodeLocations, } from "../common/fix-locations" import type { LinesAndColumns } from "../common/lines-and-columns" import type { LocationCalculator } from "../common/location-calculator" import type { ParserOptions } from "../common/parser-options" import { parseScript as parseScriptBase, parseScriptFragment, } from "../script/index" import { extractGeneric } from "../script/generic" import { DEFAULT_ECMA_VERSION } from "./parser-options" type RemapBlock = { range: [number, number] offset: number } /** * `parseScriptSetupElements` rewrites the source code so that it can parse * the combination of `", }) } } result.ast.tokens.sort((a, b) => a.range[0] - b.range[0]) } result.ast.body.sort((a, b) => a.range[0] - b.range[0]) const programStartOffset = result.ast.body.reduce( (start, node) => Math.min(start, node.range[0]), result.ast.range[0], ) result.ast.range[0] = programStartOffset result.ast.loc.start = locationCalculator.getLocFromIndex(programStartOffset) if (result.ast.start != null) { result.ast.start = [scriptSetupElement, scriptElement].reduce( (start, node) => { const textNode = node.children[0] return Math.min( start, textNode?.type === "VText" ? textNode.range[0] : node.startTag.range[1], ) }, result.ast.start, ) } const programEndOffset = result.ast.body.reduce( (end, node) => Math.max(end, node.range[1]), 0, ) result.ast.range[1] = programEndOffset result.ast.loc.end = locationCalculator.getLocFromIndex(programEndOffset) if (result.ast.end != null) { result.ast.end = [scriptSetupElement, scriptElement].reduce( (end, node) => { const textNode = node.children[0] return Math.max( end, textNode?.type === "VText" ? textNode.range[1] : (node.endTag?.range[0] ?? node.range[1]), ) }, 0, ) } return result } /** * Parses the scripts of the given ` * * ``` * * ↓ * * ```js * export let count = 42 * ; * import MyComponent from './MyComponent.vue'; * { * let count = 42 * } * ``` * * Example 2: * * ```vue * * * ``` * * ↓ * * ```js * export let count = 42 * ; * import MyComponent1 from './MyComponent1.vue'; * import MyComponent2 from './MyComponent2.vue'; * { * let count = 42; * let a * } * ``` * * Example 3: * * ```vue * * * ``` * * ↓ * * ```js * export let count = 42 * export let count2 = 42 * ; * import MyComponent1 from './MyComponent1.vue'; * { * let count = 42; * let a * ; * ({count}) * ; * let count2 = 42 * ; * count2++ * ; * } * ``` */ function getScriptSetupModuleCodeBlocks( scriptSetupElement: VElement, scriptElement: VElement, sfcCode: string, linesAndColumns: LinesAndColumns, parserOptions: ParserOptions, ): ScriptSetupModuleCodeBlocks | null { const scriptSetupCodeBlocks = getScriptSetupCodeBlocks( scriptSetupElement, sfcCode, linesAndColumns, parserOptions, ) const textNode = scriptElement.children[0] if (textNode == null || textNode.type !== "VText") { return scriptSetupCodeBlocks } const [scriptStartOffset, scriptEndOffset] = textNode.range const codeBlocks = new CodeBlocks() codeBlocks.append( sfcCode.slice(scriptStartOffset, scriptEndOffset), scriptStartOffset, ) if (scriptSetupCodeBlocks == null) { return { codeBlocks } } codeBlocks.appendSplitPunctuators(";") const scriptSetupOffset = codeBlocks.length codeBlocks.appendCodeBlocks(scriptSetupCodeBlocks.codeBlocks) return { codeBlocks, scriptSetupBlockRange: [ scriptSetupCodeBlocks.scriptSetupBlockRange[0] + scriptSetupOffset, scriptSetupCodeBlocks.scriptSetupBlockRange[1] + scriptSetupOffset, ], postprocess: scriptSetupCodeBlocks.postprocess, restoreASTCallbacks: scriptSetupCodeBlocks.restoreASTCallbacks, } } /** * Parses the script in the given `