Use type checking instead of runtime assert for surrounded list req (#467)

This commit is contained in:
Nick Guerrera 2021-04-21 09:48:37 -07:00 коммит произвёл GitHub
Родитель 02b84e5857
Коммит 55e7d5e88a
1 изменённых файлов: 32 добавлений и 29 удалений

Просмотреть файл

@ -48,90 +48,94 @@ import {
*/
type ParseListItem<T> = (pos: number, decorators: DecoratorExpressionNode[]) => T;
type OpenToken = Token.OpenBrace | Token.OpenParen | Token.OpenBracket | Token.LessThan;
type CloseToken = Token.CloseBrace | Token.CloseParen | Token.CloseBracket | Token.GreaterThan;
type DelimiterToken = Token.Comma | Token.Semicolon;
/**
* In order to share sensitive error recovery code, all parsing of delimited
* lists is done using a shared driver routine parameterized by these options.
*/
interface ListKind {
readonly optional: boolean;
readonly allowEmpty: boolean;
readonly open: Token;
readonly close: Token;
readonly delimiter: Token;
readonly toleratedDelimiter: Token;
readonly open: OpenToken | Token.None;
readonly close: CloseToken | Token.None;
readonly delimiter: DelimiterToken;
readonly toleratedDelimiter: DelimiterToken;
readonly toleratedDelimiterIsValid: boolean;
readonly trailingDelimiterIsValid: boolean;
readonly invalidDecoratorTarget?: string;
}
interface SurroundedListKind extends ListKind {
readonly open: OpenToken;
readonly close: CloseToken;
}
/**
* The fixed set of options for each of the kinds of delimited lists in ADL.
*/
namespace ListKind {
const PropertiesBase = {
allowEmpty: true,
optional: false,
toleratedDelimiterIsValid: true,
trailingDelimiterIsValid: true,
};
} as const;
export const OperationParameters: ListKind = {
export const OperationParameters = {
...PropertiesBase,
open: Token.OpenParen,
close: Token.CloseParen,
delimiter: Token.Comma,
toleratedDelimiter: Token.Semicolon,
};
} as const;
export const DecoratorArguments: ListKind = {
export const DecoratorArguments = {
...OperationParameters,
optional: true,
invalidDecoratorTarget: "expression",
};
} as const;
export const ModelProperties: ListKind = {
export const ModelProperties = {
...PropertiesBase,
open: Token.OpenBrace,
close: Token.CloseBrace,
delimiter: Token.Semicolon,
toleratedDelimiter: Token.Comma,
};
} as const;
const ExpresionsBase = {
allowEmpty: true,
optional: false,
delimiter: Token.Comma,
toleratedDelimiter: Token.Semicolon,
toleratedDelimiterIsValid: false,
trailingDelimiterIsValid: false,
invalidDecoratorTarget: "expression",
};
} as const;
export const TemplateParameters: ListKind = {
export const TemplateParameters = {
...ExpresionsBase,
optional: true,
allowEmpty: false,
open: Token.LessThan,
close: Token.GreaterThan,
};
} as const;
export const TemplateArguments: ListKind = {
export const TemplateArguments = {
...TemplateParameters,
};
} as const;
export const Heritage: ListKind = {
export const Heritage = {
...ExpresionsBase,
allowEmpty: false,
open: Token.None,
close: Token.None,
};
} as const;
export const Tuple: ListKind = {
export const Tuple = {
...ExpresionsBase,
allowEmpty: false,
open: Token.OpenBracket,
close: Token.CloseBracket,
};
} as const;
}
export function parse(code: string | SourceFile) {
@ -900,11 +904,10 @@ export function parse(code: string | SourceFile) {
}
/**
* Parse a delimited list with surround open and close punctuation if the open
* token is present. Otherwise, return an empty list.
* Parse a delimited list with surrounding open and close punctuation if the
* open token is present. Otherwise, return an empty list.
*/
function parseOptionalList<T>(kind: ListKind, parseItem: ParseListItem<T>): T[] {
assert(kind.open !== Token.None, "A list cannot be optional without open punctuation.");
function parseOptionalList<T>(kind: SurroundedListKind, parseItem: ParseListItem<T>): T[] {
return token() == kind.open ? parseList(kind, parseItem) : [];
}