add end position to errors

pull/1250/head
James Birtles 7 years ago
parent d07721cd50
commit da6a74016f

@ -102,7 +102,7 @@ export default class Selector {
while (i-- > 1) {
const selector = block.selectors[i];
if (selector.type === 'PseudoClassSelector' && selector.name === 'global') {
validator.error(`:global(...) must be the first element in a compound selector`, selector.start);
validator.error(`:global(...) must be the first element in a compound selector`, { start: selector.start, end: selector.end });
}
}
});
@ -120,7 +120,8 @@ export default class Selector {
for (let i = start; i < end; i += 1) {
if (this.blocks[i].global) {
validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, this.blocks[i].selectors[0].start);
const selector = this.blocks[i].selectors[0];
validator.error(`:global(...) can be at the start or end of a selector sequence, but not in the middle`, { start: selector.start, end: selector.end });
}
}
}

@ -4,24 +4,28 @@ import getCodeFrame from '../utils/getCodeFrame';
export default class CompileError extends Error {
frame: string;
loc: { line: number; column: number };
end: { line: number; column: number };
pos: number;
filename: string;
constructor(
message: string,
template: string,
index: number,
filename: string
startPos: number,
filename: string,
endPos: number = startPos
) {
super(message);
const { line, column } = locate(template, index);
const start = locate(template, startPos);
const end = locate(template, endPos);
this.loc = { line: line + 1, column };
this.pos = index;
this.loc = { line: start.line + 1, column: start.column };
this.end = { line: end.line + 1, column: end.column };
this.pos = startPos;
this.filename = filename;
this.frame = getCodeFrame(template, line, column);
this.frame = getCodeFrame(template, start.line, start.column);
}
public toString = () => {

@ -103,7 +103,7 @@ export default function validateHtml(validator: Validator, html: Node) {
let message = `'refs.${ref}' does not exist`;
if (match) message += ` (did you mean 'refs.${match}'?)`;
validator.error(message, callee.start);
validator.error(message, { start: callee.start, end: callee.end });
}
});
}

@ -34,12 +34,12 @@ export default function validateElement(
const nameAttribute = node.attributes.find((attribute: Node) => attribute.name === 'name');
if (nameAttribute) {
if (nameAttribute.value.length !== 1 || nameAttribute.value[0].type !== 'Text') {
validator.error(`<slot> name cannot be dynamic`, nameAttribute.start);
validator.error(`<slot> name cannot be dynamic`, { start: nameAttribute.start, end: nameAttribute.end });
}
const slotName = nameAttribute.value[0].data;
if (slotName === 'default') {
validator.error(`default is a reserved word — it cannot be used as a slot name`, nameAttribute.start);
validator.error(`default is a reserved word — it cannot be used as a slot name`, { start: nameAttribute.start, end: nameAttribute.end });
}
// TODO should duplicate slots be disallowed? Feels like it's more likely to be a
@ -61,9 +61,10 @@ export default function validateElement(
if (node.name === 'title') {
if (node.attributes.length > 0) {
const attr = node.attributes[0];
validator.error(
`<title> cannot have attributes`,
node.attributes[0].start
{ start: attr.start, end: attr.end }
);
}
@ -71,7 +72,7 @@ export default function validateElement(
if (child.type !== 'Text' && child.type !== 'MustacheTag') {
validator.error(
`<title> can only contain text and {{tags}}`,
child.start
{ start: child.start, end: child.end }
);
}
});
@ -98,7 +99,7 @@ export default function validateElement(
) {
validator.error(
`'value' is not a valid binding on <${node.name}> elements`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -107,21 +108,21 @@ export default function validateElement(
if (node.name !== 'input') {
validator.error(
`'${name}' is not a valid binding on <${node.name}> elements`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
if (checkTypeAttribute(validator, node) !== 'checkbox') {
validator.error(
`'${name}' binding can only be used with <input type="checkbox">`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
} else if (name === 'group') {
if (node.name !== 'input') {
validator.error(
`'group' is not a valid binding on <${node.name}> elements`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -130,7 +131,7 @@ export default function validateElement(
if (type !== 'checkbox' && type !== 'radio') {
validator.error(
`'checked' binding can only be used with <input type="checkbox"> or <input type="radio">`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
} else if (
@ -145,13 +146,13 @@ export default function validateElement(
if (node.name !== 'audio' && node.name !== 'video') {
validator.error(
`'${name}' binding can only be used with <audio> or <video>`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
} else {
validator.error(
`'${attribute.name}' is not a valid binding`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
} else if (attribute.type === 'EventHandler') {
@ -159,7 +160,7 @@ export default function validateElement(
validateEventHandler(validator, attribute, refCallees);
} else if (attribute.type === 'Transition') {
if (isComponent) {
validator.error(`Transitions can only be applied to DOM elements, not components`, attribute.start);
validator.error(`Transitions can only be applied to DOM elements, not components`, { start: attribute.start, end: attribute.end });
}
validator.used.transitions.add(attribute.name);
@ -170,13 +171,13 @@ export default function validateElement(
if (bidi)
validator.error(
`An element can only have one 'transition' directive`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
validator.error(
`An element cannot have both a 'transition' directive and an '${attribute.intro
? 'in'
: 'out'}' directive`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -186,11 +187,11 @@ export default function validateElement(
`An element cannot have both an '${hasIntro
? 'in'
: 'out'}' directive and a 'transition' directive`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
validator.error(
`An element can only have one '${hasIntro ? 'in' : 'out'}' directive`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -201,7 +202,7 @@ export default function validateElement(
if (!validator.transitions.has(attribute.name)) {
validator.error(
`Missing transition '${attribute.name}'`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
} else if (attribute.type === 'Attribute') {
@ -209,7 +210,7 @@ export default function validateElement(
if (node.children.length) {
validator.error(
`A <textarea> can have either a value attribute or (equivalently) child content, but not both`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
}
@ -228,13 +229,13 @@ function checkTypeAttribute(validator: Validator, node: Node) {
if (!attribute) return null;
if (attribute.value === true) {
validator.error(`'type' attribute must be specified`, attribute.start);
validator.error(`'type' attribute must be specified`, { start: attribute.start, end: attribute.end });
}
if (isDynamic(attribute)) {
validator.error(
`'type' attribute cannot be dynamic if input uses two-way binding`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -245,7 +246,7 @@ function checkSlotAttribute(validator: Validator, node: Node, attribute: Node, s
if (isDynamic(attribute)) {
validator.error(
`slot attribute cannot have a dynamic value`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
@ -260,11 +261,11 @@ function checkSlotAttribute(validator: Validator, node: Node, attribute: Node, s
if (parent.type === 'IfBlock' || parent.type === 'EachBlock') {
const message = `Cannot place slotted elements inside an ${parent.type === 'IfBlock' ? 'if' : 'each'}-block`;
validator.error(message, attribute.start);
validator.error(message, { start: attribute.start, end: attribute.end });
}
}
validator.error(`Element with a slot='...' attribute must be a descendant of a component or custom element`, attribute.start);
validator.error(`Element with a slot='...' attribute must be a descendant of a component or custom element`, { start: attribute.start, end: attribute.end });
}
function isDynamic(attribute: Node) {

@ -13,10 +13,10 @@ export default function validateEventHandlerCallee(
) {
if (!attribute.expression) return;
const { callee, start, type } = attribute.expression;
const { callee, type } = attribute.expression;
if (type !== 'CallExpression') {
validator.error(`Expected a call expression`, start);
validator.error(`Expected a call expression`, { start: attribute.expression.start, end: attribute.expression.end });
}
const { name } = flattenReference(callee);

@ -4,7 +4,7 @@ import { Node } from '../../interfaces';
export default function validateHead(validator: Validator, node: Node, refs: Map<string, Node[]>, refCallees: Node[]) {
if (node.attributes.length) {
validator.error(`<:Head> should not have any attributes or directives`, node.start);
validator.error(`<:Head> should not have any attributes or directives`, { start: node.start, end: node.end });
}
// TODO ensure only valid elements are included here

@ -25,7 +25,7 @@ export default function validateWindow(validator: Validator, node: Node, refs: M
`Bindings on <:Window/> must be to top-level properties, e.g. '${parts[
parts.length - 1
]}' rather than '${parts.join('.')}'`,
attribute.value.start
{ start: attribute.value.start, end: attribute.value.end }
);
}
@ -41,12 +41,12 @@ export default function validateWindow(validator: Validator, node: Node, refs: M
if (match) {
validator.error(
`${message} (did you mean '${match}'?)`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
} else {
validator.error(
`${message} — valid bindings are ${list(validBindings)}`,
attribute.start
{ start: attribute.start, end: attribute.end }
);
}
}

@ -10,10 +10,10 @@ class ValidationError extends CompileError {
constructor(
message: string,
template: string,
index: number,
filename: string
pos: { start: number, end: number },
filename: string,
) {
super(message, template, index, filename);
super(message, template, pos.start, filename, pos.end);
this.name = 'ValidationError';
}
}
@ -66,7 +66,7 @@ export class Validator {
};
}
error(message: string, pos: number) {
error(message: string, pos: { start: number, end: number }) {
throw new ValidationError(message, this.source, pos, this.filename);
}

@ -13,14 +13,14 @@ export default function validateJs(validator: Validator, js: Node) {
js.content.body.forEach((node: Node) => {
// check there are no named exports
if (node.type === 'ExportNamedDeclaration') {
validator.error(`A component can only have a default export`, node.start);
validator.error(`A component can only have a default export`, { start: node.start, end: node.start });
}
if (node.type === 'ExportDefaultDeclaration') {
if (node.declaration.type !== 'ObjectExpression') {
return validator.error(
`Default export must be an object literal`,
node.declaration.start
{ start: node.declaration.start, end: node.declaration.end }
);
}
@ -35,16 +35,18 @@ export default function validateJs(validator: Validator, js: Node) {
// Remove these checks in version 2
if (props.has('oncreate') && props.has('onrender')) {
const onrender = props.get('onrender');
validator.error(
'Cannot have both oncreate and onrender',
props.get('onrender').start
{ start: onrender.start, end: onrender.end }
);
}
if (props.has('ondestroy') && props.has('onteardown')) {
const onteardown = props.get('onteardown');
validator.error(
'Cannot have both ondestroy and onteardown',
props.get('onteardown').start
{ start: onteardown.start, end: onteardown.end }
);
}
@ -60,17 +62,17 @@ export default function validateJs(validator: Validator, js: Node) {
if (match) {
validator.error(
`Unexpected property '${name}' (did you mean '${match}'?)`,
prop.start
{ start: prop.start, end: prop.end }
);
} else if (/FunctionExpression/.test(prop.value.type)) {
validator.error(
`Unexpected property '${name}' (did you mean to include it in 'methods'?)`,
prop.start
{ start: prop.start, end: prop.end }
);
} else {
validator.error(
`Unexpected property '${name}'`,
prop.start
{ start: prop.start, end: prop.end }
);
}
}

@ -8,7 +8,7 @@ export default function components(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'components' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -21,7 +21,7 @@ export default function components(validator: Validator, prop: Node) {
if (name === 'state') {
validator.error(
`Component constructors cannot be called 'state' due to technical limitations`,
component.start
{ start: component.start, end: component.end }
);
}

@ -17,7 +17,7 @@ export default function computed(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'computed' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -31,21 +31,21 @@ export default function computed(validator: Validator, prop: Node) {
const suggestion = name.replace(/[^_$a-z0-9]/ig, '_').replace(/^\d/, '_$&');
validator.error(
`Computed property name '${name}' is invalid — must be a valid identifier such as ${suggestion}`,
computation.start
{ start: computation.start, end: computation.end }
);
}
if (reservedNames.has(name)) {
validator.error(
`Computed property name '${name}' is invalid — cannot be a JavaScript reserved word`,
computation.start
{ start: computation.start, end: computation.end }
);
}
if (!isFunctionExpression.has(computation.value.type)) {
validator.error(
`Computed properties can be function expressions or arrow function expressions`,
computation.value.start
{ start: computation.value.start, end: computation.value.end }
);
}
@ -55,14 +55,14 @@ export default function computed(validator: Validator, prop: Node) {
if (isThisGetCallExpression(node) && !node.callee.property.computed) {
validator.error(
`Cannot use this.get(...) — values must be passed into the function as arguments`,
node.start
{ start: node.start, end: node.end }
);
}
if (node.type === 'ThisExpression') {
validator.error(
`Computed properties should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`,
node.start
{ start: node.start, end: node.end }
);
}
});
@ -70,7 +70,7 @@ export default function computed(validator: Validator, prop: Node) {
if (params.length === 0) {
validator.error(
`A computed value must depend on at least one property`,
computation.value.start
{ start: computation.value.start, end: computation.value.end }
);
}
@ -83,7 +83,7 @@ export default function computed(validator: Validator, prop: Node) {
if (!valid) {
validator.error(
`Computed properties cannot use destructuring in function parameters`,
param.start
{ start: param.start, end: param.end }
);
}
});

@ -7,6 +7,6 @@ export default function data(validator: Validator, prop: Node) {
while (prop.type === 'ParenthesizedExpression') prop = prop.expression;
if (disallowed.has(prop.value.type)) {
validator.error(`'data' must be a function`, prop.value.start);
validator.error(`'data' must be a function`, { start: prop.value.start, end: prop.value.end });
}
}

@ -7,7 +7,7 @@ export default function events(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'events' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}

@ -10,7 +10,7 @@ export default function helpers(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'helpers' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -26,14 +26,14 @@ export default function helpers(validator: Validator, prop: Node) {
if (isThisGetCallExpression(node) && !node.callee.property.computed) {
validator.error(
`Cannot use this.get(...) — values must be passed into the helper function as arguments`,
node.start
{ start: node.start, end: node.end }
);
}
if (node.type === 'ThisExpression') {
validator.error(
`Helpers should be pure functions — they do not have access to the component instance and cannot use 'this'. Did you mean to put this in 'methods'?`,
node.start
{ start: node.start, end: node.end }
);
} else if (node.type === 'Identifier' && node.name === 'arguments') {
usesArguments = true;

@ -5,7 +5,7 @@ export default function immutable(validator: Validator, prop: Node) {
if (prop.value.type !== 'Literal' || typeof prop.value.value !== 'boolean') {
validator.error(
`'immutable' must be a boolean literal`,
prop.value.start
{ start: prop.value.start, end: prop.value.end }
);
}
}

@ -12,7 +12,7 @@ export default function methods(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'methods' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -26,7 +26,7 @@ export default function methods(validator: Validator, prop: Node) {
if (builtin.has(name)) {
validator.error(
`Cannot overwrite built-in method '${name}'`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -35,7 +35,7 @@ export default function methods(validator: Validator, prop: Node) {
validator.error(
`Method '${prop.key
.name}' should be a function expression, not an arrow function expression`,
prop.start
{ start: prop.start, end: prop.end }
);
}
}

@ -11,7 +11,7 @@ export default function namespace(validator: Validator, prop: Node) {
if (prop.value.type !== 'Literal' || typeof ns !== 'string') {
validator.error(
`The 'namespace' property must be a string literal representing a valid namespace`,
prop.start
{ start: prop.start, end: prop.end }
);
}
@ -20,10 +20,10 @@ export default function namespace(validator: Validator, prop: Node) {
if (match) {
validator.error(
`Invalid namespace '${ns}' (did you mean '${match}'?)`,
prop.start
{ start: prop.start, end: prop.end }
);
} else {
validator.error(`Invalid namespace '${ns}'`, prop.start);
validator.error(`Invalid namespace '${ns}'`, { start: prop.start, end: prop.end });
}
}
}

@ -7,7 +7,7 @@ export default function oncreate(validator: Validator, prop: Node) {
if (usesThisOrArguments(prop.value.body)) {
validator.error(
`'oncreate' should be a function expression, not an arrow function expression`,
prop.start
{ start: prop.start, end: prop.end }
);
}
}

@ -7,7 +7,7 @@ export default function ondestroy(validator: Validator, prop: Node) {
if (usesThisOrArguments(prop.value.body)) {
validator.error(
`'ondestroy' should be a function expression, not an arrow function expression`,
prop.start
{ start: prop.start, end: prop.end }
);
}
}

@ -5,7 +5,7 @@ export default function props(validator: Validator, prop: Node) {
if (prop.value.type !== 'ArrayExpression') {
validator.error(
`'props' must be an array expression, if specified`,
prop.value.start
{ start: prop.value.start, end: prop.value.end }
);
}
@ -13,7 +13,7 @@ export default function props(validator: Validator, prop: Node) {
if (element.type !== 'Literal' || typeof element.value !== 'string') {
validator.error(
`'props' must be an array of string literals`,
element.start
{ start: element.start, end: element.end }
);
}
});

@ -7,6 +7,6 @@ export default function setup(validator: Validator, prop: Node) {
while (prop.type === 'ParenthesizedExpression') prop = prop.expression;
if (disallowed.has(prop.value.type)) {
validator.error(`'setup' must be a function`, prop.value.start);
validator.error(`'setup' must be a function`, { start: prop.value.start, end: prop.value.end });
}
}

@ -5,7 +5,7 @@ export default function tag(validator: Validator, prop: Node) {
if (prop.value.type !== 'Literal' || typeof prop.value.value !== 'string') {
validator.error(
`'tag' must be a string literal`,
prop.value.start
{ start: prop.value.start, end: prop.value.end }
);
}
@ -13,7 +13,7 @@ export default function tag(validator: Validator, prop: Node) {
if (!/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
validator.error(
`tag name must be two or more words joined by the '-' character`,
prop.value.start
{ start: prop.value.start, end: prop.value.end }
);
}
}

@ -7,7 +7,7 @@ export default function transitions(validator: Validator, prop: Node) {
if (prop.value.type !== 'ObjectExpression') {
validator.error(
`The 'transitions' property must be an object literal`,
prop.start
{ start: prop.start, end: prop.end }
);
}

@ -8,7 +8,7 @@ export default function checkForAccessors(
) {
properties.forEach(prop => {
if (prop.kind !== 'init') {
validator.error(`${label} cannot use getters and setters`, prop.start);
validator.error(`${label} cannot use getters and setters`, { start: prop.start, end: prop.end });
}
});
}

@ -7,7 +7,7 @@ export default function checkForComputedKeys(
) {
properties.forEach(prop => {
if (prop.key.computed) {
validator.error(`Cannot use computed keys`, prop.start);
validator.error(`Cannot use computed keys`, { start: prop.start, end: prop.end });
}
});
}

@ -12,7 +12,7 @@ export default function checkForDupes(
const name = getName(prop.key);
if (seen.has(name)) {
validator.error(`Duplicate property '${name}'`, prop.start);
validator.error(`Duplicate property '${name}'`, { start: prop.start, end: prop.end });
}
seen.add(name);

@ -56,6 +56,7 @@ describe("validate", () => {
assert.equal(error.message, expected.message);
assert.deepEqual(error.loc, expected.loc);
assert.deepEqual(error.end, expected.end);
assert.equal(error.pos, expected.pos);
}
});

@ -4,5 +4,9 @@
"line": 1,
"column": 7
},
"end": {
"line": 1,
"column": 25
},
"pos": 7
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 24
},
"end": {
"line": 1,
"column": 28
},
"pos": 24
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 24
},
"end": {
"line": 1,
"column": 44
},
"pos": 24
}]

@ -4,5 +4,9 @@
"loc": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 15
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 18
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 6,
"column": 3
},
"end": {
"line": 6,
"column": 8
}
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 20
},
"pos": 6
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 9
},
"end": {
"line": 2,
"column": 23
},
"pos": 18
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 6
},
"end": {
"line": 1,
"column": 20
},
"pos": 6
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 1
},
"pos": 27
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 7
},
"end": {
"line": 3,
"column": 17
},
"pos": 43
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 7
},
"end": {
"line": 3,
"column": 17
},
"pos": 31
}]

@ -4,5 +4,9 @@
"loc": {
"line": 7,
"column": 4
},
"end": {
"line": 7,
"column": 8
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 7,
"column": 11
},
"end": {
"line": 7,
"column": 28
}
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 6
},
"end": {
"line": 2,
"column": 19
},
"pos": 14
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 5
},
"end": {
"line": 2,
"column": 18
},
"pos": 13
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 18
},
"end": {
"line": 1,
"column": 18
},
"pos": 18
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 17
},
"end": {
"line": 1,
"column": 17
},
"pos": 17
}]

@ -4,5 +4,9 @@
"loc": {
"line": 2,
"column": 18
},
"end": {
"line": 2,
"column": 35
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 3,
"column": 8
},
"end": {
"line": 3,
"column": 8
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 2,
"column": 16
},
"end": {
"line": 2,
"column": 22
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 7,
"column": 4
},
"end": {
"line": 7,
"column": 8
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 7,
"column": 11
},
"end": {
"line": 7,
"column": 28
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 6,
"column": 3
},
"end": {
"line": 8,
"column": 4
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 2,
"column": 1
},
"end": {
"line": 2,
"column": 1
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 18
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 41
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 11
}
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 37
},
"pos": 29
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 33
},
"pos": 29
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 34
},
"pos": 29
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 34
},
"pos": 29
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 2
},
"end": {
"line": 3,
"column": 38
},
"pos": 29
}]

@ -4,5 +4,9 @@
"loc": {
"line": 3,
"column": 2
},
"end": {
"line": 5,
"column": 3
}
}]

@ -4,5 +4,9 @@
"loc": {
"line": 3,
"column": 2
},
"end": {
"line": 5,
"column": 3
}
}]

@ -5,5 +5,9 @@
"line": 9,
"column": 3
},
"end": {
"line": 9,
"column": 18
},
"pos": 87
}]

@ -4,5 +4,9 @@
"line": 5,
"column": 2
},
"end": {
"line": 5,
"column": 23
},
"pos": 42
}]

@ -4,5 +4,9 @@
"line": 6,
"column": 8
},
"end": {
"line": 6,
"column": 20
},
"pos": 62
}]

@ -4,5 +4,9 @@
"line": 9,
"column": 3
},
"end": {
"line": 9,
"column": 28
},
"pos": 87
}]

@ -4,5 +4,9 @@
"line": 6,
"column": 8
},
"end": {
"line": 6,
"column": 16
},
"pos": 62
}]

@ -4,5 +4,9 @@
"loc": {
"line": 4,
"column": 8
},
"end": {
"line": 4,
"column": 16
}
}]

@ -4,5 +4,9 @@
"line": 5,
"column": 8
},
"end": {
"line": 7,
"column": 3
},
"pos": 48
}]

@ -4,5 +4,9 @@
"line": 9,
"column": 2
},
"end": {
"line": 11,
"column": 3
},
"pos": 74
}]

@ -4,5 +4,9 @@
"line": 4,
"column": 3
},
"end": {
"line": 6,
"column": 4
},
"pos": 43
}]

@ -4,5 +4,9 @@
"line": 5,
"column": 2
},
"end": {
"line": 7,
"column": 3
},
"pos": 42
}]

@ -4,5 +4,9 @@
"line": 5,
"column": 2
},
"end": {
"line": 9,
"column": 3
},
"pos": 42
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 15
},
"pos": 5
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 7
},
"end": {
"line": 3,
"column": 16
},
"pos": 34
}]

@ -4,5 +4,9 @@
"line": 3,
"column": 7
},
"end": {
"line": 3,
"column": 9
},
"pos": 34
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 10
},
"end": {
"line": 1,
"column": 25
},
"pos": 10
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 8
},
"end": {
"line": 2,
"column": 25
},
"pos": 16
}]

@ -4,5 +4,9 @@
"line": 2,
"column": 11
},
"end": {
"line": 2,
"column": 35
},
"pos": 19
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 26
},
"pos": 12
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 12
},
"end": {
"line": 1,
"column": 18
},
"pos": 12
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 27
},
"pos": 13
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 13
},
"end": {
"line": 1,
"column": 20
},
"pos": 13
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 26
},
"pos": 20
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 27
},
"pos": 20
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 20
},
"end": {
"line": 1,
"column": 34
},
"pos": 20
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 5
},
"end": {
"line": 1,
"column": 11
},
"pos": 5
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 8
},
"end": {
"line": 1,
"column": 14
},
"pos": 8
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 28
},
"pos": 9
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 26
},
"end": {
"line": 1,
"column": 37
},
"pos": 26
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 23
},
"pos": 9
}]

@ -4,5 +4,9 @@
"line": 1,
"column": 9
},
"end": {
"line": 1,
"column": 26
},
"pos": 9
}]
Loading…
Cancel
Save