mirror of https://github.com/sveltejs/svelte
189 lines
3.7 KiB
189 lines
3.7 KiB
import { Parser } from '../index';
|
|
|
|
interface Identifier {
|
|
start: number;
|
|
end: number;
|
|
type: 'Identifier';
|
|
name: string;
|
|
}
|
|
|
|
interface Property {
|
|
start: number;
|
|
end: number;
|
|
type: 'Property';
|
|
kind: 'init' | 'rest';
|
|
shorthand: boolean;
|
|
key: Identifier;
|
|
value: Context;
|
|
}
|
|
|
|
interface Context {
|
|
start: number;
|
|
end: number;
|
|
type: 'Identifier' | 'ArrayPattern' | 'ObjectPattern' | 'RestIdentifier';
|
|
name?: string;
|
|
elements?: Context[];
|
|
properties?: Property[];
|
|
}
|
|
|
|
function error_on_assignment_pattern(parser: Parser) {
|
|
if (parser.eat('=')) {
|
|
parser.error({
|
|
code: 'invalid-assignment-pattern',
|
|
message: 'Assignment patterns are not supported'
|
|
}, parser.index - 1);
|
|
}
|
|
}
|
|
|
|
function error_on_rest_pattern_not_last(parser: Parser) {
|
|
parser.error({
|
|
code: 'rest-pattern-not-last',
|
|
message: 'Rest destructuring expected to be last'
|
|
}, parser.index);
|
|
}
|
|
|
|
export default function read_context(parser: Parser) {
|
|
const context: Context = {
|
|
start: parser.index,
|
|
end: null,
|
|
type: null
|
|
};
|
|
|
|
if (parser.eat('[')) {
|
|
context.type = 'ArrayPattern';
|
|
context.elements = [];
|
|
|
|
do {
|
|
parser.allow_whitespace();
|
|
|
|
const lastContext = context.elements[context.elements.length - 1];
|
|
if (lastContext && lastContext.type === 'RestIdentifier') {
|
|
error_on_rest_pattern_not_last(parser);
|
|
}
|
|
|
|
if (parser.template[parser.index] === ',') {
|
|
context.elements.push(null);
|
|
} else {
|
|
context.elements.push(read_context(parser));
|
|
parser.allow_whitespace();
|
|
}
|
|
} while (parser.eat(','));
|
|
|
|
error_on_assignment_pattern(parser);
|
|
parser.eat(']', true);
|
|
context.end = parser.index;
|
|
}
|
|
|
|
else if (parser.eat('{')) {
|
|
context.type = 'ObjectPattern';
|
|
context.properties = [];
|
|
|
|
do {
|
|
parser.allow_whitespace();
|
|
|
|
if (parser.eat('...')) {
|
|
parser.allow_whitespace();
|
|
|
|
const start = parser.index;
|
|
const name = parser.read_identifier();
|
|
const key: Identifier = {
|
|
start,
|
|
end: parser.index,
|
|
type: 'Identifier',
|
|
name
|
|
};
|
|
const property: Property = {
|
|
start,
|
|
end: parser.index,
|
|
type: 'Property',
|
|
kind: 'rest',
|
|
shorthand: true,
|
|
key,
|
|
value: key
|
|
};
|
|
|
|
context.properties.push(property);
|
|
|
|
parser.allow_whitespace();
|
|
|
|
if (parser.eat(',')) {
|
|
parser.error({
|
|
code: `comma-after-rest`,
|
|
message: `Comma is not permitted after the rest element`
|
|
}, parser.index - 1);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
const start = parser.index;
|
|
const name = parser.read_identifier();
|
|
const key: Identifier = {
|
|
start,
|
|
end: parser.index,
|
|
type: 'Identifier',
|
|
name
|
|
};
|
|
parser.allow_whitespace();
|
|
|
|
const value = parser.eat(':')
|
|
? (parser.allow_whitespace(), read_context(parser))
|
|
: key;
|
|
|
|
const property: Property = {
|
|
start,
|
|
end: value.end,
|
|
type: 'Property',
|
|
kind: 'init',
|
|
shorthand: value.type === 'Identifier' && value.name === name,
|
|
key,
|
|
value
|
|
};
|
|
|
|
context.properties.push(property);
|
|
|
|
parser.allow_whitespace();
|
|
} while (parser.eat(','));
|
|
|
|
error_on_assignment_pattern(parser);
|
|
parser.eat('}', true);
|
|
context.end = parser.index;
|
|
}
|
|
|
|
else if (parser.eat('...')) {
|
|
const name = parser.read_identifier();
|
|
if (name) {
|
|
context.type = 'RestIdentifier';
|
|
context.end = parser.index;
|
|
context.name = name;
|
|
}
|
|
|
|
else {
|
|
parser.error({
|
|
code: 'invalid-context',
|
|
message: 'Expected a rest pattern'
|
|
});
|
|
}
|
|
}
|
|
|
|
else {
|
|
const name = parser.read_identifier();
|
|
if (name) {
|
|
context.type = 'Identifier';
|
|
context.end = parser.index;
|
|
context.name = name;
|
|
}
|
|
|
|
else {
|
|
parser.error({
|
|
code: 'invalid-context',
|
|
message: 'Expected a name, array pattern or object pattern'
|
|
});
|
|
}
|
|
|
|
error_on_assignment_pattern(parser);
|
|
}
|
|
|
|
return context;
|
|
}
|