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)));
        }
Beispiel #2
0
        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 : { }
            })
Beispiel #6
0
        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()
                       ));
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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());
        }
Beispiel #9
0
        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));
        }
Beispiel #10
0
 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());
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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));
        }
Beispiel #15
0
        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));
        }