private SingleNamespaceOrTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyntax node, DeclarationKind kind) { SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; if (node.BaseList != null) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasBaseDeclarations; } var memberNames = GetNonTypeMemberNames(((Syntax.InternalSyntax.TypeDeclarationSyntax)(node.Green)).Members, ref declFlags); return(new SingleTypeDeclaration( kind: kind, name: node.Identifier.ValueText, modifiers: node.Modifiers.ToDeclarationModifiers(), arity: node.Arity, declFlags: declFlags, syntaxReference: _syntaxTree.GetReference(node), nameLocation: new SourceLocation(node.Identifier), memberNames: memberNames, children: VisitTypeChildren(node))); }
public override SingleNamespaceOrTypeDeclaration VisitEnumDeclaration(EnumDeclarationSyntax node) { var members = node.Members; SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; if (node.BaseList != null) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasBaseDeclarations; } string[] memberNames = GetEnumMemberNames(members, ref declFlags); return(new SingleTypeDeclaration( kind: DeclarationKind.Enum, name: node.Identifier.ValueText, arity: 0, modifiers: node.Modifiers.ToDeclarationModifiers(), declFlags: declFlags, syntaxReference: _syntaxTree.GetReference(node), nameLocation: new SourceLocation(node.Identifier), memberNames: memberNames, children: ImmutableArray <SingleTypeDeclaration> .Empty)); }
public override SingleNamespaceOrTypeDeclaration VisitEnumDeclaration(EnumDeclarationSyntax node) { var members = node.Members; SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; if (node.ImplementList != null) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasBaseDeclarations; } ImmutableHashSet <string> memberNames = GetEnumMemberNames(members, ref declFlags); var diagnostics = DiagnosticBag.GetInstance(); var modifiers = node.Modifiers.ToDeclarationModifiers(diagnostics: diagnostics); return(new SingleTypeDeclaration( kind: DeclarationKind.Enum, name: node.Identifier.ValueText, arity: 0, modifiers: modifiers, declFlags: declFlags, syntaxReference: _syntaxTree.GetReference(node), nameLocation: new SourceLocation(node.Identifier), memberNames: memberNames, children: ImmutableArray <SingleTypeDeclaration> .Empty, diagnostics: diagnostics.ToReadOnlyAndFree())); }
private SingleNamespaceOrTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyntax node, DeclarationKind kind) { SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; if (node.ExtendList != null || node.ImplementList != null) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasBaseDeclarations; } var diagnostics = DiagnosticBag.GetInstance(); if (node.Arity == 0) { Symbol.ReportErrorIfHasConstraints(node.ConstraintClauses, diagnostics); } var memberNames = GetNonTypeMemberNames(((Syntax.InternalSyntax.TypeDeclarationSyntax)(node.Green)).Members, ref declFlags); var modifiers = node.Modifiers.ToDeclarationModifiers(diagnostics: diagnostics); return(new SingleTypeDeclaration( kind: kind, name: node.Identifier.ValueText, modifiers: modifiers, arity: node.Arity, declFlags: declFlags, syntaxReference: _syntaxTree.GetReference(node), nameLocation: new SourceLocation(node.Identifier), memberNames: memberNames, children: VisitTypeChildren(node), diagnostics: diagnostics.ToReadOnlyAndFree())); }
private SingleNamespaceOrTypeDeclaration VisitTypeDeclaration(TypeDeclarationSyntax node, DeclarationKind kind) { SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; if (node.BaseList != null) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasBaseDeclarations; } var diagnostics = DiagnosticBag.GetInstance(); if (node.Arity == 0) { Symbol.ReportErrorIfHasConstraints(node.ConstraintClauses, diagnostics); } var memberNames = GetNonTypeMemberNames(((Syntax.InternalSyntax.TypeDeclarationSyntax)(node.Green)).Members, ref declFlags); // A record with parameters at least has a primary constructor if (((declFlags & SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers) == 0) && node is RecordDeclarationSyntax { ParameterList : { } })
private RootSingleNamespaceDeclaration CreateScriptRootDeclaration( CompilationUnitSyntax compilationUnit ) { Debug.Assert(_syntaxTree.Options.Kind != SourceCodeKind.Regular); var members = compilationUnit.Members; var rootChildren = ArrayBuilder <SingleNamespaceOrTypeDeclaration> .GetInstance(); var scriptChildren = ArrayBuilder <SingleTypeDeclaration> .GetInstance(); foreach (var member in members) { var decl = Visit(member); if (decl != null) { // Although namespaces are not allowed in script code process them // here as if they were to improve error reporting. if (decl.Kind == DeclarationKind.Namespace) { rootChildren.Add(decl); } else { scriptChildren.Add((SingleTypeDeclaration)decl); } } } //Script class is not static and contains no extensions. SingleTypeDeclaration.TypeDeclarationFlags declFlags = SingleTypeDeclaration.TypeDeclarationFlags.None; var membernames = GetNonTypeMemberNames( ((Syntax.InternalSyntax.CompilationUnitSyntax)(compilationUnit.Green)).Members, ref declFlags ); rootChildren.Add( CreateScriptClass( compilationUnit, scriptChildren.ToImmutableAndFree(), membernames, declFlags ) ); return(new RootSingleNamespaceDeclaration( hasUsings: compilationUnit.Usings.Any(), hasExternAliases: compilationUnit.Externs.Any(), treeNode: _syntaxTree.GetReference(compilationUnit), children: rootChildren.ToImmutableAndFree(), referenceDirectives: GetReferenceDirectives(compilationUnit), hasAssemblyAttributes: compilationUnit.AttributeLists.Any() )); }
private SingleNamespaceOrTypeDeclaration CreateScriptClass( CompilationUnitSyntax parent, ImmutableArray <SingleTypeDeclaration> children, ImmutableHashSet <string> memberNames, SingleTypeDeclaration.TypeDeclarationFlags declFlags ) { Debug.Assert( parent.Kind() == SyntaxKind.CompilationUnit && _syntaxTree.Options.Kind != SourceCodeKind.Regular ); // script type is represented by the parent node: var parentReference = _syntaxTree.GetReference(parent); var fullName = _scriptClassName.Split('.'); // Note: The symbol representing the merged declarations uses parentReference to enumerate non-type members. SingleNamespaceOrTypeDeclaration decl = new SingleTypeDeclaration( kind: _isSubmission ? DeclarationKind.Submission : DeclarationKind.Script, name: fullName.Last(), arity: 0, modifiers: DeclarationModifiers.Internal | DeclarationModifiers.Partial | DeclarationModifiers.Sealed, declFlags: declFlags, syntaxReference: parentReference, nameLocation: new SourceLocation(parentReference), memberNames: memberNames, children: children, diagnostics: ImmutableArray <Diagnostic> .Empty ); for (int i = fullName.Length - 2; i >= 0; i--) { decl = SingleNamespaceDeclaration.Create( name: fullName[i], hasUsings: false, hasExternAliases: false, syntaxReference: parentReference, nameLocation: new SourceLocation(parentReference), children: ImmutableArray.Create(decl), diagnostics: ImmutableArray <Diagnostic> .Empty ); } return(decl); }
private ImmutableArray <SingleNamespaceOrTypeDeclaration> VisitNamespaceChildren( CSharpSyntaxNode node, SyntaxList <MemberDeclarationSyntax> members, Syntax.InternalSyntax.SyntaxList <Syntax.InternalSyntax.MemberDeclarationSyntax> internalMembers) { Debug.Assert(node.Kind == SyntaxKind.NamespaceDeclaration || (node.Kind == SyntaxKind.CompilationUnit && syntaxTree.Options.Kind == SourceCodeKind.Regular)); if (members.Count == 0) { return(ImmutableArray <SingleNamespaceOrTypeDeclaration> .Empty); } // We look for members that are not allowed in a namespace. // If there are any we create an implicit class to wrap them. bool hasGlobalMembers = false; var childrenBuilder = ArrayBuilder <SingleNamespaceOrTypeDeclaration> .GetInstance(); foreach (var member in members) { SingleNamespaceOrTypeDeclaration namespaceOrType = Visit(member); if (namespaceOrType != null) { childrenBuilder.Add(namespaceOrType); } else { hasGlobalMembers = hasGlobalMembers || member.Kind != SyntaxKind.IncompleteMember; } } // wrap all members that are defined in a namespace or compilation unit into an implicit type: if (hasGlobalMembers) { //The implicit class is not static and has no extensions SingleTypeDeclaration.TypeDeclarationFlags declFlags = SingleTypeDeclaration.TypeDeclarationFlags.None; var memberNames = GetNonTypeMemberNames(internalMembers, false, ref declFlags); var container = syntaxTree.GetReference(node); childrenBuilder.Add(CreateImplicitClass(memberNames, container, declFlags)); } return(childrenBuilder.ToImmutableAndFree()); }
public override SingleNamespaceOrTypeDeclaration VisitDelegateDeclaration(DelegateDeclarationSyntax node) { SingleTypeDeclaration.TypeDeclarationFlags declFlags = node.AttributeLists.Any() ? SingleTypeDeclaration.TypeDeclarationFlags.HasAnyAttributes : SingleTypeDeclaration.TypeDeclarationFlags.None; declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; return(new SingleTypeDeclaration( kind: DeclarationKind.Delegate, name: node.Identifier.ValueText, modifiers: node.Modifiers.ToDeclarationModifiers(), declFlags: declFlags, arity: node.Arity, syntaxReference: syntaxTree.GetReference(node), nameLocation: new SourceLocation(node.Identifier), memberNames: SpecializedCollections.EmptyCollection <string>(), children: ImmutableArray <SingleTypeDeclaration> .Empty)); }
private static SingleNamespaceOrTypeDeclaration CreateImplicitClass( ImmutableHashSet <string> memberNames, SyntaxReference container, SingleTypeDeclaration.TypeDeclarationFlags declFlags ) { return(new SingleTypeDeclaration( kind: DeclarationKind.ImplicitClass, name: TypeSymbol.ImplicitTypeName, arity: 0, modifiers: DeclarationModifiers.Internal | DeclarationModifiers.Partial | DeclarationModifiers.Sealed, declFlags: declFlags, syntaxReference: container, nameLocation: new SourceLocation(container), memberNames: memberNames, children: ImmutableArray <SingleTypeDeclaration> .Empty, diagnostics: ImmutableArray <Diagnostic> .Empty )); }
private ImmutableArray <SingleNamespaceOrTypeDeclaration> VisitNamespaceChildren( CSharpSyntaxNode node, SyntaxList <MemberDeclarationSyntax> members, CoreInternalSyntax.SyntaxList <Syntax.InternalSyntax.MemberDeclarationSyntax> internalMembers) { Debug.Assert( node.Kind() is SyntaxKind.NamespaceDeclaration or SyntaxKind.FileScopedNamespaceDeclaration || (node.Kind() == SyntaxKind.CompilationUnit && _syntaxTree.Options.Kind == SourceCodeKind.Regular)); if (members.Count == 0) { return(ImmutableArray <SingleNamespaceOrTypeDeclaration> .Empty); } // We look for members that are not allowed in a namespace. // If there are any we create an implicit class to wrap them. bool hasGlobalMembers = false; bool acceptSimpleProgram = node.Kind() == SyntaxKind.CompilationUnit && _syntaxTree.Options.Kind == SourceCodeKind.Regular; bool hasAwaitExpressions = false; bool isIterator = false; bool hasReturnWithExpression = false; GlobalStatementSyntax firstGlobalStatement = null; bool hasNonEmptyGlobalStatement = false; var childrenBuilder = ArrayBuilder <SingleNamespaceOrTypeDeclaration> .GetInstance(); foreach (var member in members) { SingleNamespaceOrTypeDeclaration namespaceOrType = Visit(member); if (namespaceOrType != null) { childrenBuilder.Add(namespaceOrType); } else if (acceptSimpleProgram && member.IsKind(SyntaxKind.GlobalStatement)) { var global = (GlobalStatementSyntax)member; firstGlobalStatement ??= global; var topLevelStatement = global.Statement; if (!topLevelStatement.IsKind(SyntaxKind.EmptyStatement)) { hasNonEmptyGlobalStatement = true; } if (!hasAwaitExpressions) { hasAwaitExpressions = SyntaxFacts.HasAwaitOperations(topLevelStatement); } if (!isIterator) { isIterator = SyntaxFacts.HasYieldOperations(topLevelStatement); } if (!hasReturnWithExpression) { hasReturnWithExpression = SyntaxFacts.HasReturnWithExpression(topLevelStatement); } } else if (!hasGlobalMembers && member.Kind() != SyntaxKind.IncompleteMember) { hasGlobalMembers = true; } } // wrap all global statements in a compilation unit into a simple program type: if (firstGlobalStatement is object) { var diagnostics = ImmutableArray <Diagnostic> .Empty; if (!hasNonEmptyGlobalStatement) { var bag = DiagnosticBag.GetInstance(); bag.Add(ErrorCode.ERR_SimpleProgramIsEmpty, ((EmptyStatementSyntax)firstGlobalStatement.Statement).SemicolonToken.GetLocation()); diagnostics = bag.ToReadOnlyAndFree(); } childrenBuilder.Add(CreateSimpleProgram(firstGlobalStatement, hasAwaitExpressions, isIterator, hasReturnWithExpression, diagnostics)); } // wrap all members that are defined in a namespace or compilation unit into an implicit type: if (hasGlobalMembers) { //The implicit class is not static and has no extensions SingleTypeDeclaration.TypeDeclarationFlags declFlags = SingleTypeDeclaration.TypeDeclarationFlags.None; var memberNames = GetNonTypeMemberNames(internalMembers, ref declFlags, skipGlobalStatements: acceptSimpleProgram); var container = _syntaxTree.GetReference(node); childrenBuilder.Add(CreateImplicitClass(memberNames, container, declFlags)); } return(childrenBuilder.ToImmutableAndFree()); }
private static string[] GetNonTypeMemberNames(Syntax.InternalSyntax.SyntaxList <Syntax.InternalSyntax.MemberDeclarationSyntax> members, bool hasPrimaryConstructor, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) { bool anyMethodHadExtensionSyntax = false; bool anyMemberHasAttributes = false; bool anyNonTypeMembers = false; var set = PooledHashSet <string> .GetInstance(); if (hasPrimaryConstructor) { anyNonTypeMembers = true; set.Add(WellKnownMemberNames.InstanceConstructorName); declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasPrimaryCtor; } foreach (var member in members) { AddNonTypeMemberNames(member, set, ref anyNonTypeMembers); // Check to see if any method contains a 'this' modifier on its first parameter. // This data is used to determine if a type needs to have its members materialized // as part of extension method lookup. if (!anyMethodHadExtensionSyntax && CheckMethodMemberForExtensionSyntax(member)) { anyMethodHadExtensionSyntax = true; } if (!anyMemberHasAttributes && CheckMemberForAttributes(member)) { anyMemberHasAttributes = true; } } if (anyMethodHadExtensionSyntax) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasExtensionMethodSyntax; } if (anyMemberHasAttributes) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasAttributes; } if (anyNonTypeMembers) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; } // PERF: The member names collection tends to be long-lived. Use a string array since // that uses less memory than a HashSet<string>. string[] result = new string[set.Count]; set.CopyTo(result); set.Free(); return(result); }
private static string[] GetEnumMemberNames(SeparatedSyntaxList <EnumMemberDeclarationSyntax> members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) { var cnt = members.Count; string[] memberNames = new string[cnt]; if (cnt != 0) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; } int i = 0; bool anyMemberHasAttributes = false; foreach (var member in members) { memberNames[i++] = member.Identifier.ValueText; if (!anyMemberHasAttributes && member.AttributeLists.Any()) { anyMemberHasAttributes = true; } } if (anyMemberHasAttributes) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasAttributes; } return(memberNames); }
private static ImmutableHashSet <string> GetNonTypeMemberNames( CoreInternalSyntax.SyntaxList <Syntax.InternalSyntax.MemberDeclarationSyntax> members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) { bool anyMethodHadExtensionSyntax = false; bool anyMemberHasAttributes = false; bool anyNonTypeMembers = false; var memberNameBuilder = s_memberNameBuilderPool.Allocate(); foreach (var member in members) { AddNonTypeMemberNames(member, memberNameBuilder, ref anyNonTypeMembers); // Check to see if any method contains a 'this' modifier on its first parameter. // This data is used to determine if a type needs to have its members materialized // as part of extension method lookup. if (!anyMethodHadExtensionSyntax && CheckMethodMemberForExtensionSyntax(member)) { anyMethodHadExtensionSyntax = true; } if (!anyMemberHasAttributes && CheckMemberForAttributes(member)) { anyMemberHasAttributes = true; } } if (anyMethodHadExtensionSyntax) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasExtensionMethodSyntax; } if (anyMemberHasAttributes) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasAttributes; } if (anyNonTypeMembers) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; } return(ToImmutableAndFree(memberNameBuilder)); }
private static ImmutableHashSet <string> GetEnumMemberNames(SeparatedSyntaxList <EnumMemberDeclarationSyntax> members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) { var cnt = members.Count; var memberNamesBuilder = s_memberNameBuilderPool.Allocate(); if (cnt != 0) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.HasAnyNontypeMembers; } bool anyMemberHasAttributes = false; foreach (var member in members) { memberNamesBuilder.Add(member.Identifier.ValueText); if (!anyMemberHasAttributes && member.AttributeLists.Any()) { anyMemberHasAttributes = true; } } if (anyMemberHasAttributes) { declFlags |= SingleTypeDeclaration.TypeDeclarationFlags.AnyMemberHasAttributes; } return(ToImmutableAndFree(memberNamesBuilder)); }