Optimize finishNode calls in parser
Spreading the 3 finishing values turns out to be noticeably cheaper than spreading the unfinished node.
This commit is contained in:
Родитель
3ac9719b17
Коммит
fa575e515e
|
@ -186,7 +186,7 @@ export function parse(code: string | SourceFile) {
|
|||
locals: createSymbolTable(),
|
||||
inScopeNamespaces: [],
|
||||
parseDiagnostics,
|
||||
...finishNode({}, 0),
|
||||
...finishNode(0),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -316,8 +316,6 @@ export function parse(code: string | SourceFile) {
|
|||
}
|
||||
nsSegments.push(currentName);
|
||||
|
||||
let parameters: ModelExpressionNode | undefined;
|
||||
|
||||
const nextTok = parseExpectedOneOf(Token.Semicolon, Token.OpenBrace);
|
||||
|
||||
let statements: Statement[] | undefined;
|
||||
|
@ -326,28 +324,22 @@ export function parse(code: string | SourceFile) {
|
|||
parseExpected(Token.CloseBrace);
|
||||
}
|
||||
|
||||
let outerNs: NamespaceStatementNode = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.NamespaceStatement,
|
||||
decorators,
|
||||
name: nsSegments[0],
|
||||
parameters,
|
||||
statements,
|
||||
},
|
||||
nsSegments[0].pos
|
||||
);
|
||||
let outerNs: NamespaceStatementNode = {
|
||||
kind: SyntaxKind.NamespaceStatement,
|
||||
decorators,
|
||||
name: nsSegments[0],
|
||||
statements,
|
||||
...finishNode(nsSegments[0].pos),
|
||||
};
|
||||
|
||||
for (let i = 1; i < nsSegments.length; i++) {
|
||||
outerNs = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.NamespaceStatement,
|
||||
decorators: [],
|
||||
name: nsSegments[i],
|
||||
parameters,
|
||||
statements: outerNs,
|
||||
},
|
||||
nsSegments[i].pos
|
||||
);
|
||||
outerNs = {
|
||||
kind: SyntaxKind.NamespaceStatement,
|
||||
decorators: [],
|
||||
name: nsSegments[i],
|
||||
statements: outerNs,
|
||||
...finishNode(nsSegments[i].pos),
|
||||
};
|
||||
}
|
||||
|
||||
return outerNs;
|
||||
|
@ -359,13 +351,11 @@ export function parse(code: string | SourceFile) {
|
|||
const name = parseIdentifierOrMemberExpression();
|
||||
parseExpected(Token.Semicolon);
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.UsingStatement,
|
||||
name,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.UsingStatement,
|
||||
name,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseOperationStatement(decorators: DecoratorExpressionNode[]): OperationStatementNode {
|
||||
|
@ -379,28 +369,24 @@ export function parse(code: string | SourceFile) {
|
|||
const returnType = parseExpression();
|
||||
parseExpected(Token.Semicolon);
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.OperationStatement,
|
||||
id,
|
||||
parameters,
|
||||
returnType,
|
||||
decorators,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.OperationStatement,
|
||||
id,
|
||||
parameters,
|
||||
returnType,
|
||||
decorators,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseOperationParameters(): ModelExpressionNode {
|
||||
const pos = tokenPos();
|
||||
const properties = parseList(ListKind.OperationParameters, parseModelPropertyOrSpread);
|
||||
const parameters: ModelExpressionNode = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelExpression,
|
||||
properties,
|
||||
},
|
||||
pos
|
||||
);
|
||||
const parameters: ModelExpressionNode = {
|
||||
kind: SyntaxKind.ModelExpression,
|
||||
properties,
|
||||
...finishNode(pos),
|
||||
};
|
||||
return parameters;
|
||||
}
|
||||
|
||||
|
@ -420,32 +406,28 @@ export function parse(code: string | SourceFile) {
|
|||
const assignment = parseExpression();
|
||||
parseExpected(Token.Semicolon);
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelStatement,
|
||||
id,
|
||||
heritage: [],
|
||||
templateParameters,
|
||||
assignment,
|
||||
decorators,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ModelStatement,
|
||||
id,
|
||||
heritage: [],
|
||||
templateParameters,
|
||||
assignment,
|
||||
decorators,
|
||||
...finishNode(pos),
|
||||
};
|
||||
} else {
|
||||
const heritage: ReferenceExpression[] = parseOptionalModelHeritage();
|
||||
const properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelStatement,
|
||||
id,
|
||||
heritage,
|
||||
templateParameters,
|
||||
decorators,
|
||||
properties,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ModelStatement,
|
||||
id,
|
||||
heritage,
|
||||
templateParameters,
|
||||
decorators,
|
||||
properties,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -463,13 +445,11 @@ export function parse(code: string | SourceFile) {
|
|||
): TemplateParameterDeclarationNode {
|
||||
reportInvalidDecorators(decorators, "template parameter");
|
||||
const id = parseIdentifier();
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.TemplateParameterDeclaration,
|
||||
id,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.TemplateParameterDeclaration,
|
||||
id,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseModelPropertyOrSpread(pos: number, decorators: DecoratorExpressionNode[]) {
|
||||
|
@ -489,13 +469,11 @@ export function parse(code: string | SourceFile) {
|
|||
// This could be broadened to allow any type expression
|
||||
const target = parseReferenceExpression();
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelSpreadProperty,
|
||||
target,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ModelSpreadProperty,
|
||||
target,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseModelProperty(
|
||||
|
@ -511,16 +489,14 @@ export function parse(code: string | SourceFile) {
|
|||
parseExpected(Token.Colon);
|
||||
const value = parseExpression();
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelProperty,
|
||||
id,
|
||||
decorators,
|
||||
value,
|
||||
optional,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ModelProperty,
|
||||
id,
|
||||
decorators,
|
||||
value,
|
||||
optional,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseExpression(): Expression {
|
||||
|
@ -536,22 +512,17 @@ export function parse(code: string | SourceFile) {
|
|||
return node;
|
||||
}
|
||||
|
||||
node = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.UnionExpression,
|
||||
options: [node],
|
||||
},
|
||||
pos
|
||||
);
|
||||
|
||||
const options = [node];
|
||||
while (parseOptional(Token.Bar)) {
|
||||
const expr = parseIntersectionExpressionOrHigher();
|
||||
node.options.push(expr);
|
||||
options.push(expr);
|
||||
}
|
||||
|
||||
node.end = tokenPos();
|
||||
|
||||
return node;
|
||||
return {
|
||||
kind: SyntaxKind.UnionExpression,
|
||||
options,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseIntersectionExpressionOrHigher(): Expression {
|
||||
|
@ -563,22 +534,17 @@ export function parse(code: string | SourceFile) {
|
|||
return node;
|
||||
}
|
||||
|
||||
node = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.IntersectionExpression,
|
||||
options: [node],
|
||||
},
|
||||
pos
|
||||
);
|
||||
|
||||
const options = [node];
|
||||
while (parseOptional(Token.Ampersand)) {
|
||||
const expr = parseArrayExpressionOrHigher();
|
||||
node.options.push(expr);
|
||||
options.push(expr);
|
||||
}
|
||||
|
||||
node.end = tokenPos();
|
||||
|
||||
return node;
|
||||
return {
|
||||
kind: SyntaxKind.UnionExpression,
|
||||
options,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseArrayExpressionOrHigher(): Expression {
|
||||
|
@ -588,13 +554,11 @@ export function parse(code: string | SourceFile) {
|
|||
while (parseOptional(Token.OpenBracket)) {
|
||||
parseExpected(Token.CloseBracket);
|
||||
|
||||
expr = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ArrayExpression,
|
||||
elementType: expr,
|
||||
},
|
||||
pos
|
||||
);
|
||||
expr = {
|
||||
kind: SyntaxKind.ArrayExpression,
|
||||
elementType: expr,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
return expr;
|
||||
|
@ -605,14 +569,12 @@ export function parse(code: string | SourceFile) {
|
|||
const target = parseIdentifierOrMemberExpression();
|
||||
const args = parseOptionalList(ListKind.TemplateArguments, parseExpression);
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.TypeReference,
|
||||
target,
|
||||
arguments: args,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.TypeReference,
|
||||
target,
|
||||
arguments: args,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseImportStatement(): ImportStatementNode {
|
||||
|
@ -622,13 +584,11 @@ export function parse(code: string | SourceFile) {
|
|||
const path = parseStringLiteral();
|
||||
|
||||
parseExpected(Token.Semicolon);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ImportStatement,
|
||||
path,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ImportStatement,
|
||||
path,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseDecoratorExpression(): DecoratorExpressionNode {
|
||||
|
@ -637,14 +597,12 @@ export function parse(code: string | SourceFile) {
|
|||
|
||||
const target = parseIdentifierOrMemberExpression();
|
||||
const args = parseOptionalList(ListKind.DecoratorArguments, parseExpression);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.DecoratorExpression,
|
||||
arguments: args,
|
||||
target,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.DecoratorExpression,
|
||||
arguments: args,
|
||||
target,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseIdentifierOrMemberExpression(): IdentifierNode | MemberExpressionNode {
|
||||
|
@ -652,14 +610,12 @@ export function parse(code: string | SourceFile) {
|
|||
|
||||
while (parseOptional(Token.Dot)) {
|
||||
const pos = tokenPos();
|
||||
base = finishNode(
|
||||
{
|
||||
kind: SyntaxKind.MemberExpression,
|
||||
base,
|
||||
id: parseIdentifier(),
|
||||
},
|
||||
pos
|
||||
);
|
||||
base = {
|
||||
kind: SyntaxKind.MemberExpression,
|
||||
base,
|
||||
id: parseIdentifier(),
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
return base;
|
||||
|
@ -698,44 +654,38 @@ export function parse(code: string | SourceFile) {
|
|||
parseExpected(Token.OpenParen);
|
||||
const expr = parseExpression();
|
||||
parseExpected(Token.CloseParen);
|
||||
return finishNode(expr, pos);
|
||||
return { ...expr, ...finishNode(pos) };
|
||||
}
|
||||
|
||||
function parseTupleExpression(): TupleExpressionNode {
|
||||
const pos = tokenPos();
|
||||
const values = parseList(ListKind.Tuple, parseExpression);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.TupleExpression,
|
||||
values,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.TupleExpression,
|
||||
values,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseModelExpression(): ModelExpressionNode {
|
||||
const pos = tokenPos();
|
||||
const properties = parseList(ListKind.ModelProperties, parseModelPropertyOrSpread);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.ModelExpression,
|
||||
properties,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.ModelExpression,
|
||||
properties,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseStringLiteral(): StringLiteralNode {
|
||||
const pos = tokenPos();
|
||||
const value = tokenValue();
|
||||
parseExpected(Token.StringLiteral);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.StringLiteral,
|
||||
value,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.StringLiteral,
|
||||
value,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseNumericLiteral(): NumericLiteralNode {
|
||||
|
@ -744,27 +694,22 @@ export function parse(code: string | SourceFile) {
|
|||
const value = Number(text);
|
||||
|
||||
parseExpected(Token.NumericLiteral);
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.NumericLiteral,
|
||||
text,
|
||||
value,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.NumericLiteral,
|
||||
value,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseBooleanLiteral(): BooleanLiteralNode {
|
||||
const pos = tokenPos();
|
||||
const token = parseExpectedOneOf(Token.TrueKeyword, Token.FalseKeyword);
|
||||
const value = token === Token.TrueKeyword;
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.BooleanLiteral,
|
||||
value,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.BooleanLiteral,
|
||||
value,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
function parseIdentifier(message?: string): IdentifierNode {
|
||||
|
@ -781,13 +726,11 @@ export function parse(code: string | SourceFile) {
|
|||
const sv = tokenValue();
|
||||
nextToken();
|
||||
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.Identifier,
|
||||
sv,
|
||||
},
|
||||
pos
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.Identifier,
|
||||
sv,
|
||||
...finishNode(pos),
|
||||
};
|
||||
}
|
||||
|
||||
// utility functions
|
||||
|
@ -816,21 +759,18 @@ export function parse(code: string | SourceFile) {
|
|||
|
||||
function createMissingIdentifier(): IdentifierNode {
|
||||
missingIdentifierCounter++;
|
||||
return finishNode(
|
||||
{
|
||||
kind: SyntaxKind.Identifier,
|
||||
sv: "<missing identifier>" + missingIdentifierCounter,
|
||||
},
|
||||
tokenPos()
|
||||
);
|
||||
return {
|
||||
kind: SyntaxKind.Identifier,
|
||||
sv: "<missing identifier>" + missingIdentifierCounter,
|
||||
...finishNode(tokenPos()),
|
||||
};
|
||||
}
|
||||
|
||||
function finishNode<T>(o: T, pos: number): T & TextRange & { flags: NodeFlags } {
|
||||
function finishNode(pos: number): TextRange & { flags: NodeFlags } {
|
||||
const flags = parseErrorInNextFinishedNode ? NodeFlags.ThisNodeHasError : NodeFlags.None;
|
||||
parseErrorInNextFinishedNode = false;
|
||||
|
||||
return {
|
||||
...o,
|
||||
pos,
|
||||
end: previousTokenEnd,
|
||||
flags,
|
||||
|
@ -953,7 +893,7 @@ export function parse(code: string | SourceFile) {
|
|||
function parseEmptyStatement(): EmptyStatementNode {
|
||||
const pos = tokenPos();
|
||||
parseExpected(Token.Semicolon);
|
||||
return finishNode({ kind: SyntaxKind.EmptyStatement }, pos);
|
||||
return { kind: SyntaxKind.EmptyStatement, ...finishNode(pos) };
|
||||
}
|
||||
|
||||
function parseInvalidStatement(): InvalidStatementNode {
|
||||
|
@ -972,7 +912,7 @@ export function parse(code: string | SourceFile) {
|
|||
);
|
||||
|
||||
error("Statement expected.", { pos, end: previousTokenEnd });
|
||||
return finishNode({ kind: SyntaxKind.InvalidStatement }, pos);
|
||||
return { kind: SyntaxKind.InvalidStatement, ...finishNode(pos) };
|
||||
}
|
||||
|
||||
function error(message: string, target?: TextRange & { realPos?: number }) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче