});
class LocationCalculator {
- constructor(gapOffsets, ltOffsets, baseOffset) {
+ constructor(gapOffsets, ltOffsets, baseOffset, shiftOffset = 0) {
this.gapOffsets = gapOffsets;
this.ltOffsets = ltOffsets;
this.baseOffset = baseOffset || 0;
this.baseOffset === 0
? 0
: sortedLastIndex(gapOffsets, this.baseOffset);
+ this.shiftOffset = shiftOffset;
}
getSubCalculatorAfter(offset) {
- return new LocationCalculator(this.gapOffsets, this.ltOffsets, this.baseOffset + offset);
+ return new LocationCalculator(this.gapOffsets, this.ltOffsets, this.baseOffset + offset, this.shiftOffset);
+ }
+ getSubCalculatorShift(offset) {
+ return new LocationCalculator(this.gapOffsets, this.ltOffsets, this.baseOffset, this.shiftOffset + offset);
}
_getLocation(offset) {
const line = sortedLastIndex(this.ltOffsets, offset) + 1;
return g0 - this.baseIndexOfGap;
}
getLocation(index) {
- return this._getLocation(this.baseOffset + index);
+ return this._getLocation(this.baseOffset + index + this.shiftOffset);
}
getOffsetWithGap(index) {
- return this.baseOffset + index + this._getGap(index);
+ const shiftOffset = this.shiftOffset;
+ return (this.baseOffset +
+ index +
+ shiftOffset +
+ this._getGap(index + shiftOffset));
}
fixLocation(node) {
+ const shiftOffset = this.shiftOffset;
const range = node.range;
const loc = node.loc;
- const gap0 = this._getGap(range[0]);
- const gap1 = this._getGap(range[1]);
- const d0 = this.baseOffset + Math.max(0, gap0);
- const d1 = this.baseOffset + Math.max(0, gap1);
+ const gap0 = this._getGap(range[0] + shiftOffset);
+ const gap1 = this._getGap(range[1] + shiftOffset);
+ const d0 = this.baseOffset + Math.max(0, gap0) + shiftOffset;
+ const d1 = this.baseOffset + Math.max(0, gap1) + shiftOffset;
if (d0 !== 0) {
range[0] += d0;
if (node.start != null) {
return node;
}
fixErrorLocation(error) {
- const gap = this._getGap(error.index);
- const diff = this.baseOffset + Math.max(0, gap);
+ const shiftOffset = this.shiftOffset;
+ const gap = this._getGap(error.index + shiftOffset);
+ const diff = this.baseOffset + Math.max(0, gap) + shiftOffset;
error.index += diff;
const loc = this._getLocation(error.index);
error.lineNumber = loc.line;
function parseExpressionBody(code, locationCalculator, parserOptions, allowEmpty = false) {
debug('[script] parse expression: "0(%s)"', code);
try {
- const ast = parseScriptFragment(`0(${code})`, locationCalculator.getSubCalculatorAfter(-2), parserOptions).ast;
+ const ast = parseScriptFragment(`0(${code})`, locationCalculator.getSubCalculatorShift(-2), parserOptions).ast;
const tokens = ast.tokens || [];
const comments = ast.comments || [];
const references = analyzeExternalReferences(ast, parserOptions);
const argsCode = paren === -1 ? null : code.slice(paren);
if (calleeCode.trim()) {
const spaces = /^\s*/u.exec(calleeCode)[0];
- const { ast } = parseScriptFragment(`${spaces}"${calleeCode.trim()}"`, locationCalculator, parserOptions);
+ const subCalculator = locationCalculator.getSubCalculatorShift(spaces.length);
+ const { ast } = parseScriptFragment(`"${calleeCode.trim()}"`, subCalculator, parserOptions);
const statement = ast.body[0];
const callee = statement.expression;
if (callee.type !== "Literal") {
expression.callee = {
type: "Identifier",
parent: expression,
- range: [callee.range[0], callee.range[1] - 2],
+ range: [
+ callee.range[0],
+ subCalculator.getOffsetWithGap(calleeCode.trim().length),
+ ],
loc: {
start: callee.loc.start,
- end: locationCalculator.getLocation(callee.range[1] - callee.range[0] - 1),
+ end: subCalculator.getLocation(calleeCode.trim().length),
},
name: String(callee.value),
};
return throwEmptyError(locationCalculator, "a filter name");
}
if (argsCode != null) {
- const { ast } = parseScriptFragment(`0${argsCode}`, locationCalculator.getSubCalculatorAfter(paren - 1), parserOptions);
+ const { ast } = parseScriptFragment(`0${argsCode}`, locationCalculator
+ .getSubCalculatorAfter(paren)
+ .getSubCalculatorShift(-1), parserOptions);
const statement = ast.body[0];
const callExpression = statement.expression;
ast.tokens.shift();
range: [prevLoc, prevLoc + 1],
loc: {},
}));
- const retF = parseFilter(filterCode, locationCalculator.getSubCalculatorAfter(prevLoc + 1), parserOptions);
+ const retF = parseFilter(filterCode, locationCalculator.getSubCalculatorShift(prevLoc + 1), parserOptions);
if (retF) {
if (retF.expression) {
ret.expression.filters.push(retF.expression);
}
try {
const replaced = processedCode !== code;
- const ast = parseScriptFragment(`for(let ${processedCode});`, locationCalculator.getSubCalculatorAfter(-8), parserOptions).ast;
+ const ast = parseScriptFragment(`for(let ${processedCode});`, locationCalculator.getSubCalculatorShift(-8), parserOptions).ast;
const tokens = ast.tokens || [];
const comments = ast.comments || [];
const scope = analyzeVariablesAndExternalReferences(ast, parserOptions);
throwEmptyError(locationCalculator, "statements");
}
try {
- const ast = parseScriptFragment(`void function($event){${code}}`, locationCalculator.getSubCalculatorAfter(-22), parserOptions).ast;
+ const ast = parseScriptFragment(`void function($event){${code}}`, locationCalculator.getSubCalculatorShift(-22), parserOptions).ast;
const references = analyzeExternalReferences(ast, parserOptions);
const outermostStatement = ast.body[0];
const functionDecl = outermostStatement.expression
throwEmptyError(locationCalculator, "an identifier or an array/object pattern");
}
try {
- const ast = parseScriptFragment(`void function(${code}) {}`, locationCalculator.getSubCalculatorAfter(-14), parserOptions).ast;
+ const ast = parseScriptFragment(`void function(${code}) {}`, locationCalculator.getSubCalculatorShift(-14), parserOptions).ast;
const statement = ast.body[0];
const rawExpression = statement.expression;
const functionDecl = rawExpression.argument;