Skip to content

Change parser to allow parsing two script tags on <script setup> #108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"pretest": "run-s build lint",
"test": "npm run -s test:mocha",
"test:mocha": "nyc mocha \"test/*.js\" --reporter dot --timeout 10000",
"test:debug": "mocha --inspect --require ts-node/register \"test/*.js\" --reporter dot --timeout 10000",
"test:debug": "mocha --inspect --require ts-node/register/transpile-only \"test/*.js\" --reporter dot --timeout 10000",
"preupdate-fixtures": "npm run -s build",
"update-fixtures": "node scripts/update-fixtures-ast.js && node scripts/update-fixtures-document-fragment.js",
"preversion": "npm test",
Expand Down
132 changes: 119 additions & 13 deletions scripts/update-fixtures-ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
const fs = require("fs")
const path = require("path")
const parser = require("../")
const escope = require("eslint-scope")

//------------------------------------------------------------------------------
// Helpers
Expand All @@ -38,7 +39,7 @@ function replacer(key, value) {
return undefined
}
if (key === "errors" && Array.isArray(value)) {
return value.map(e => ({
return value.map((e) => ({
message: e.message,
index: e.index,
lineNumber: e.lineNumber,
Expand Down Expand Up @@ -95,6 +96,106 @@ function getTree(source, ast) {
return root.children
}

function scopeToJSON(scopeManager) {
return JSON.stringify(normalizeScope(scopeManager.globalScope), replacer, 4)

function normalizeScope(scope) {
return {
type: scope.type,
variables: scope.variables.map(normalizeVar),
references: scope.references.map(normalizeReference),
childScopes: scope.childScopes.map(normalizeScope),
through: scope.through.map(normalizeReference),
}
}

function normalizeVar(v) {
return {
name: v.name,
identifiers: v.identifiers.map(normalizeId),
defs: v.defs.map(normalizeDef),
references: v.references.map(normalizeReference),
}
}

function normalizeReference(reference) {
return {
identifier: normalizeId(reference.identifier),
from: reference.from.type,
resolved: normalizeId(
reference.resolved &&
reference.resolved.defs &&
reference.resolved.defs[0] &&
reference.resolved.defs[0].name
),
init: reference.init || null,
}
}

function normalizeDef(def) {
return {
type: def.type,
node: normalizeDefNode(def.node),
name: def.name.name,
}
}

function normalizeId(identifier) {
return (
identifier && {
type: identifier.type,
name: identifier.name,
loc: identifier.loc,
}
)
}

function normalizeDefNode(node) {
return {
type: node.type,
loc: node.loc,
}
}
}

/**
* Analyze scope
*/
function analyze(ast, parserOptions) {
const ecmaVersion = parserOptions.ecmaVersion || 2017
const ecmaFeatures = parserOptions.ecmaFeatures || {}
const sourceType = parserOptions.sourceType || "script"
const result = escope.analyze(ast, {
ignoreEval: true,
nodejsScope: false,
impliedStrict: ecmaFeatures.impliedStrict,
ecmaVersion,
sourceType,
fallback: getFallbackKeys,
})

return result

function getFallbackKeys(node) {
return Object.keys(node).filter(fallbackKeysFilter, node)
}

function fallbackKeysFilter(key) {
const value = null
return (
key !== "comments" &&
key !== "leadingComments" &&
key !== "loc" &&
key !== "parent" &&
key !== "range" &&
key !== "tokens" &&
key !== "trailingComments" &&
typeof value === "object" &&
(typeof value.type === "string" || Array.isArray(value))
)
}
}

//------------------------------------------------------------------------------
// Main
//------------------------------------------------------------------------------
Expand All @@ -105,25 +206,30 @@ for (const name of TARGETS) {
const astPath = path.join(ROOT, `${name}/ast.json`)
const tokenRangesPath = path.join(ROOT, `${name}/token-ranges.json`)
const treePath = path.join(ROOT, `${name}/tree.json`)
const scopePath = path.join(ROOT, `${name}/scope.json`)
const source = fs.readFileSync(sourcePath, "utf8")
const actual = parser.parse(
source,
Object.assign(
{ filePath: sourcePath },
PARSER_OPTIONS,
fs.existsSync(optionsPath)
? JSON.parse(fs.readFileSync(optionsPath, "utf8"))
: {}
)
const options = Object.assign(
{ filePath: sourcePath },
PARSER_OPTIONS,
fs.existsSync(optionsPath)
? JSON.parse(fs.readFileSync(optionsPath, "utf8"))
: {}
)
const tokenRanges = getAllTokens(actual).map(t =>
const actual = parser.parseForESLint(source, options)
const tokenRanges = getAllTokens(actual.ast).map((t) =>
source.slice(t.range[0], t.range[1])
)
const tree = getTree(source, actual)
const tree = getTree(source, actual.ast)

console.log("Update:", name)

fs.writeFileSync(astPath, JSON.stringify(actual, replacer, 4))
fs.writeFileSync(astPath, JSON.stringify(actual.ast, replacer, 4))
fs.writeFileSync(tokenRangesPath, JSON.stringify(tokenRanges, replacer, 4))
fs.writeFileSync(treePath, JSON.stringify(tree, replacer, 4))
if (fs.existsSync(scopePath)) {
fs.writeFileSync(
scopePath,
scopeToJSON(actual.scopeManager || analyze(actual.ast, options))
)
}
}
62 changes: 58 additions & 4 deletions src/common/fix-locations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import type { ESLintExtendedProgram, LocationRange, Node } from "../ast"
import type {
ESLintExtendedProgram,
HasLocation,
LocationRange,
Node,
ParseError,
} from "../ast"
import { traverseNodes } from "../ast"
import type { LocationCalculator } from "./location-calculator"

Expand Down Expand Up @@ -42,7 +48,7 @@ export function fixLocations(
traversed.add(node.loc)
}
} else {
locationCalculator.fixLocation(node)
fixLocation(node, locationCalculator)
traversed.add(node.range)
traversed.add(node.loc)
}
Expand All @@ -55,9 +61,57 @@ export function fixLocations(
})

for (const token of result.ast.tokens || []) {
locationCalculator.fixLocation(token)
fixLocation(token, locationCalculator)
}
for (const comment of result.ast.comments || []) {
locationCalculator.fixLocation(comment)
fixLocation(comment, locationCalculator)
}
}

/**
* Modify the location information of the given node with using the base offset and gaps of this calculator.
* @param node The node to modify their location.
*/
export function fixLocation<T extends HasLocation>(
node: T,
locationCalculator: LocationCalculator,
): T {
const range = node.range
const loc = node.loc
const d0 = locationCalculator.getFixOffset(range[0], "start")
const d1 = locationCalculator.getFixOffset(range[1], "end")

if (d0 !== 0) {
range[0] += d0
if (node.start != null) {
node.start += d0
}
loc.start = locationCalculator.getLocFromIndex(range[0])
}
if (d1 !== 0) {
range[1] += d1
if (node.end != null) {
node.end += d0
}
loc.end = locationCalculator.getLocFromIndex(range[1])
}

return node
}

/**
* Modify the location information of the given error with using the base offset and gaps of this calculator.
* @param error The error to modify their location.
*/
export function fixErrorLocation(
error: ParseError,
locationCalculator: LocationCalculator,
) {
const diff = locationCalculator.getFixOffset(error.index, "start")

error.index += diff

const loc = locationCalculator.getLocFromIndex(error.index)
error.lineNumber = loc.line
error.column = loc.column
}
27 changes: 27 additions & 0 deletions src/common/lines-and-columns.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import sortedLastIndex from "lodash/sortedLastIndex"
import type { Location } from "../ast"
/**
* A class for getting lines and columns location.
*/
export class LinesAndColumns {
protected ltOffsets: number[]

/**
* Initialize.
* @param ltOffsets The list of the offset of line terminators.
*/
public constructor(ltOffsets: number[]) {
this.ltOffsets = ltOffsets
}

/**
* Calculate the location of the given index.
* @param index The index to calculate their location.
* @returns The location of the index.
*/
public getLocFromIndex(index: number): Location {
const line = sortedLastIndex(this.ltOffsets, index) + 1
const column = index - (line === 1 ? 0 : this.ltOffsets[line - 2])
return { line, column }
}
}
Loading