jsonc-eslint-parser
Advanced tools
Comparing version 1.3.1 to 1.4.0
@@ -1,6 +0,6 @@ | ||
import type { Node, Program, ObjectExpression, ArrayExpression, Literal, Identifier, UnaryExpression, TemplateLiteral, Expression } from "estree"; | ||
import type { Node } from "estree"; | ||
import type { AST } from "eslint"; | ||
import type { JSONNode, JSONProgram, JSONObjectExpression, JSONArrayExpression, JSONExpression, JSONLiteral, JSONIdentifier, Locations, JSONUnaryExpression, JSONTemplateLiteral } from "./ast"; | ||
import type { ParseError } from "./errors"; | ||
import type { TokenStore, MaybeNodeOrToken } from "./token-store"; | ||
import type { JSONNode, JSONProgram } from "./ast"; | ||
import type { TokenStore } from "./token-store"; | ||
import type { Token as AcornToken } from "acorn"; | ||
export declare type JSONSyntaxContext = { | ||
@@ -31,14 +31,9 @@ trailingCommas: boolean; | ||
}; | ||
export declare function convertNode(node: Program, tokens: TokenStore, ctx: JSONSyntaxContext): JSONProgram; | ||
export declare function convertNode(node: ObjectExpression, tokens: TokenStore, ctx: JSONSyntaxContext): JSONObjectExpression; | ||
export declare function convertNode(node: ArrayExpression, tokens: TokenStore, ctx: JSONSyntaxContext): JSONArrayExpression; | ||
export declare function convertNode(node: Literal, tokens: TokenStore, ctx: JSONSyntaxContext): JSONLiteral; | ||
export declare function convertNode(node: UnaryExpression, tokens: TokenStore, ctx: JSONSyntaxContext): JSONUnaryExpression; | ||
export declare function convertNode(node: Identifier, tokens: TokenStore, ctx: JSONSyntaxContext): JSONIdentifier; | ||
export declare function convertNode(node: TemplateLiteral, tokens: TokenStore, ctx: JSONSyntaxContext): JSONTemplateLiteral; | ||
export declare function convertNode(node: Expression, tokens: TokenStore, ctx: JSONSyntaxContext): JSONExpression; | ||
export declare function convertNode(node: Node, tokens: TokenStore, ctx: JSONSyntaxContext): JSONNode; | ||
export declare function convertToken(token: AST.Token): AST.Token; | ||
export declare function fixLocation(node: MaybeNodeOrToken | AST.Token): void; | ||
export declare function fixErrorLocation(error: ParseError): void; | ||
export declare function getFixLocation(node: MaybeNodeOrToken | AST.Token): Locations; | ||
export declare class TokenConvertor { | ||
private readonly code; | ||
private readonly templateBuffer; | ||
private readonly tokTypes; | ||
constructor(code: string); | ||
convertToken(token: AcornToken): AST.Token | null; | ||
} | ||
export declare function convertProgramNode(node: Node | JSONNode, tokens: TokenStore, ctx: JSONSyntaxContext, code: string): JSONProgram; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getFixLocation = exports.fixErrorLocation = exports.fixLocation = exports.convertToken = exports.convertNode = void 0; | ||
const traverse_1 = require("./traverse"); | ||
exports.convertProgramNode = exports.TokenConvertor = void 0; | ||
const validate_1 = require("./validate"); | ||
const errors_1 = require("./errors"); | ||
const token_store_1 = require("./token-store"); | ||
const require_utils_1 = require("./require-utils"); | ||
const lineBreakPattern = /\r\n|[\n\r\u2028\u2029]/u; | ||
const octalNumericLiteralPattern = /^0[Oo]/u; | ||
const legacyOctalNumericLiteralPattern = /^0\d/u; | ||
const binaryNumericLiteralPattern = /^0[Bb]/u; | ||
let cacheCodePointEscapeMatcher; | ||
function getCodePointEscapeMatcher() { | ||
if (!cacheCodePointEscapeMatcher) { | ||
const utils = (0, require_utils_1.requireFromCwd)("eslint-utils") || | ||
(0, require_utils_1.requireFromLinter)("eslint-utils") || | ||
require("eslint-utils"); | ||
cacheCodePointEscapeMatcher = new utils.PatternMatcher(/\\u\{[\dA-Fa-f]+\}/gu); | ||
const acorn_1 = require("./modules/acorn"); | ||
class TokenConvertor { | ||
constructor(code) { | ||
this.templateBuffer = []; | ||
this.code = code; | ||
this.tokTypes = (0, acorn_1.getAcorn)().tokTypes; | ||
} | ||
return cacheCodePointEscapeMatcher; | ||
} | ||
function convertNode(node, tokens, ctx) { | ||
if (node.type === "Program") { | ||
return convertProgramNode(node, tokens, ctx); | ||
} | ||
if (node.type === "ObjectExpression") { | ||
return convertObjectExpressionNode(node, tokens, ctx); | ||
} | ||
if (node.type === "ArrayExpression") { | ||
return convertArrayExpressionNode(node, tokens, ctx); | ||
} | ||
if (node.type === "Literal") { | ||
return convertLiteralNode(node, tokens, ctx); | ||
} | ||
if (node.type === "UnaryExpression") { | ||
return convertUnaryExpressionNode(node, tokens, ctx); | ||
} | ||
if (node.type === "Identifier") { | ||
return convertIdentifierNode(node, tokens, ctx); | ||
} | ||
if (node.type === "TemplateLiteral") { | ||
return convertTemplateLiteralNode(node, tokens, ctx); | ||
} | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
exports.convertNode = convertNode; | ||
function convertToken(token) { | ||
if (token.type === "Punctuator") { | ||
if (token.value === "(" || token.value === ")") { | ||
return (0, errors_1.throwUnexpectedTokenError)(token.value, token); | ||
convertToken(token) { | ||
const { tokTypes } = this; | ||
let type, value; | ||
const additional = {}; | ||
if (token.type === tokTypes.string) { | ||
type = "String"; | ||
value = this.code.slice(...token.range); | ||
} | ||
} | ||
return Object.assign({ type: token.type, value: token.value }, getFixLocation(token)); | ||
} | ||
exports.convertToken = convertToken; | ||
function convertProgramNode(node, tokens, ctx) { | ||
if (node.type !== "Program") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
const bodyNode = node.body[0]; | ||
if (bodyNode.type !== "ExpressionStatement") { | ||
return (0, errors_1.throwUnexpectedNodeError)(bodyNode, tokens); | ||
} | ||
const expression = bodyNode.expression; | ||
if (expression.type === "Identifier") { | ||
if (!isStaticValueIdentifier(expression, ctx)) { | ||
return (0, errors_1.throwUnexpectedNodeError)(expression, tokens); | ||
else if (token.type === tokTypes.num) { | ||
type = "Numeric"; | ||
value = this.code.slice(...token.range); | ||
} | ||
} | ||
const body = Object.assign(Object.assign({ type: "JSONExpressionStatement", expression: convertNode(expression, tokens, ctx) }, getFixLocation(bodyNode)), { parent: null }); | ||
const nn = Object.assign(Object.assign({ type: "Program", body: [body], comments: [], tokens: [] }, getFixLocation(node)), { parent: null }); | ||
return nn; | ||
} | ||
function convertObjectExpressionNode(node, tokens, ctx) { | ||
if (node.type !== "ObjectExpression") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (!ctx.trailingCommas) { | ||
const token = tokens.getTokenBefore(tokens.getLastToken(node)); | ||
if (token && (0, token_store_1.isComma)(token)) { | ||
return (0, errors_1.throwUnexpectedTokenError)(",", token); | ||
} | ||
} | ||
const nn = Object.assign(Object.assign({ type: "JSONObjectExpression", properties: node.properties.map((p) => convertPropertyNode(p, tokens, ctx)) }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function convertPropertyNode(node, tokens, ctx) { | ||
if (node.type !== "Property") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (node.computed) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (node.method) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.value, tokens); | ||
} | ||
if (node.shorthand) { | ||
return (0, errors_1.throwExpectedTokenError)(":", node); | ||
} | ||
if (node.kind !== "init") { | ||
return (0, errors_1.throwExpectedTokenError)(":", tokens.getFirstToken(node)); | ||
} | ||
if (node.key.type === "Literal") { | ||
const keyValueType = typeof node.key.value; | ||
if (keyValueType === "number") { | ||
if (!ctx.numberProperties) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); | ||
else if (token.type.keyword) { | ||
if (token.type.keyword === "true" || | ||
token.type.keyword === "false") { | ||
type = "Boolean"; | ||
} | ||
} | ||
else if (keyValueType !== "string") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); | ||
} | ||
} | ||
else if (node.key.type === "Identifier") { | ||
if (!ctx.unquoteProperties) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); | ||
} | ||
} | ||
else { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.key, tokens); | ||
} | ||
if (node.value.type === "Identifier") { | ||
if (!isStaticValueIdentifier(node.value, ctx)) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node.value, tokens); | ||
} | ||
} | ||
const nn = Object.assign(Object.assign({ type: "JSONProperty", key: convertNode(node.key, tokens, ctx), value: convertNode(node.value, tokens, ctx), kind: node.kind, computed: node.computed, method: node.method, shorthand: node.shorthand }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function convertArrayExpressionNode(node, tokens, ctx) { | ||
if (node.type !== "ArrayExpression") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (!ctx.trailingCommas) { | ||
const token = tokens.getTokenBefore(tokens.getLastToken(node)); | ||
if (token && (0, token_store_1.isComma)(token)) { | ||
return (0, errors_1.throwUnexpectedTokenError)(",", token); | ||
} | ||
} | ||
const elements = node.elements.map((child, index) => { | ||
if (!child) { | ||
if (ctx.sparseArrays) { | ||
return null; | ||
else if (token.type.keyword === "null") { | ||
type = "Null"; | ||
} | ||
const beforeIndex = index - 1; | ||
const before = beforeIndex >= 0 | ||
? tokens.getLastToken(node.elements[beforeIndex]) | ||
: tokens.getFirstToken(node); | ||
return (0, errors_1.throwUnexpectedTokenError)(",", tokens.getTokenAfter(before, token_store_1.isComma)); | ||
} | ||
if (child.type === "Identifier") { | ||
if (!isStaticValueIdentifier(child, ctx)) { | ||
return (0, errors_1.throwUnexpectedNodeError)(child, tokens); | ||
else { | ||
type = "Keyword"; | ||
} | ||
value = token.value; | ||
} | ||
return convertNode(child, tokens, ctx); | ||
}); | ||
const nn = Object.assign(Object.assign({ type: "JSONArrayExpression", elements }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function isRegExpLiteral(node) { | ||
return Boolean(node.regex); | ||
} | ||
function convertLiteralNode(node, tokens, ctx) { | ||
if (node.type !== "Literal") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
let nn; | ||
if (isRegExpLiteral(node)) { | ||
if (!ctx.regExpLiterals) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
else if (token.type === tokTypes.braceL || | ||
token.type === tokTypes.braceR || | ||
token.type === tokTypes.bracketL || | ||
token.type === tokTypes.bracketR || | ||
token.type === tokTypes.colon || | ||
token.type === tokTypes.comma || | ||
token.type === tokTypes.plusMin) { | ||
type = "Punctuator"; | ||
value = this.code.slice(...token.range); | ||
} | ||
nn = Object.assign({ type: "JSONLiteral", value: node.value, raw: node.raw, regex: node.regex }, getFixLocation(node)); | ||
} | ||
else if (node.bigint) { | ||
if (!ctx.bigintLiterals) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
else if (token.type === tokTypes.name) { | ||
type = "Identifier"; | ||
value = token.value; | ||
} | ||
nn = Object.assign({ type: "JSONLiteral", value: node.value, raw: node.raw, bigint: node.bigint }, getFixLocation(node)); | ||
} | ||
else { | ||
validateLiteral(node, ctx); | ||
const value = node.value; | ||
nn = Object.assign({ type: "JSONLiteral", value, raw: node.raw }, getFixLocation(node)); | ||
} | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function validateLiteral(node, ctx) { | ||
const value = node.value; | ||
if ((!ctx.invalidJsonNumbers || | ||
!ctx.leadingOrTrailingDecimalPoints || | ||
!ctx.numericSeparators) && | ||
typeof value === "number") { | ||
const text = node.raw; | ||
if (!ctx.leadingOrTrailingDecimalPoints) { | ||
if (text.startsWith(".")) { | ||
return (0, errors_1.throwUnexpectedTokenError)(".", node); | ||
} | ||
if (text.endsWith(".")) { | ||
return (0, errors_1.throwUnexpectedTokenError)(".", { | ||
range: [node.range[1] - 1, node.range[1]], | ||
else if (token.type === tokTypes.backQuote) { | ||
if (this.templateBuffer.length > 0) { | ||
const first = this.templateBuffer[0]; | ||
this.templateBuffer.length = 0; | ||
return { | ||
type: "Template", | ||
value: this.code.slice(first.start, token.end), | ||
range: [first.start, token.end], | ||
loc: { | ||
start: { | ||
line: node.loc.end.line, | ||
column: node.loc.end.column - 1, | ||
}, | ||
end: node.loc.end, | ||
start: first.loc.start, | ||
end: token.loc.end, | ||
}, | ||
}); | ||
}; | ||
} | ||
this.templateBuffer.push(token); | ||
return null; | ||
} | ||
if (!ctx.numericSeparators) { | ||
if (text.includes("_")) { | ||
const index = text.indexOf("_"); | ||
return (0, errors_1.throwUnexpectedTokenError)("_", { | ||
range: [node.range[0] + index, node.range[0] + index + 1], | ||
loc: { | ||
start: { | ||
line: node.loc.start.line, | ||
column: node.loc.start.column + index, | ||
}, | ||
end: { | ||
line: node.loc.start.line, | ||
column: node.loc.start.column + index + 1, | ||
}, | ||
}, | ||
}); | ||
else if (token.type === tokTypes.template) { | ||
if (this.templateBuffer.length === 0) { | ||
return (0, errors_1.throwUnexpectedTokenError)(this.code.slice(...token.range), token); | ||
} | ||
this.templateBuffer.push(token); | ||
return null; | ||
} | ||
if (!ctx.octalNumericLiterals) { | ||
if (octalNumericLiteralPattern.test(text)) { | ||
return (0, errors_1.throwUnexpectedError)("octal numeric literal", node); | ||
} | ||
else if (token.type === tokTypes.regexp) { | ||
const reValue = token.value; | ||
type = "RegularExpression"; | ||
additional.regex = { | ||
flags: reValue.flags, | ||
pattern: reValue.pattern, | ||
}; | ||
value = `/${reValue.pattern}/${reValue.flags}`; | ||
} | ||
if (!ctx.legacyOctalNumericLiterals) { | ||
if (legacyOctalNumericLiteralPattern.test(text)) { | ||
return (0, errors_1.throwUnexpectedError)("legacy octal numeric literal", node); | ||
} | ||
else { | ||
return (0, errors_1.throwUnexpectedTokenError)(this.code.slice(...token.range), token); | ||
} | ||
if (!ctx.binaryNumericLiterals) { | ||
if (binaryNumericLiteralPattern.test(text)) { | ||
return (0, errors_1.throwUnexpectedError)("binary numeric literal", node); | ||
} | ||
; | ||
token.type = type; | ||
token.value = value; | ||
for (const k in additional) { | ||
; | ||
token[k] = additional[k]; | ||
} | ||
if (!ctx.invalidJsonNumbers) { | ||
try { | ||
JSON.parse(text); | ||
} | ||
catch (_a) { | ||
return (0, errors_1.throwInvalidNumberError)(text, node); | ||
} | ||
} | ||
return token; | ||
} | ||
if ((!ctx.multilineStrings || | ||
!ctx.singleQuotes || | ||
!ctx.unicodeCodepointEscapes) && | ||
typeof value === "string") { | ||
if (!ctx.singleQuotes) { | ||
if (node.raw.startsWith("'")) { | ||
return (0, errors_1.throwUnexpectedError)("single quoted", node); | ||
} | ||
} | ||
if (!ctx.multilineStrings) { | ||
if (lineBreakPattern.test(node.raw)) { | ||
return (0, errors_1.throwUnexpectedError)("multiline string", node); | ||
} | ||
} | ||
if (!ctx.unicodeCodepointEscapes) { | ||
if (getCodePointEscapeMatcher().test(node.raw)) { | ||
return (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node); | ||
} | ||
} | ||
} | ||
return undefined; | ||
} | ||
function convertUnaryExpressionNode(node, tokens, ctx) { | ||
if (node.type !== "UnaryExpression") { | ||
exports.TokenConvertor = TokenConvertor; | ||
function convertProgramNode(node, tokens, ctx, code) { | ||
if (node.type !== "JSONObjectExpression" && | ||
node.type !== "JSONArrayExpression" && | ||
node.type !== "JSONLiteral" && | ||
node.type !== "JSONUnaryExpression" && | ||
node.type !== "JSONIdentifier" && | ||
node.type !== "JSONTemplateLiteral") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
const operator = node.operator; | ||
if (operator === "+") { | ||
if (!ctx.plusSigns) { | ||
return (0, errors_1.throwUnexpectedTokenError)("+", node); | ||
if (node.type === "JSONIdentifier") { | ||
if (!(0, validate_1.isStaticValueIdentifier)(node, ctx)) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
} | ||
else if (operator !== "-") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
const argument = node.argument; | ||
if (argument.type === "Literal") { | ||
if (typeof argument.value !== "number") { | ||
return (0, errors_1.throwUnexpectedNodeError)(argument, tokens); | ||
} | ||
} | ||
else if (argument.type === "Identifier") { | ||
if (!isNumberIdentifier(argument, ctx)) { | ||
return (0, errors_1.throwUnexpectedNodeError)(argument, tokens); | ||
} | ||
} | ||
else { | ||
return (0, errors_1.throwUnexpectedNodeError)(argument, tokens); | ||
} | ||
if (!ctx.spacedSigns) { | ||
if (node.range[0] + 1 < argument.range[0]) { | ||
return (0, errors_1.throwUnexpectedSpaceError)(tokens.getFirstToken(node)); | ||
} | ||
} | ||
const nn = Object.assign(Object.assign({ type: "JSONUnaryExpression", operator, prefix: node.prefix, argument: convertNode(argument, tokens, ctx) }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function convertIdentifierNode(node, tokens, ctx) { | ||
if (node.type !== "Identifier") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (!ctx.escapeSequenceInIdentifier) { | ||
if (node.name.length < node.range[1] - node.range[0]) { | ||
return (0, errors_1.throwUnexpectedError)("escape sequence", node); | ||
} | ||
} | ||
const nn = Object.assign({ type: "JSONIdentifier", name: node.name }, getFixLocation(node)); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function convertTemplateLiteralNode(node, tokens, ctx) { | ||
if (node.type !== "TemplateLiteral") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (!ctx.templateLiterals) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
if (node.expressions.length) { | ||
const token = tokens.getFirstToken(node.quasis[0]); | ||
const loc = { | ||
loc: { | ||
start: { | ||
line: token.loc.end.line, | ||
column: token.loc.end.column - 2, | ||
}, | ||
end: token.loc.end, | ||
const body = Object.assign(Object.assign({ type: "JSONExpressionStatement", expression: node }, cloneLocation(node)), { parent: null }); | ||
setParent(node, body); | ||
const end = code.length; | ||
const endLoc = (0, acorn_1.getAcorn)().getLineInfo(code, end); | ||
const nn = { | ||
type: "Program", | ||
body: [body], | ||
comments: [], | ||
tokens: [], | ||
range: [0, end], | ||
loc: { | ||
start: { | ||
line: 1, | ||
column: 0, | ||
}, | ||
range: [token.range[1] - 2, token.range[1]], | ||
}; | ||
return (0, errors_1.throwUnexpectedTokenError)("$", loc); | ||
} | ||
if (!ctx.unicodeCodepointEscapes) { | ||
if (getCodePointEscapeMatcher().test(node.quasis[0].value.raw)) { | ||
return (0, errors_1.throwUnexpectedError)("unicode codepoint escape", node); | ||
} | ||
} | ||
const quasis = [ | ||
convertTemplateElementNode(node.quasis[0], tokens), | ||
]; | ||
const nn = Object.assign(Object.assign({ type: "JSONTemplateLiteral", quasis, expressions: [] }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
end: { | ||
line: endLoc.line, | ||
column: endLoc.column, | ||
}, | ||
}, | ||
parent: null, | ||
}; | ||
setParent(body, nn); | ||
return nn; | ||
} | ||
function convertTemplateElementNode(node, tokens) { | ||
if (node.type !== "TemplateElement") { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
const { cooked, raw } = node.value; | ||
if (cooked == null) { | ||
return (0, errors_1.throwUnexpectedNodeError)(node, tokens); | ||
} | ||
const nn = Object.assign(Object.assign({ type: "JSONTemplateElement", tail: node.tail, value: { raw, cooked } }, getFixLocation(node)), { parent: null }); | ||
checkUnexpectedKeys(node, tokens, nn); | ||
return nn; | ||
} | ||
function isStaticValueIdentifier(node, ctx) { | ||
if (isNumberIdentifier(node, ctx)) { | ||
return true; | ||
} | ||
return node.name === "undefined" && ctx.undefinedKeywords; | ||
} | ||
function isNumberIdentifier(node, ctx) { | ||
if (node.name === "Infinity" && ctx.infinities) { | ||
return true; | ||
} | ||
if (node.name === "NaN" && ctx.nans) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
function checkUnexpectedKeys(node, tokens, jsonNode) { | ||
const keys = (0, traverse_1.getKeys)(node); | ||
for (const key of keys) { | ||
if (!(key in jsonNode)) { | ||
(0, errors_1.throwUnexpectedNodeError)((0, traverse_1.getNodes)(node, key).next().value, tokens); | ||
} | ||
} | ||
} | ||
function fixLocation(node) { | ||
const locs = getFixLocation(node); | ||
node.range = locs.range; | ||
node.loc = locs.loc; | ||
} | ||
exports.fixLocation = fixLocation; | ||
function fixErrorLocation(error) { | ||
error.index = Math.max(error.index - 2, 0); | ||
if (error.lineNumber === 0) { | ||
error.column = Math.max(error.column - 2, 0); | ||
} | ||
} | ||
exports.fixErrorLocation = fixErrorLocation; | ||
function getFixLocation(node) { | ||
exports.convertProgramNode = convertProgramNode; | ||
function cloneLocation(node) { | ||
const range = node.range; | ||
const loc = node.loc; | ||
return { | ||
range: [Math.max(range[0] - 2, 0), Math.max(range[1] - 2, 0)], | ||
range: [range[0], range[1]], | ||
loc: { | ||
start: { | ||
line: loc.start.line, | ||
column: loc.start.line === 1 | ||
? Math.max(loc.start.column - 2, 0) | ||
: loc.start.column, | ||
column: loc.start.column, | ||
}, | ||
end: { | ||
line: loc.end.line, | ||
column: loc.end.line === 1 | ||
? Math.max(loc.end.column - 2, 0) | ||
: loc.end.column, | ||
column: loc.end.column, | ||
}, | ||
@@ -431,2 +156,5 @@ }, | ||
} | ||
exports.getFixLocation = getFixLocation; | ||
function setParent(prop, parent) { | ||
; | ||
prop.parent = parent; | ||
} |
import type { Node } from "estree"; | ||
import type { TokenStore, MaybeNodeOrToken } from "./token-store"; | ||
import type { Comment } from "../types"; | ||
import type { JSONNode } from "./ast"; | ||
export declare class ParseError extends SyntaxError { | ||
@@ -8,7 +9,4 @@ index: number; | ||
column: number; | ||
static normalize(x: any): ParseError | null; | ||
constructor(message: string, offset: number, line: number, column: number); | ||
static isParseError(x: any): x is ParseError; | ||
} | ||
export declare function throwEmptyError(expected: string): never; | ||
export declare function throwExpectedTokenError(name: string, beforeToken: MaybeNodeOrToken): never; | ||
@@ -20,3 +18,2 @@ export declare function throwUnexpectedError(name: string, token: MaybeNodeOrToken): never; | ||
export declare function throwInvalidNumberError(text: string, token: MaybeNodeOrToken): never; | ||
export declare function throwUnexpectedNodeError(node: Node, tokens: TokenStore, offset?: number): never; | ||
export declare function throwErrorAsAdjustingOutsideOfCode(err: any, code: string): never; | ||
export declare function throwUnexpectedNodeError(node: Node | JSONNode, tokens: TokenStore, offset?: number): never; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.throwErrorAsAdjustingOutsideOfCode = exports.throwUnexpectedNodeError = exports.throwInvalidNumberError = exports.throwUnexpectedSpaceError = exports.throwUnexpectedCommentError = exports.throwUnexpectedTokenError = exports.throwUnexpectedError = exports.throwExpectedTokenError = exports.throwEmptyError = exports.ParseError = void 0; | ||
const convert_1 = require("./convert"); | ||
exports.throwUnexpectedNodeError = exports.throwInvalidNumberError = exports.throwUnexpectedSpaceError = exports.throwUnexpectedCommentError = exports.throwUnexpectedTokenError = exports.throwUnexpectedError = exports.throwExpectedTokenError = exports.ParseError = void 0; | ||
const utils_1 = require("./utils"); | ||
class ParseError extends SyntaxError { | ||
@@ -12,28 +12,7 @@ constructor(message, offset, line, column) { | ||
} | ||
static normalize(x) { | ||
if (ParseError.isParseError(x)) { | ||
return x; | ||
} | ||
if (isAcornStyleParseError(x)) { | ||
return new ParseError(x.message, x.pos, x.loc.line, x.loc.column); | ||
} | ||
return null; | ||
} | ||
static isParseError(x) { | ||
return (x instanceof ParseError || | ||
(typeof x.message === "string" && | ||
typeof x.index === "number" && | ||
typeof x.lineNumber === "number" && | ||
typeof x.column === "number")); | ||
} | ||
} | ||
exports.ParseError = ParseError; | ||
function throwEmptyError(expected) { | ||
const err = new ParseError(`Expected to be ${expected}, but got empty.`, 0, 1, 1); | ||
throw err; | ||
} | ||
exports.throwEmptyError = throwEmptyError; | ||
function throwExpectedTokenError(name, beforeToken) { | ||
const locs = (0, convert_1.getFixLocation)(beforeToken); | ||
const err = new ParseError(`Expected token '${name}'.`, locs.range[1], locs.loc.end.line, locs.loc.end.column + 1); | ||
const locs = getLocation(beforeToken); | ||
const err = new ParseError(`Expected token '${name}'.`, locs.end, locs.loc.end.line, locs.loc.end.column + 1); | ||
throw err; | ||
@@ -43,4 +22,4 @@ } | ||
function throwUnexpectedError(name, token) { | ||
const locs = (0, convert_1.getFixLocation)(token); | ||
const err = new ParseError(`Unexpected ${name}.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
const locs = getLocation(token); | ||
const err = new ParseError(`Unexpected ${name}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
@@ -58,4 +37,4 @@ } | ||
function throwUnexpectedSpaceError(beforeToken) { | ||
const locs = (0, convert_1.getFixLocation)(beforeToken); | ||
const err = new ParseError("Unexpected whitespace.", locs.range[1], locs.loc.end.line, locs.loc.end.column + 1); | ||
const locs = getLocation(beforeToken); | ||
const err = new ParseError("Unexpected whitespace.", locs.end, locs.loc.end.line, locs.loc.end.column + 1); | ||
throw err; | ||
@@ -65,4 +44,4 @@ } | ||
function throwInvalidNumberError(text, token) { | ||
const locs = (0, convert_1.getFixLocation)(token); | ||
const err = new ParseError(`Invalid number ${text}.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
const locs = getLocation(token); | ||
const err = new ParseError(`Invalid number ${text}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
@@ -72,11 +51,11 @@ } | ||
function throwUnexpectedNodeError(node, tokens, offset) { | ||
if (node.type === "Identifier") { | ||
const locs = (0, convert_1.getFixLocation)(node); | ||
const err = new ParseError(`Unexpected identifier '${node.name}'.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
if (node.type === "Identifier" || node.type === "JSONIdentifier") { | ||
const locs = getLocation(node); | ||
const err = new ParseError(`Unexpected identifier '${node.name}'.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
} | ||
if (node.type === "Literal") { | ||
if (node.type === "Literal" || node.type === "JSONLiteral") { | ||
const type = node.bigint | ||
? "bigint" | ||
: node.regex | ||
: (0, utils_1.isRegExpLiteral)(node) | ||
? "regex" | ||
@@ -86,9 +65,10 @@ : node.value === null | ||
: typeof node.value; | ||
const locs = (0, convert_1.getFixLocation)(node); | ||
const err = new ParseError(`Unexpected ${type} literal.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
const locs = getLocation(node); | ||
const err = new ParseError(`Unexpected ${type} literal.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
} | ||
if (node.type === "TemplateLiteral") { | ||
const locs = (0, convert_1.getFixLocation)(node); | ||
const err = new ParseError("Unexpected template literal.", locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
if (node.type === "TemplateLiteral" || | ||
node.type === "JSONTemplateLiteral") { | ||
const locs = getLocation(node); | ||
const err = new ParseError("Unexpected template literal.", locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
@@ -98,5 +78,8 @@ } | ||
node.type !== "FunctionExpression") { | ||
const name = node.type.replace(/\B([A-Z])/gu, " $1").toLowerCase(); | ||
const locs = (0, convert_1.getFixLocation)(node); | ||
const err = new ParseError(`Unexpected ${name}.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
const name = node.type | ||
.replace(/^JSON/u, "") | ||
.replace(/\B([A-Z])/gu, " $1") | ||
.toLowerCase(); | ||
const locs = getLocation(node); | ||
const err = new ParseError(`Unexpected ${name}.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
@@ -107,24 +90,13 @@ } | ||
const name = (t === null || t === void 0 ? void 0 : t.value) || "unknown"; | ||
const locs = (0, convert_1.getFixLocation)(t || node); | ||
const err = new ParseError(`Unexpected token '${name}'.`, locs.range[0], locs.loc.start.line, locs.loc.start.column + 1); | ||
const locs = getLocation(t || node); | ||
const err = new ParseError(`Unexpected token '${name}'.`, locs.start, locs.loc.start.line, locs.loc.start.column + 1); | ||
throw err; | ||
} | ||
exports.throwUnexpectedNodeError = throwUnexpectedNodeError; | ||
function throwErrorAsAdjustingOutsideOfCode(err, code) { | ||
if (ParseError.isParseError(err)) { | ||
const endOffset = code.length; | ||
if (err.index >= endOffset) { | ||
err.message = "Unexpected end of expression."; | ||
} | ||
} | ||
throw err; | ||
function getLocation(token) { | ||
var _a, _b, _c, _d; | ||
const start = (_b = (_a = token.range) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : token.start; | ||
const end = (_d = (_c = token.range) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : token.end; | ||
const loc = token.loc; | ||
return { start, end, loc }; | ||
} | ||
exports.throwErrorAsAdjustingOutsideOfCode = throwErrorAsAdjustingOutsideOfCode; | ||
function isAcornStyleParseError(x) { | ||
return (typeof x.message === "string" && | ||
typeof x.pos === "number" && | ||
typeof x.loc === "object" && | ||
x.loc !== null && | ||
typeof x.loc.line === "number" && | ||
typeof x.loc.column === "number"); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.parseForESLint = void 0; | ||
const espree_1 = require("./espree"); | ||
const errors_1 = require("./errors"); | ||
const espree_1 = require("./modules/espree"); | ||
const visitor_keys_1 = require("./visitor-keys"); | ||
@@ -10,2 +9,3 @@ const convert_1 = require("./convert"); | ||
const semver_1 = require("semver"); | ||
const extend_parser_1 = require("./extend-parser"); | ||
const DEFAULT_ECMA_VERSION = 2019; | ||
@@ -22,77 +22,29 @@ function parseForESLint(code, options) { | ||
}); | ||
try { | ||
const ast = parseJS(`0(${code}\n)`, parserOptions); | ||
const tokens = ast.tokens || []; | ||
const tokenStore = new token_store_1.TokenStore(tokens); | ||
const statement = ast.body[0]; | ||
const callExpression = statement.expression; | ||
const expression = callExpression.arguments[0]; | ||
if (!expression) { | ||
return (0, errors_1.throwEmptyError)("an expression"); | ||
} | ||
if (expression && expression.type === "SpreadElement") { | ||
return (0, errors_1.throwUnexpectedTokenError)("...", expression); | ||
} | ||
if (callExpression.arguments[1]) { | ||
const node = callExpression.arguments[1]; | ||
return (0, errors_1.throwUnexpectedTokenError)(",", tokenStore.getTokenBefore(node, token_store_1.isComma)); | ||
} | ||
tokens.shift(); | ||
tokens.shift(); | ||
tokens.pop(); | ||
const last = tokens[tokens.length - 1]; | ||
if (last && (0, token_store_1.isComma)(last)) { | ||
return (0, errors_1.throwUnexpectedTokenError)(",", last); | ||
} | ||
ast.range[1] = statement.range[1] = last.range[1]; | ||
ast.loc.end.line = statement.loc.end.line = last.loc.end.line; | ||
ast.loc.end.column = statement.loc.end.column = last.loc.end.column; | ||
ast.body = [statement]; | ||
statement.expression = expression; | ||
return { | ||
ast: postprocess(ast, tokenStore, parserOptions), | ||
visitorKeys: (0, visitor_keys_1.getVisitorKeys)(), | ||
services: { | ||
isJSON: true, | ||
}, | ||
}; | ||
parserOptions.ecmaVersion = normalizeEcmaVersion(parserOptions.ecmaVersion); | ||
const ctx = getJSONSyntaxContext(parserOptions.jsonSyntax); | ||
const tokens = []; | ||
const comments = []; | ||
const tokenStore = new token_store_1.TokenStore(tokens); | ||
const nodes = []; | ||
parserOptions.ctx = ctx; | ||
parserOptions.tokenStore = tokenStore; | ||
parserOptions.comments = comments; | ||
parserOptions.nodes = nodes; | ||
const baseAst = (0, extend_parser_1.getParser)().parseExpressionAt(code, 0, parserOptions); | ||
for (const node of nodes) { | ||
; | ||
node.type = `JSON${node.type}`; | ||
} | ||
catch (err) { | ||
return (0, errors_1.throwErrorAsAdjustingOutsideOfCode)(err, code); | ||
} | ||
const ast = (0, convert_1.convertProgramNode)(baseAst, tokenStore, ctx, code); | ||
ast.tokens = tokens; | ||
ast.comments = comments; | ||
return { | ||
ast, | ||
visitorKeys: (0, visitor_keys_1.getVisitorKeys)(), | ||
services: { | ||
isJSON: true, | ||
}, | ||
}; | ||
} | ||
exports.parseForESLint = parseForESLint; | ||
function parseJS(code, options) { | ||
const espree = (0, espree_1.getEspree)(); | ||
const ecmaVersion = normalizeEcmaVersion(espree, options.ecmaVersion); | ||
try { | ||
return espree.parse(code, Object.assign(Object.assign({}, options), { ecmaVersion })); | ||
} | ||
catch (err) { | ||
const perr = errors_1.ParseError.normalize(err); | ||
if (perr) { | ||
(0, convert_1.fixErrorLocation)(perr); | ||
throw perr; | ||
} | ||
throw err; | ||
} | ||
} | ||
function postprocess(ast, tokenStore, options) { | ||
const ctx = getJSONSyntaxContext(options === null || options === void 0 ? void 0 : options.jsonSyntax); | ||
const jsonAst = (0, convert_1.convertNode)(ast, tokenStore, ctx); | ||
const tokens = []; | ||
for (const token of ast.tokens || []) { | ||
tokens.push((0, convert_1.convertToken)(token)); | ||
} | ||
const comments = ast.comments || []; | ||
if (!ctx.comments && comments.length > 0) { | ||
return (0, errors_1.throwUnexpectedCommentError)(comments[0]); | ||
} | ||
for (const comment of comments) { | ||
(0, convert_1.fixLocation)(comment); | ||
} | ||
jsonAst.tokens = tokens; | ||
jsonAst.comments = comments; | ||
return jsonAst; | ||
} | ||
function getJSONSyntaxContext(str) { | ||
@@ -207,3 +159,4 @@ const upperCase = str === null || str === void 0 ? void 0 : str.toUpperCase(); | ||
} | ||
function normalizeEcmaVersion(espree, version) { | ||
function normalizeEcmaVersion(version) { | ||
const espree = (0, espree_1.getEspree)(); | ||
const latestEcmaVersion = getLatestEcmaVersion(espree); | ||
@@ -210,0 +163,0 @@ if (version == null || version === "latest") { |
@@ -0,2 +1,7 @@ | ||
/// <reference types="node" /> | ||
import type ModuleClass from "module"; | ||
export declare function createRequire(filename: string): ReturnType<typeof ModuleClass.createRequire>; | ||
export declare function getRequireFromLinter(): NodeRequire | null; | ||
export declare function getRequireFromCwd(): NodeRequire | null; | ||
export declare function requireFromLinter<T>(module: string): T | null; | ||
export declare function requireFromCwd<T>(module: string): T | null; |
@@ -6,3 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.requireFromCwd = exports.requireFromLinter = void 0; | ||
exports.requireFromCwd = exports.requireFromLinter = exports.getRequireFromCwd = exports.getRequireFromLinter = exports.createRequire = void 0; | ||
const path_1 = __importDefault(require("path")); | ||
@@ -22,10 +22,11 @@ function createRequire(filename) { | ||
} | ||
exports.createRequire = createRequire; | ||
function isLinterPath(p) { | ||
return (p.includes(`eslint${path_1.default.sep}lib${path_1.default.sep}linter${path_1.default.sep}linter.js`) || p.includes(`eslint${path_1.default.sep}lib${path_1.default.sep}linter.js`)); | ||
} | ||
function requireFromLinter(module) { | ||
function getRequireFromLinter() { | ||
const linterPath = Object.keys(require.cache).find(isLinterPath); | ||
if (linterPath) { | ||
try { | ||
return createRequire(linterPath)(module); | ||
return createRequire(linterPath); | ||
} | ||
@@ -37,8 +38,8 @@ catch (_a) { | ||
} | ||
exports.requireFromLinter = requireFromLinter; | ||
function requireFromCwd(module) { | ||
exports.getRequireFromLinter = getRequireFromLinter; | ||
function getRequireFromCwd() { | ||
try { | ||
const cwd = process.cwd(); | ||
const relativeTo = path_1.default.join(cwd, "__placeholder__.js"); | ||
return createRequire(relativeTo)(module); | ||
return createRequire(relativeTo); | ||
} | ||
@@ -49,2 +50,22 @@ catch (_a) { | ||
} | ||
exports.getRequireFromCwd = getRequireFromCwd; | ||
function requireFromLinter(module) { | ||
var _a; | ||
try { | ||
return (_a = getRequireFromLinter()) === null || _a === void 0 ? void 0 : _a(module); | ||
} | ||
catch (_b) { | ||
} | ||
return null; | ||
} | ||
exports.requireFromLinter = requireFromLinter; | ||
function requireFromCwd(module) { | ||
var _a; | ||
try { | ||
return (_a = getRequireFromCwd()) === null || _a === void 0 ? void 0 : _a(module); | ||
} | ||
catch (_b) { | ||
} | ||
return null; | ||
} | ||
exports.requireFromCwd = requireFromCwd; |
@@ -8,5 +8,6 @@ import type { AST } from "eslint"; | ||
export declare class TokenStore { | ||
private readonly tokens; | ||
readonly tokens: AST.Token[]; | ||
constructor(tokens: AST.Token[]); | ||
findIndexByOffset(offset: number): number; | ||
add(token: AST.Token): void; | ||
private findIndexByOffset; | ||
findTokenByOffset(offset: number): AST.Token | null; | ||
@@ -13,0 +14,0 @@ getFirstToken(nodeOrToken: MaybeNodeOrToken): AST.Token; |
@@ -8,2 +8,5 @@ "use strict"; | ||
} | ||
add(token) { | ||
this.tokens.push(token); | ||
} | ||
findIndexByOffset(offset) { | ||
@@ -10,0 +13,0 @@ return this.tokens.findIndex((token) => token.range[0] <= offset && offset < token.range[1]); |
{ | ||
"name": "jsonc-eslint-parser", | ||
"version": "1.3.1", | ||
"version": "1.4.0", | ||
"description": "JSON, JSONC and JSON5 parser for use with ESLint plugins", | ||
@@ -25,3 +25,4 @@ "main": "lib/index.js", | ||
"version": "npm run eslint-fix && git add .", | ||
"update-fixtures": "ts-node ./tools/update-fixtures.ts" | ||
"update-fixtures": "ts-node ./tools/update-fixtures.ts", | ||
"benchmark": "ts-node --transpile-only benchmark/index.ts" | ||
}, | ||
@@ -47,2 +48,3 @@ "repository": { | ||
"@ota-meshi/eslint-plugin": "^0.8.0", | ||
"@types/benchmark": "^2.1.0", | ||
"@types/eslint": "^7.2.0", | ||
@@ -57,2 +59,3 @@ "@types/eslint-visitor-keys": "^1.0.0", | ||
"@typescript-eslint/parser": "^4.0.0-0", | ||
"benchmark": "^2.1.4", | ||
"eslint": "^7.3.0", | ||
@@ -76,2 +79,3 @@ "eslint-config-prettier": "^8.0.0", | ||
"dependencies": { | ||
"acorn": "^7.4.1", | ||
"eslint-utils": "^2.1.0", | ||
@@ -78,0 +82,0 @@ "eslint-visitor-keys": "^1.3.0", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
66955
35
1584
5
28
2
+ Addedacorn@^7.4.1