Skip to content

Commit

Permalink
Merge branch 'master' into gh-1197
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Apr 15, 2018
2 parents 33afb7e + 7fe139f commit 410f44d
Show file tree
Hide file tree
Showing 197 changed files with 800 additions and 394 deletions.
10 changes: 8 additions & 2 deletions src/css/Selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ 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);
validator.error(selector, {
code: `css-invalid-global`,
message: `:global(...) must be the first element in a compound selector`
});
}
}
});
Expand All @@ -120,7 +123,10 @@ 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]);
validator.error(this.blocks[i].selectors[0], {
code: `css-invalid-global`,
message: `:global(...) can be at the start or end of a selector sequence, but not in the middle`
});
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/css/Stylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ export default class Stylesheet {
const message = `Unused CSS selector`;

onwarn({
code: `css-unused-selector`,
message,
frame,
loc: { line: line + 1, column },
Expand Down
1 change: 1 addition & 0 deletions src/generators/wrapModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ function getGlobals(dependencies: Dependency[], options: CompileOptions) {
onerror(error);
} else {
const warning = {
code: `options-missing-globals`,
message: `No name was supplied for imported module '${d.source}'. Guessing '${d.name}', but you should use options.globals`,
};

Expand Down
1 change: 1 addition & 0 deletions src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface Warning {
loc?: { line: number; column: number; pos?: number };
end?: { line: number; column: number; };
pos?: number;
code: string;
message: string;
filename?: string;
frame?: string;
Expand Down
40 changes: 32 additions & 8 deletions src/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,19 @@ export class Parser {
const current = this.current();

const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
this.error(`${type} was left open`, current.start);
const slug = current.type === 'Element' ? 'element' : 'block';

this.error({
code: `unclosed-${slug}`,
message: `${type} was left open`
}, current.start);
}

if (state !== fragment) {
this.error('Unexpected end of input');
this.error({
code: `unexpected-eof`,
message: 'Unexpected end of input'
});
}

if (this.html.children.length) {
Expand All @@ -97,12 +105,16 @@ export class Parser {
}

acornError(err: any) {
this.error(err.message.replace(/ \(\d+:\d+\)$/, ''), err.pos);
this.error({
code: `parse-error`,
message: err.message.replace(/ \(\d+:\d+\)$/, '')
}, err.pos);
}

error(message: string, index = this.index) {
error({ code, message }: { code: string, message: string }, index = this.index) {
error(message, {
name: 'ParseError',
code,
source: this.template,
start: index,
filename: this.filename
Expand All @@ -116,7 +128,10 @@ export class Parser {
}

if (required) {
this.error(message || `Expected ${str}`);
this.error({
code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
message: message || `Expected ${str}`
});
}

return false;
Expand Down Expand Up @@ -164,15 +179,21 @@ export class Parser {
const identifier = this.template.slice(this.index, this.index = i);

if (reservedNames.has(identifier)) {
this.error(`'${identifier}' is a reserved word in JavaScript and cannot be used here`, start);
this.error({
code: `unexpected-reserved-word`,
message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`
}, start);
}

return identifier;
}

readUntil(pattern: RegExp) {
if (this.index >= this.template.length)
this.error('Unexpected end of input');
this.error({
code: `unexpected-eof`,
message: 'Unexpected end of input'
});

const start = this.index;
const match = pattern.exec(this.template.slice(start));
Expand All @@ -192,7 +213,10 @@ export class Parser {

requireWhitespace() {
if (!whitespace.test(this.template[this.index])) {
this.error(`Expected whitespace`);
this.error({
code: `missing-whitespace`,
message: `Expected whitespace`
});
}

this.allowWhitespace();
Expand Down
24 changes: 21 additions & 3 deletions src/parse/read/directives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,19 @@ import { parseExpressionAt } from 'acorn';
import repeat from '../../utils/repeat';
import { Parser } from '../index';

const DIRECTIVES = {
const DIRECTIVES: Record<string, {
names: string[];
attribute: (
start: number,
end: number,
type: string,
name: string,
expression?: any,
directiveName?: string
) => { start: number, end: number, type: string, name: string, value?: any, expression?: any };
allowedExpressionTypes: string[];
error: string;
}> = {
Ref: {
names: ['ref'],
attribute(start, end, type, name) {
Expand Down Expand Up @@ -143,7 +155,10 @@ export function readDirective(
try {
expression = readExpression(parser, expressionStart, quoteMark);
if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) {
parser.error(directive.error, expressionStart);
parser.error({
code: `invalid-directive-value`,
message: directive.error
}, expressionStart);
}
} catch (err) {
if (parser.template[expressionStart] === '{') {
Expand All @@ -155,7 +170,10 @@ export function readDirective(
const value = parser.template.slice(expressionStart + (parser.v2 ? 1 : 2), expressionEnd);
message += ` — use '${value}', not '${parser.v2 ? `{${value}}` : `{{${value}}}`}'`;
}
parser.error(message, expressionStart);
parser.error({
code: `invalid-directive-value`,
message
}, expressionStart);
}

throw err;
Expand Down
5 changes: 4 additions & 1 deletion src/parse/read/script.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ export default function readScript(parser: Parser, start: number, attributes: No
const scriptStart = parser.index;
const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart);

if (scriptEnd === -1) parser.error(`<script> must have a closing tag`);
if (scriptEnd === -1) parser.error({
code: `unclosed-script`,
message: `<script> must have a closing tag`
});

const source =
repeat(' ', scriptStart) + parser.template.slice(scriptStart, scriptEnd);
Expand Down
5 changes: 4 additions & 1 deletion src/parse/read/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export default function readStyle(parser: Parser, start: number, attributes: Nod
});
} catch (err) {
if (err.name === 'CssSyntaxError') {
parser.error(err.message, err.offset);
parser.error({
code: `css-syntax-error`,
message: err.message
}, err.offset);
} else {
throw err;
}
Expand Down
56 changes: 42 additions & 14 deletions src/parse/state/mustache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export default function mustache(parser: Parser) {
} else if (block.type === 'AwaitBlock') {
expected = 'await';
} else {
parser.error(`Unexpected block closing tag`);
parser.error({
code: `unexpected-block-close`,
message: `Unexpected block closing tag`
});
}

parser.eat(expected, true);
Expand Down Expand Up @@ -86,9 +89,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat(parser.v2 ? ':elseif' : 'elseif')) {
const block = parser.current();
if (block.type !== 'IfBlock')
parser.error(
'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
);
parser.error({
code: `invalid-elseif-placement`,
message: 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block'
});

parser.requireWhitespace();

Expand Down Expand Up @@ -117,9 +121,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat(parser.v2 ? ':else' : 'else')) {
const block = parser.current();
if (block.type !== 'IfBlock' && block.type !== 'EachBlock') {
parser.error(
'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
);
parser.error({
code: `invalid-else-placement`,
message: 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block'
});
}

parser.allowWhitespace();
Expand Down Expand Up @@ -191,7 +196,10 @@ export default function mustache(parser: Parser) {
} else if (parser.eat('await')) {
type = 'AwaitBlock';
} else {
parser.error(`Expected if, each or await`);
parser.error({
code: `expected-block-type`,
message: `Expected if, each or await`
});
}

parser.requireWhitespace();
Expand Down Expand Up @@ -249,28 +257,42 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();

const destructuredContext = parser.readIdentifier();
if (!destructuredContext) parser.error(`Expected name`);
if (!destructuredContext) parser.error({
code: `expected-name`,
message: `Expected name`
});

block.destructuredContexts.push(destructuredContext);
parser.allowWhitespace();
} while (parser.eat(','));

if (!block.destructuredContexts.length) parser.error(`Expected name`);
if (!block.destructuredContexts.length) parser.error({
code: `expected-name`,
message: `Expected name`
});

block.context = block.destructuredContexts.join('_');

parser.allowWhitespace();
parser.eat(']', true);
} else {
block.context = parser.readIdentifier();
if (!block.context) parser.error(`Expected name`);
if (!block.context) parser.error({
code: `expected-name`,
message: `Expected name`
});
}

parser.allowWhitespace();

if (parser.eat(',')) {
parser.allowWhitespace();
block.index = parser.readIdentifier();
if (!block.index) parser.error(`Expected name`);
if (!block.index) parser.error({
code: `expected-name`,
message: `Expected name`
});

parser.allowWhitespace();
}

Expand All @@ -287,7 +309,10 @@ export default function mustache(parser: Parser) {
expression.property.computed ||
expression.property.type !== 'Identifier'
) {
parser.error('invalid key', expression.start);
parser.error({
code: `invalid-key`,
message: 'invalid key'
}, expression.start);
}

block.key = expression.property.name;
Expand All @@ -296,7 +321,10 @@ export default function mustache(parser: Parser) {
parser.allowWhitespace();
} else if (parser.eat('@')) {
block.key = parser.readIdentifier();
if (!block.key) parser.error(`Expected name`);
if (!block.key) parser.error({
code: `expected-name`,
message: `Expected name`
});
parser.allowWhitespace();
}
}
Expand Down
Loading

0 comments on commit 410f44d

Please sign in to comment.