A loop isn't needed here at all. Just tail call parseDeclarationFlags
as needed to replay the logic.
function parseDeclarationFlags(): StatementFlags {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.LetKeyword:
case SyntaxKind.FunctionKeyword:
case SyntaxKind.ClassKeyword:
return StatementFlags.Statement;
case SyntaxKind.EnumKeyword:
return StatementFlags.ModuleElement;
case SyntaxKind.ConstKeyword:
nextToken();
return token === SyntaxKind.EnumKeyword ? StatementFlags.ModuleElement : StatementFlags.Statement;
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.TypeKeyword:
nextToken();
return isIdentifierOrKeyword() ? StatementFlags.ModuleElement : 0;
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
nextToken();
return isIdentifierOrKeyword() || token === SyntaxKind.StringLiteral ? StatementFlags.ModuleElement : 0;
case SyntaxKind.ImportKeyword:
nextToken();
return token === SyntaxKind.StringLiteral || token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken || isIdentifierOrKeyword() ?
StatementFlags.ModuleElement : 0;
case SyntaxKind.ExportKeyword:
nextToken();
if (token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken ||
token === SyntaxKind.OpenBraceToken || token === SyntaxKind.DefaultKeyword) {
return StatementFlags.ModuleElement;
}
return parseDeclarationFlags();
case SyntaxKind.DeclareKeyword:
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.StaticKeyword:
return nextToken() && parseDeclarationFlags();
default:
return 0;
}
Instead of repeating the logic directly above this line, simply return and call the function again:
nextToken();
return token === SyntaxKind.EnumKeyword ? StatementFlags.ModuleElement : StatementFlags.Statement;
⬇️
return nextToken() && parseDeclarationFlags();
Isolate and coalesce this comparison logic into a separate function. It's too complex to be inline.
function isTokenModuleCompatibleSyntax() {
return token === SyntaxKind.StringLiteral
|| token === SyntaxKind.AsteriskToken
|| token === SyntaxKind.OpenBraceToken
|| token === SyntaxKind.EqualsToken
|| token === SyntaxKind.AsteriskToken
|| token === SyntaxKind.OpenBraceToken
|| token === SyntaxKind.DefaultKeyword
|| isIdentifierOrKeyword()
;
}
// L3673
case SyntaxKind.ImportKeyword:
return nextToken()
&& isTokenModuleCompatibleSyntax()
? StatementFlags.ModuleElement
: 0
;
// L3678
case SyntaxKind.ExportKeyword:
nextToken();
if (isTokenModuleCompatibleSyntax()) {
return StatementFlags.ModuleElement;
} else {
continue;
}