in Public/Src/FrontEnd/TypeScript.Net/TypeScript.Net/TypeChecking/Checker.cs [22612:22912]
private bool CheckGrammarModifiers(INode node)
{
switch (node.Kind)
{
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ExportAssignment:
case SyntaxKind.Parameter:
break;
case SyntaxKind.FunctionDeclaration:
if (node.Modifiers != null && (node.Modifiers.Count > 1 || (node.Modifiers.Count > 0 && node.Modifiers[0].Kind != SyntaxKind.AsyncKeyword)) &&
node.Parent.Kind != SyntaxKind.ModuleBlock && node.Parent.Kind != SyntaxKind.SourceFile)
{
return GrammarErrorOnFirstToken(node, Errors.Modifiers_cannot_appear_here);
}
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.VariableStatement:
case SyntaxKind.TypeAliasDeclaration:
if (node.Modifiers != null && node.Parent.Kind != SyntaxKind.ModuleBlock && node.Parent.Kind != SyntaxKind.SourceFile)
{
return GrammarErrorOnFirstToken(node, Errors.Modifiers_cannot_appear_here);
}
break;
case SyntaxKind.EnumDeclaration:
if (node.Modifiers != null && (node.Modifiers.Count > 1 || (node.Modifiers.Count > 0 && node.Modifiers[0].Kind != SyntaxKind.ConstKeyword)) &&
node.Parent.Kind != SyntaxKind.ModuleBlock && node.Parent.Kind != SyntaxKind.SourceFile)
{
return GrammarErrorOnFirstToken(node, Errors.Modifiers_cannot_appear_here);
}
break;
default:
return false;
}
if (node.Modifiers == null)
{
// TODO: original implementation returns nothing.
// Potentially, it means that this function returns 3 different states: true, false, undefined
return false;
}
INode lastStatic = null, lastPrivate = null, lastProtected = null, lastDeclare = null, lastAsync = null;
NodeFlags flags = NodeFlags.None;
foreach (var modifier in node.Modifiers)
{
switch (modifier.Kind)
{
case SyntaxKind.ConstKeyword:
if (node.Kind != SyntaxKind.EnumDeclaration && node.Parent.Kind == SyntaxKind.ClassDeclaration)
{
return GrammarErrorOnNode(node, Errors.A_class_member_cannot_have_the_0_keyword, TokenToString(SyntaxKind.ConstKeyword));
}
break;
case SyntaxKind.PublicKeyword:
case SyntaxKind.ProtectedKeyword:
case SyntaxKind.PrivateKeyword:
string text = null;
if (modifier.Kind == SyntaxKind.PublicKeyword)
{
text = "public";
}
else if (modifier.Kind == SyntaxKind.ProtectedKeyword)
{
text = "protected";
lastProtected = modifier;
}
else
{
text = "private";
lastPrivate = modifier;
}
if ((flags & NodeFlags.AccessibilityModifier) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Accessibility_modifier_already_seen);
}
else if ((flags & NodeFlags.Static) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, text, "static");
}
else if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, text, "async");
}
else if (node.Parent.Kind == SyntaxKind.ModuleBlock || node.Parent.Kind == SyntaxKind.SourceFile)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_appear_on_a_module_element, text);
}
else if ((flags & NodeFlags.Abstract) != NodeFlags.None)
{
if (modifier.Kind == SyntaxKind.PrivateKeyword)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_be_used_with_1_modifier, text, "abstract");
}
else
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, text, "abstract");
}
}
flags |= modifier.Kind.ModifierToFlag();
break;
case SyntaxKind.StaticKeyword:
if ((flags & NodeFlags.Static) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_already_seen, "static");
}
else if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, "static", "async");
}
else if (node.Parent.Kind == SyntaxKind.ModuleBlock || node.Parent.Kind == SyntaxKind.SourceFile)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_appear_on_a_module_element, "static");
}
else if (node.Kind == SyntaxKind.Parameter)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_appear_on_a_parameter, "static");
}
else if ((flags & NodeFlags.Abstract) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
}
flags |= NodeFlags.Static;
lastStatic = modifier;
break;
case SyntaxKind.ExportKeyword:
if ((flags & NodeFlags.Export) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_already_seen, "export");
}
else if ((flags & NodeFlags.Ambient) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, "export", "declare");
}
else if ((flags & NodeFlags.Abstract) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, "export", "abstract");
}
else if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_must_precede_modifier1, "export", "async");
}
else if (node.Parent.Kind == SyntaxKind.ClassDeclaration)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_appear_on_a_class_element, "export");
}
else if (node.Kind == SyntaxKind.Parameter)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_appear_on_a_parameter, "export");
}
flags |= NodeFlags.Export;
break;
case SyntaxKind.DeclareKeyword:
if ((flags & NodeFlags.Ambient) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_already_seen, "declare");
}
else if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.Parent.Kind == SyntaxKind.ClassDeclaration)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_appear_on_a_class_element, "declare");
}
else if (node.Kind == SyntaxKind.Parameter)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_appear_on_a_parameter, "declare");
}
else if (IsInAmbientContext(node.Parent) && node.Parent.Kind == SyntaxKind.ModuleBlock)
{
return GrammarErrorOnNode(modifier, Errors.A_declare_modifier_cannot_be_used_in_an_already_ambient_context);
}
flags |= NodeFlags.Ambient;
lastDeclare = modifier;
break;
case SyntaxKind.AbstractKeyword:
if ((flags & NodeFlags.Abstract) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_already_seen, "abstract");
}
if (node.Kind != SyntaxKind.ClassDeclaration)
{
if (node.Kind != SyntaxKind.MethodDeclaration)
{
return GrammarErrorOnNode(modifier, Errors.Abstract_modifier_can_only_appear_on_a_class_or_method_declaration);
}
if (!(node.Parent.Kind == SyntaxKind.ClassDeclaration && (node.Parent.Flags & NodeFlags.Abstract) != NodeFlags.None))
{
return GrammarErrorOnNode(modifier, Errors.Abstract_methods_can_only_appear_within_an_abstract_class);
}
if ((flags & NodeFlags.Static) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
}
if ((flags & NodeFlags.Private) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_be_used_with_1_modifier, "private", "abstract");
}
}
flags |= NodeFlags.Abstract;
break;
case SyntaxKind.AsyncKeyword:
if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_already_seen, "async");
}
else if ((flags & NodeFlags.Ambient) != NodeFlags.None || IsInAmbientContext(node.Parent))
{
return GrammarErrorOnNode(modifier, Errors.Modifier0_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.Kind == SyntaxKind.Parameter)
{
return GrammarErrorOnNode(modifier, Errors.Zero_modifier_cannot_appear_on_a_parameter, "async");
}
flags |= NodeFlags.Async;
lastAsync = modifier;
break;
}
}
if (node.Kind == SyntaxKind.Constructor)
{
if ((flags & NodeFlags.Static) != NodeFlags.None)
{
return GrammarErrorOnNode(lastStatic, Errors.Zero_modifier_cannot_appear_on_a_constructor_declaration, "static");
}
if ((flags & NodeFlags.Abstract) != NodeFlags.None)
{
return GrammarErrorOnNode(lastStatic, Errors.Zero_modifier_cannot_appear_on_a_constructor_declaration, "abstract");
}
else if ((flags & NodeFlags.Protected) != NodeFlags.None)
{
return GrammarErrorOnNode(lastProtected, Errors.Zero_modifier_cannot_appear_on_a_constructor_declaration, "protected");
}
else if ((flags & NodeFlags.Private) != NodeFlags.None)
{
return GrammarErrorOnNode(lastPrivate, Errors.Zero_modifier_cannot_appear_on_a_constructor_declaration, "private");
}
else if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return GrammarErrorOnNode(lastAsync, Errors.Zero_modifier_cannot_appear_on_a_constructor_declaration, "async");
}
// TODO: this was just 'return'. It means that this function potentially could have 3 different return values!
return false;
}
else if ((node.Kind == SyntaxKind.ImportDeclaration || node.Kind == SyntaxKind.ImportEqualsDeclaration) && (flags & NodeFlags.Ambient) != NodeFlags.None)
{
return GrammarErrorOnNode(lastDeclare, Errors.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
}
else if (node.Kind == SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) != NodeFlags.None && IsBindingPattern(node.Cast<IParameterDeclaration>().Name) != null)
{
return GrammarErrorOnNode(node, Errors.A_parameter_property_may_not_be_a_binding_pattern);
}
if ((flags & NodeFlags.Async) != NodeFlags.None)
{
return CheckGrammarAsyncModifier(node, lastAsync);
}
return false;
}