add end position to warnings

pull/1250/head
James Birtles 8 years ago
parent 270e1d188b
commit d07721cd50

@ -33,7 +33,7 @@ export default function a11y(
if (name.startsWith('aria-')) { if (name.startsWith('aria-')) {
if (invisibleElements.has(node.name)) { if (invisibleElements.has(node.name)) {
// aria-unsupported-elements // aria-unsupported-elements
validator.warn(`A11y: <${node.name}> should not have aria-* attributes`, attribute.start); validator.warn(`A11y: <${node.name}> should not have aria-* attributes`, { start: attribute.start, end: attribute.end });
} }
const type = name.slice(5); const type = name.slice(5);
@ -42,7 +42,7 @@ export default function a11y(
let message = `A11y: Unknown aria attribute 'aria-${type}'`; let message = `A11y: Unknown aria attribute 'aria-${type}'`;
if (match) message += ` (did you mean '${match}'?)`; if (match) message += ` (did you mean '${match}'?)`;
validator.warn(message, attribute.start); validator.warn(message, { start: attribute.start, end: attribute.end });
} }
} }
@ -50,7 +50,7 @@ export default function a11y(
if (name === 'role') { if (name === 'role') {
if (invisibleElements.has(node.name)) { if (invisibleElements.has(node.name)) {
// aria-unsupported-elements // aria-unsupported-elements
validator.warn(`A11y: <${node.name}> should not have role attribute`, attribute.start); validator.warn(`A11y: <${node.name}> should not have role attribute`, { start: attribute.start, end: attribute.end });
} }
const value = getStaticAttributeValue(node, 'role'); const value = getStaticAttributeValue(node, 'role');
@ -59,30 +59,30 @@ export default function a11y(
let message = `A11y: Unknown role '${value}'`; let message = `A11y: Unknown role '${value}'`;
if (match) message += ` (did you mean '${match}'?)`; if (match) message += ` (did you mean '${match}'?)`;
validator.warn(message, attribute.start); validator.warn(message, { start: attribute.start, end: attribute.end });
} }
} }
// no-access-key // no-access-key
if (name === 'accesskey') { if (name === 'accesskey') {
validator.warn(`A11y: Avoid using accesskey`, attribute.start); validator.warn(`A11y: Avoid using accesskey`, { start: attribute.start, end: attribute.end });
} }
// no-autofocus // no-autofocus
if (name === 'autofocus') { if (name === 'autofocus') {
validator.warn(`A11y: Avoid using autofocus`, attribute.start); validator.warn(`A11y: Avoid using autofocus`, { start: attribute.start, end: attribute.end });
} }
// scope // scope
if (name === 'scope' && node.name !== 'th') { if (name === 'scope' && node.name !== 'th') {
validator.warn(`A11y: The scope attribute should only be used with <th> elements`, attribute.start); validator.warn(`A11y: The scope attribute should only be used with <th> elements`, { start: attribute.start, end: attribute.end });
} }
// tabindex-no-positive // tabindex-no-positive
if (name === 'tabindex') { if (name === 'tabindex') {
const value = getStaticAttributeValue(node, 'tabindex'); const value = getStaticAttributeValue(node, 'tabindex');
if (!isNaN(value) && +value > 0) { if (!isNaN(value) && +value > 0) {
validator.warn(`A11y: avoid tabindex values above zero`, attribute.start); validator.warn(`A11y: avoid tabindex values above zero`, { start: attribute.start, end: attribute.end });
} }
} }
@ -96,13 +96,13 @@ export default function a11y(
attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` : attributes.slice(0, -1).join(', ') + ` or ${attributes[attributes.length - 1]}` :
attributes[0]; attributes[0];
validator.warn(`A11y: <${name}> element should have ${article} ${sequence} attribute`, node.start); validator.warn(`A11y: <${name}> element should have ${article} ${sequence} attribute`, { start: node.start, end: node.end });
} }
} }
function shouldHaveContent() { function shouldHaveContent() {
if (node.children.length === 0) { if (node.children.length === 0) {
validator.warn(`A11y: <${node.name}> element should have child content`, node.start); validator.warn(`A11y: <${node.name}> element should have child content`, { start: node.start, end: node.end });
} }
} }
@ -110,7 +110,7 @@ export default function a11y(
const href = attributeMap.get(attribute); const href = attributeMap.get(attribute);
const value = getStaticAttributeValue(node, attribute); const value = getStaticAttributeValue(node, attribute);
if (value === '' || value === '#') { if (value === '' || value === '#') {
validator.warn(`A11y: '${value}' is not a valid ${attribute} attribute`, href.start); validator.warn(`A11y: '${value}' is not a valid ${attribute} attribute`, { start: href.start, end: href.end });
} }
} }
@ -122,7 +122,7 @@ export default function a11y(
// anchor-in-svg-is-valid // anchor-in-svg-is-valid
shouldHaveValidHref('xlink:href') shouldHaveValidHref('xlink:href')
} else { } else {
validator.warn(`A11y: <a> element should have an href attribute`, node.start); validator.warn(`A11y: <a> element should have an href attribute`, { start: node.start, end: node.end });
} }
// anchor-has-content // anchor-has-content
@ -141,7 +141,8 @@ export default function a11y(
shouldHaveContent(); shouldHaveContent();
if (attributeMap.has('aria-hidden')) { if (attributeMap.has('aria-hidden')) {
validator.warn(`A11y: <${node.name}> element should not be hidden`, attributeMap.get('aria-hidden').start); const attr = attributeMap.get('aria-hidden');
validator.warn(`A11y: <${node.name}> element should not be hidden`, { start: attr.start, end: attr.end });
} }
} }
@ -157,14 +158,14 @@ export default function a11y(
// no-distracting-elements // no-distracting-elements
if (node.name === 'marquee' || node.name === 'blink') { if (node.name === 'marquee' || node.name === 'blink') {
validator.warn(`A11y: Avoid <${node.name}> elements`, node.start); validator.warn(`A11y: Avoid <${node.name}> elements`, { start: node.start, end: node.end });
} }
if (node.name === 'figcaption') { if (node.name === 'figcaption') {
const parent = elementStack[elementStack.length - 1]; const parent = elementStack[elementStack.length - 1];
if (parent) { if (parent) {
if (parent.name !== 'figure') { if (parent.name !== 'figure') {
validator.warn(`A11y: <figcaption> must be an immediate child of <figure>`, node.start); validator.warn(`A11y: <figcaption> must be an immediate child of <figure>`, { start: node.start, end: node.end });
} else { } else {
const children = parent.children.filter(node => { const children = parent.children.filter(node => {
if (node.type === 'Comment') return false; if (node.type === 'Comment') return false;
@ -175,7 +176,7 @@ export default function a11y(
const index = children.indexOf(node); const index = children.indexOf(node);
if (index !== 0 && index !== children.length - 1) { if (index !== 0 && index !== children.length - 1) {
validator.warn(`A11y: <figcaption> must be first or last child of <figure>`, node.start); validator.warn(`A11y: <figcaption> must be first or last child of <figure>`, { start: node.start, end: node.end });
} }
} }
} }

@ -52,7 +52,7 @@ export default function validateHtml(validator: Validator, html: Node) {
else if (node.type === 'EachBlock') { else if (node.type === 'EachBlock') {
if (validator.helpers.has(node.context)) { if (validator.helpers.has(node.context)) {
let c = node.expression.end; let c: number = node.expression.end;
// find start of context // find start of context
while (/\s/.test(validator.source[c])) c += 1; while (/\s/.test(validator.source[c])) c += 1;
@ -61,13 +61,13 @@ export default function validateHtml(validator: Validator, html: Node) {
validator.warn( validator.warn(
`Context clashes with a helper. Rename one or the other to eliminate any ambiguity`, `Context clashes with a helper. Rename one or the other to eliminate any ambiguity`,
c { start: c, end: c + node.context.length }
); );
} }
} }
if (validator.options.dev && isEmptyBlock(node)) { if (validator.options.dev && isEmptyBlock(node)) {
validator.warn('Empty block', node.start); validator.warn('Empty block', { start: node.start, end: node.end });
} }
if (node.children) { if (node.children) {

@ -20,13 +20,13 @@ export default function validateElement(
if (!isComponent && /^[A-Z]/.test(node.name[0])) { if (!isComponent && /^[A-Z]/.test(node.name[0])) {
// TODO upgrade to validator.error in v2 // TODO upgrade to validator.error in v2
validator.warn(`${node.name} component is not defined`, node.start); validator.warn(`${node.name} component is not defined`, { start: node.start, end: node.end });
} }
if (elementStack.length === 0 && validator.namespace !== namespaces.svg && svg.test(node.name)) { if (elementStack.length === 0 && validator.namespace !== namespaces.svg && svg.test(node.name)) {
validator.warn( validator.warn(
`<${node.name}> is an SVG element did you forget to add { namespace: 'svg' } ?`, `<${node.name}> is an SVG element did you forget to add { namespace: 'svg' } ?`,
node.start { start: node.start, end: node.end }
); );
} }

@ -30,7 +30,10 @@ export default function validateEventHandlerCallee(
if (name === 'store' && attribute.expression.callee.type === 'MemberExpression') { if (name === 'store' && attribute.expression.callee.type === 'MemberExpression') {
if (!validator.options.store) { if (!validator.options.store) {
validator.warn('compile with `store: true` in order to call store methods', attribute.expression.start); validator.warn(
'compile with `store: true` in order to call store methods',
{ start: attribute.expression.start, end: attribute.expression.end }
);
} }
return; return;
} }
@ -56,5 +59,5 @@ export default function validateEventHandlerCallee(
message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`; message += `. '${callee.name}' exists on 'helpers', did you put it in the wrong place?`;
} }
validator.warn(message, start); validator.warn(message, { start: attribute.expression.start, end: attribute.expression.end });
} }

@ -70,19 +70,21 @@ export class Validator {
throw new ValidationError(message, this.source, pos, this.filename); throw new ValidationError(message, this.source, pos, this.filename);
} }
warn(message: string, pos: number) { warn(message: string, pos: { start: number, end: number }) {
if (!this.locator) this.locator = getLocator(this.source); if (!this.locator) this.locator = getLocator(this.source);
const { line, column } = this.locator(pos); const start = this.locator(pos.start);
const end = this.locator(pos.end);
const frame = getCodeFrame(this.source, line, column); const frame = getCodeFrame(this.source, start.line, start.column);
this.onwarn({ this.onwarn({
message, message,
frame, frame,
loc: { line: line + 1, column }, loc: { line: start.line + 1, column: start.column },
pos, end: { line: end.line + 1, column: end.column },
pos: pos.start,
filename: this.filename, filename: this.filename,
toString: () => `${message} (${line + 1}:${column})\n${frame}`, toString: () => `${message} (${start.line + 1}:${start.column})\n${frame}`,
}); });
} }
} }
@ -148,7 +150,7 @@ export default function validate(
if (!validator.used[category].has(name)) { if (!validator.used[category].has(name)) {
validator.warn( validator.warn(
`The '${name}' ${categories[category]} is unused`, `The '${name}' ${categories[category]} is unused`,
prop.start { start: prop.start, end: prop.end }
); );
} }
}); });

@ -26,7 +26,7 @@ export default function components(validator: Validator, prop: Node) {
} }
if (!/^[A-Z]/.test(name)) { if (!/^[A-Z]/.test(name)) {
validator.warn(`Component names should be capitalised`, component.start); validator.warn(`Component names should be capitalised`, { start: component.start, end: component.end });
} }
}); });
} }

@ -43,7 +43,7 @@ export default function helpers(validator: Validator, prop: Node) {
if (prop.value.params.length === 0 && !usesArguments) { if (prop.value.params.length === 0 && !usesArguments) {
validator.warn( validator.warn(
`Helpers should be pure functions, with at least one argument`, `Helpers should be pure functions, with at least one argument`,
prop.start { start: prop.start, end: prop.end }
); );
} }
}); });

@ -5,7 +5,7 @@ import { Node } from '../../../interfaces';
export default function onrender(validator: Validator, prop: Node) { export default function onrender(validator: Validator, prop: Node) {
validator.warn( validator.warn(
`'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x`, `'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x`,
prop.start { start: prop.start, end: prop.end }
); );
oncreate(validator, prop); oncreate(validator, prop);
} }

@ -5,7 +5,7 @@ import { Node } from '../../../interfaces';
export default function onteardown(validator: Validator, prop: Node) { export default function onteardown(validator: Validator, prop: Node) {
validator.warn( validator.warn(
`'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x`, `'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x`,
prop.start { start: prop.start, end: prop.end }
); );
ondestroy(validator, prop); ondestroy(validator, prop);
} }

@ -31,7 +31,8 @@ describe("validate", () => {
warnings.push({ warnings.push({
message: warning.message, message: warning.message,
pos: warning.pos, pos: warning.pos,
loc: warning.loc loc: warning.loc,
end: warning.end,
}); });
}, },
dev: config.dev dev: config.dev

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 19
},
"pos": 0 "pos": 0
}, },
@ -14,6 +18,10 @@
"line": 4, "line": 4,
"column": 1 "column": 1
}, },
"end": {
"line": 4,
"column": 7
},
"pos": 28 "pos": 28
}, },
@ -23,6 +31,10 @@
"line": 7, "line": 7,
"column": 0 "column": 0
}, },
"end": {
"line": 7,
"column": 17
},
"pos": 43 "pos": 43
}, },
@ -32,6 +44,10 @@
"line": 9, "line": 9,
"column": 0 "column": 0
}, },
"end": {
"line": 9,
"column": 20
},
"pos": 62 "pos": 62
} }
] ]

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

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 11 "column": 11
}, },
"end": {
"line": 1,
"column": 37
},
"pos": 11 "pos": 11
}, },
{ {
@ -13,6 +17,10 @@
"line": 2, "line": 2,
"column": 14 "column": 14
}, },
"end": {
"line": 2,
"column": 27
},
"pos": 65 "pos": 65
}, },
{ {
@ -21,6 +29,10 @@
"line": 3, "line": 3,
"column": 14 "column": 14
}, },
"end": {
"line": 3,
"column": 28
},
"pos": 130 "pos": 130
} }
] ]

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 26
},
"pos": 0 "pos": 0
}, },
{ {
@ -13,6 +17,10 @@
"line": 2, "line": 2,
"column": 3 "column": 3
}, },
"end": {
"line": 2,
"column": 10
},
"pos": 30 "pos": 30
}, },
{ {
@ -21,6 +29,10 @@
"line": 3, "line": 3,
"column": 3 "column": 3
}, },
"end": {
"line": 3,
"column": 11
},
"pos": 53 "pos": 53
} }
] ]

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 20 "column": 20
}, },
"end": {
"line": 1,
"column": 40
},
"pos": 20 "pos": 20
}, },
@ -14,6 +18,10 @@
"column": 0, "column": 0,
"line": 1 "line": 1
}, },
"end": {
"line": 1,
"column": 41
},
"pos": 0 "pos": 0
} }
] ]

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

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 6 "column": 6
}, },
"end": {
"line": 1,
"column": 25
},
"pos": 6 "pos": 6
}, },
@ -14,6 +18,10 @@
"line": 2, "line": 2,
"column": 6 "column": 6
}, },
"end": {
"line": 2,
"column": 20
},
"pos": 33 "pos": 33
} }
] ]

@ -5,6 +5,10 @@
"line": 4, "line": 4,
"column": 1 "column": 1
}, },
"end": {
"line": 6,
"column": 14
},
"pos": 57 "pos": 57
}, },
{ {
@ -13,6 +17,10 @@
"line": 15, "line": 15,
"column": 2 "column": 2
}, },
"end": {
"line": 17,
"column": 15
},
"pos": 252 "pos": 252
} }
] ]

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 9
},
"pos": 0 "pos": 0
}, },
@ -14,6 +18,10 @@
"line": 2, "line": 2,
"column": 4 "column": 4
}, },
"end": {
"line": 2,
"column": 15
},
"pos": 14 "pos": 14
} }
] ]

@ -4,6 +4,10 @@
"column": 0, "column": 0,
"line": 5 "line": 5
}, },
"end": {
"line": 5,
"column": 13
},
"message": "A11y: <html> element should have a lang attribute", "message": "A11y: <html> element should have a lang attribute",
"pos": 84 "pos": 84
} }

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 31
},
"pos": 0 "pos": 0
} }
] ]

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

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

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 10
},
"pos": 0 "pos": 0
}, },
@ -14,6 +18,10 @@
"line": 2, "line": 2,
"column": 0 "column": 0
}, },
"end": {
"line": 2,
"column": 8
},
"pos": 11 "pos": 11
} }
] ]

@ -5,6 +5,10 @@
"column": 8, "column": 8,
"line": 2 "line": 2
}, },
"end": {
"line": 2,
"column": 17
},
"pos": 29 "pos": 29
} }
] ]

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

@ -5,6 +5,10 @@
"line": 3, "line": 3,
"column": 5 "column": 5
}, },
"end": {
"line": 3,
"column": 17
},
"pos": 46 "pos": 46
} }
] ]

@ -5,6 +5,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 3,
"column": 9
},
"pos": 0 "pos": 0
}, },
{ {
@ -13,6 +17,10 @@
"line": 5, "line": 5,
"column": 0 "column": 0
}, },
"end": {
"line": 5,
"column": 34
},
"pos": 38 "pos": 38
} }
] ]

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

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

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

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

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

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

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

@ -4,6 +4,10 @@
"line": 1, "line": 1,
"column": 0 "column": 0
}, },
"end": {
"line": 1,
"column": 65
},
"pos": 0 "pos": 0
}, },
{ {
@ -12,6 +16,10 @@
"column": 1, "column": 1,
"line": 5 "line": 5
}, },
"end": {
"line": 5,
"column": 66
},
"pos": 90 "pos": 90
}, },
{ {
@ -20,6 +28,10 @@
"column": 2, "column": 2,
"line": 10 "line": 10
}, },
"end": {
"line": 10,
"column": 67
},
"pos": 191 "pos": 191
}, },
{ {
@ -28,6 +40,10 @@
"column": 2, "column": 2,
"line": 20 "line": 20
}, },
"end": {
"line": 20,
"column": 67
},
"pos": 333 "pos": 333
}, },
{ {
@ -36,5 +52,9 @@
"column": 2, "column": 2,
"line": 26 "line": 26
}, },
"end": {
"line": 26,
"column": 67
},
"pos": 445 "pos": 445
}] }]

@ -5,6 +5,10 @@
"line": 7, "line": 7,
"column": 3 "column": 3
}, },
"end": {
"line": 7,
"column": 6
},
"pos": 109 "pos": 109
}, },
{ {
@ -13,6 +17,10 @@
"line": 8, "line": 8,
"column": 3 "column": 3
}, },
"end": {
"line": 8,
"column": 6
},
"pos": 117 "pos": 117
} }
] ]

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

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

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

Loading…
Cancel
Save