private static string[] GetNonTypeMemberNames( CoreInternalSyntax.SyntaxList <Syntax.InternalSyntax.MemberDeclarationSyntax> members, ref SingleTypeDeclaration.TypeDeclarationFlags declFlags) { bool anyMethodHadExtensionSyntax = false; bool anyMemberHasAttributes = false; bool anyNonTypeMembers = false; var set = PooledHashSet <string> .GetInstance(); 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; if (set.Count == 0) { result = Array.Empty <string>(); } else { result = new string[set.Count]; set.CopyTo(result); } set.Free(); return(result); }
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 ImmutableArray <SingleNamespaceOrTypeDeclaration> VisitNamespaceChildren( CSharpSyntaxNode node, SyntaxList <MemberDeclarationSyntax> members, CoreInternalSyntax.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, ref declFlags); var container = _syntaxTree.GetReference(node); childrenBuilder.Add(CreateImplicitClass(memberNames, container, declFlags)); } return(childrenBuilder.ToImmutableAndFree()); }
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()); }