예제 #1
0
        protected BoundExpression BindTargetExpression(BindingDiagnosticBag diagnostics, Binder originalBinder, TypeSymbol targetTypeOpt = null)
        {
            if (_lazyExpressionAndDiagnostics == null)
            {
                // Filter out method group in conversion.
                var             expressionDiagnostics = BindingDiagnosticBag.GetInstance();
                BoundExpression boundExpression       = originalBinder.BindValue(TargetExpressionSyntax, expressionDiagnostics, Binder.BindValueKind.RValueOrMethodGroup);
                if (targetTypeOpt is object)
                {
                    boundExpression = originalBinder.GenerateConversionForAssignment(targetTypeOpt, boundExpression, expressionDiagnostics);
                }
                else
                {
                    boundExpression = originalBinder.BindToNaturalType(boundExpression, expressionDiagnostics);
                }
                Interlocked.CompareExchange(ref _lazyExpressionAndDiagnostics, new ExpressionAndDiagnostics(boundExpression, expressionDiagnostics.ToReadOnlyAndFree()), null);
            }
            Debug.Assert(_lazyExpressionAndDiagnostics != null);

            if (diagnostics != null)
            {
                diagnostics.AddRange(_lazyExpressionAndDiagnostics.Diagnostics, allowMismatchInDependencyAccumulation: true);
            }

            return(_lazyExpressionAndDiagnostics.Expression);
        }
예제 #2
0
            private void BindAndReplaceCref(XAttribute attribute, CSharpSyntaxNode originatingSyntax)
            {
                string     attributeValue = attribute.Value;
                CrefSyntax crefSyntax     = SyntaxFactory.ParseCref(attributeValue);

                if (crefSyntax == null)
                {
                    // This can happen if the cref is verbatim (e.g. "T:C").
                    return;
                }

                // CONSIDER: It would be easy to construct an XmlLocation from the XAttribute, so that
                // we could point the user at the actual problem.
                Location sourceLocation = originatingSyntax.Location;

                RecordSyntaxDiagnostics(crefSyntax, sourceLocation); // Respects DocumentationMode.

                MemberDeclarationSyntax memberDeclSyntax = BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax);

                Debug.Assert(memberDeclSyntax != null,
                             "Why are we processing a documentation comment that is not attached to a member declaration?");

                Binder binder = BinderFactory.MakeCrefBinder(crefSyntax, memberDeclSyntax, _compilation.GetBinderFactory(memberDeclSyntax.SyntaxTree));

                var crefDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics);

                attribute.Value = GetDocumentationCommentId(crefSyntax, binder, crefDiagnostics); // NOTE: mutation (element must be a copy)
                RecordBindingDiagnostics(crefDiagnostics, sourceLocation);                        // Respects DocumentationMode.
                crefDiagnostics.Free();
            }
예제 #3
0
        internal static void BindFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod?scriptInitializerOpt,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > fieldInitializers,
            BindingDiagnosticBag diagnostics,
            ref ProcessedFieldInitializers processedInitializers
            )
        {
            var diagsForInstanceInitializers = BindingDiagnosticBag.GetInstance(
                withDiagnostics: true,
                diagnostics.AccumulatesDependencies
                );
            ImportChain?firstImportChain;

            processedInitializers.BoundInitializers = BindFieldInitializers(
                compilation,
                scriptInitializerOpt,
                fieldInitializers,
                diagsForInstanceInitializers,
                out firstImportChain
                );
            processedInitializers.HasErrors        = diagsForInstanceInitializers.HasAnyErrors();
            processedInitializers.FirstImportChain = firstImportChain;
            diagnostics.AddRange(diagsForInstanceInitializers);
            diagsForInstanceInitializers.Free();
        }
예제 #4
0
        protected bool VerifyPresenceOfRequiredAPIs()
        {
            var bag = BindingDiagnosticBag.GetInstance(
                withDiagnostics: true,
                diagnostics.AccumulatesDependencies
                );

            EnsureSpecialType(SpecialType.System_Int32, bag);
            EnsureSpecialType(SpecialType.System_IDisposable, bag);
            EnsureSpecialMember(SpecialMember.System_IDisposable__Dispose, bag);

            // IEnumerator
            EnsureSpecialType(SpecialType.System_Collections_IEnumerator, bag);
            EnsureSpecialPropertyGetter(SpecialMember.System_Collections_IEnumerator__Current, bag);
            EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__MoveNext, bag);
            EnsureSpecialMember(SpecialMember.System_Collections_IEnumerator__Reset, bag);

            // IEnumerator<T>
            EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerator_T, bag);
            EnsureSpecialPropertyGetter(
                SpecialMember.System_Collections_Generic_IEnumerator_T__Current,
                bag
                );

            if (_isEnumerable)
            {
                // IEnumerable and IEnumerable<T>
                EnsureSpecialType(SpecialType.System_Collections_IEnumerable, bag);
                EnsureSpecialMember(
                    SpecialMember.System_Collections_IEnumerable__GetEnumerator,
                    bag
                    );
                EnsureSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T, bag);
                EnsureSpecialMember(
                    SpecialMember.System_Collections_Generic_IEnumerable_T__GetEnumerator,
                    bag
                    );
            }

            bool hasErrors = bag.HasAnyErrors();

            if (!hasErrors)
            {
                diagnostics.AddDependencies(bag);
            }
            else
            {
                diagnostics.AddRange(bag);
            }

            bag.Free();
            return(!hasErrors);
        }
예제 #5
0
            private void BindName(
                XAttribute attribute,
                CSharpSyntaxNode originatingSyntax,
                bool isParameter,
                bool isTypeParameterRef
                )
            {
                XmlNameAttributeSyntax attrSyntax = ParseNameAttribute(
                    attribute.ToString(),
                    attribute.Parent.Name.LocalName
                    );

                // CONSIDER: It would be easy to construct an XmlLocation from the XAttribute, so that
                // we could point the user at the actual problem.
                Location sourceLocation = originatingSyntax.Location;

                RecordSyntaxDiagnostics(attrSyntax, sourceLocation); // Respects DocumentationMode.

                MemberDeclarationSyntax memberDeclSyntax =
                    BinderFactory.GetAssociatedMemberForXmlSyntax(originatingSyntax);

                Debug.Assert(
                    memberDeclSyntax != null,
                    "Why are we processing a documentation comment that is not attached to a member declaration?"
                    );

                var    nameDiagnostics = BindingDiagnosticBag.GetInstance(_diagnostics);
                Binder binder          = MakeNameBinder(
                    isParameter,
                    isTypeParameterRef,
                    _memberSymbol,
                    _compilation
                    );

                DocumentationCommentCompiler.BindName(
                    attrSyntax,
                    binder,
                    _memberSymbol,
                    ref _documentedParameters,
                    ref _documentedTypeParameters,
                    nameDiagnostics
                    );
                RecordBindingDiagnostics(nameDiagnostics, sourceLocation); // Respects DocumentationMode.
                nameDiagnostics.Free();
            }
예제 #6
0
        protected bool VerifyPresenceOfRequiredAPIs()
        {
            var bag = BindingDiagnosticBag.GetInstance(withDiagnostics: true, diagnostics.AccumulatesDependencies);

            VerifyPresenceOfRequiredAPIs(bag);

            bool hasErrors = bag.HasAnyErrors();

            if (!hasErrors)
            {
                diagnostics.AddDependencies(bag);
            }
            else
            {
                diagnostics.AddRange(bag);
            }

            bag.Free();
            return(!hasErrors && _constructedSuccessfully);
        }
예제 #7
0
        internal bool LoadAndValidateAttributes(
            OneOrMany <SyntaxList <AttributeListSyntax> > attributesSyntaxLists,
            ref CustomAttributesBag <CSharpAttributeData> lazyCustomAttributesBag,
            AttributeLocation symbolPart = AttributeLocation.None,
            bool earlyDecodingOnly       = false,
            Binder binderOpt             = null,
            Func <AttributeSyntax, bool> attributeMatchesOpt = null
            )
        {
            var diagnostics = BindingDiagnosticBag.GetInstance();
            var compilation = this.DeclaringCompilation;

            ImmutableArray <Binder>          binders;
            ImmutableArray <AttributeSyntax> attributesToBind = this.GetAttributesToBind(
                attributesSyntaxLists,
                symbolPart,
                diagnostics,
                compilation,
                attributeMatchesOpt,
                binderOpt,
                out binders
                );

            Debug.Assert(!attributesToBind.IsDefault);

            ImmutableArray <CSharpAttributeData> boundAttributes;
            WellKnownAttributeData wellKnownAttributeData;

            if (attributesToBind.Any())
            {
                Debug.Assert(!binders.IsDefault);
                Debug.Assert(binders.Length == attributesToBind.Length);

                // Initialize the bag so that data decoded from early attributes can be stored onto it.
                if (lazyCustomAttributesBag == null)
                {
                    Interlocked.CompareExchange(
                        ref lazyCustomAttributesBag,
                        new CustomAttributesBag <CSharpAttributeData>(),
                        null
                        );
                }

                // Bind the attribute types and then early decode them.
                int totalAttributesCount  = attributesToBind.Length;
                var attributeTypesBuilder = new NamedTypeSymbol[totalAttributesCount];

                Binder.BindAttributeTypes(
                    binders,
                    attributesToBind,
                    this,
                    attributeTypesBuilder,
                    diagnostics
                    );
                ImmutableArray <NamedTypeSymbol> boundAttributeTypes =
                    attributeTypesBuilder.AsImmutableOrNull();

                this.EarlyDecodeWellKnownAttributeTypes(boundAttributeTypes, attributesToBind);
                this.PostEarlyDecodeWellKnownAttributeTypes();

                // Bind the attribute in two stages - early and normal.
                var attributesBuilder = new CSharpAttributeData[totalAttributesCount];

                // Early bind and decode some well-known attributes.
                EarlyWellKnownAttributeData earlyData = this.EarlyDecodeWellKnownAttributes(
                    binders,
                    boundAttributeTypes,
                    attributesToBind,
                    symbolPart,
                    attributesBuilder
                    );
                Debug.Assert(!attributesBuilder.Contains((attr) => attr != null && attr.HasErrors));

                // Store data decoded from early bound well-known attributes.
                // TODO: what if this succeeds on another thread, not ours?
                lazyCustomAttributesBag.SetEarlyDecodedWellKnownAttributeData(earlyData);

                if (earlyDecodingOnly)
                {
                    diagnostics.Free(); //NOTE: dropped.
                    return(false);
                }

                // Bind attributes.
                Binder.GetAttributes(
                    binders,
                    attributesToBind,
                    boundAttributeTypes,
                    attributesBuilder,
                    diagnostics
                    );
                boundAttributes = attributesBuilder.AsImmutableOrNull();

                // All attributes must be bound by now.
                Debug.Assert(!boundAttributes.Any((attr) => attr == null));

                // Validate attribute usage and Decode remaining well-known attributes.
                wellKnownAttributeData = this.ValidateAttributeUsageAndDecodeWellKnownAttributes(
                    binders,
                    attributesToBind,
                    boundAttributes,
                    diagnostics,
                    symbolPart
                    );

                // Store data decoded from remaining well-known attributes.
                // TODO: what if this succeeds on another thread but not this thread?
                lazyCustomAttributesBag.SetDecodedWellKnownAttributeData(wellKnownAttributeData);
            }
            else if (earlyDecodingOnly)
            {
                diagnostics.Free(); //NOTE: dropped.
                return(false);
            }
            else
            {
                boundAttributes        = ImmutableArray <CSharpAttributeData> .Empty;
                wellKnownAttributeData = null;
                Interlocked.CompareExchange(
                    ref lazyCustomAttributesBag,
                    CustomAttributesBag <CSharpAttributeData> .WithEmptyData(),
                    null
                    );
                this.PostEarlyDecodeWellKnownAttributeTypes();
            }

            this.PostDecodeWellKnownAttributes(
                boundAttributes,
                attributesToBind,
                diagnostics,
                symbolPart,
                wellKnownAttributeData
                );

            // Store attributes into the bag.
            bool lazyAttributesStoredOnThisThread = false;

            if (lazyCustomAttributesBag.SetAttributes(boundAttributes))
            {
                if (attributeMatchesOpt is null)
                {
                    this.RecordPresenceOfBadAttributes(boundAttributes);
                    AddDeclarationDiagnostics(diagnostics);
                }
                lazyAttributesStoredOnThisThread = true;
                if (lazyCustomAttributesBag.IsEmpty)
                {
                    lazyCustomAttributesBag = CustomAttributesBag <CSharpAttributeData> .Empty;
                }
            }

            Debug.Assert(lazyCustomAttributesBag.IsSealed);
            diagnostics.Free();
            return(lazyAttributesStoredOnThisThread);
        }
예제 #8
0
        private BoundExpression FinalTranslation(QueryTranslationState state, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(state.clauses.IsEmpty());
            switch (state.selectOrGroup.Kind())
            {
            case SyntaxKind.SelectClause:
            {
                // A query expression of the form
                //     from x in e select v
                // is translated into
                //     ( e ) . Select ( x => v )
                var selectClause = (SelectClauseSyntax)state.selectOrGroup;
                var x            = state.rangeVariable;
                var e            = state.fromExpression;
                var v            = selectClause.Expression;
                var lambda       = MakeQueryUnboundLambda(state.RangeVariableMap(), x, v, diagnostics.AccumulatesDependencies);
                var result       = MakeQueryInvocation(state.selectOrGroup, e, "Select", lambda, diagnostics);
                return(MakeQueryClause(selectClause, result, queryInvocation: result));
            }

            case SyntaxKind.GroupClause:
            {
                // A query expression of the form
                //     from x in e group v by k
                // is translated into
                //     ( e ) . GroupBy ( x => k , x => v )
                // except when v is the identifier x, the translation is
                //     ( e ) . GroupBy ( x => k )
                var       groupClause = (GroupClauseSyntax)state.selectOrGroup;
                var       x           = state.rangeVariable;
                var       e           = state.fromExpression;
                var       v           = groupClause.GroupExpression;
                var       k           = groupClause.ByExpression;
                var       vId         = v as IdentifierNameSyntax;
                BoundCall result;
                var       lambdaLeft = MakeQueryUnboundLambda(state.RangeVariableMap(), x, k, diagnostics.AccumulatesDependencies);

                // this is the unoptimized form (when v is not the identifier x)
                var             d           = BindingDiagnosticBag.GetInstance(diagnostics);
                BoundExpression lambdaRight = MakeQueryUnboundLambda(state.RangeVariableMap(), x, v, diagnostics.AccumulatesDependencies);
                result = MakeQueryInvocation(state.selectOrGroup, e, "GroupBy", ImmutableArray.Create(lambdaLeft, lambdaRight), d);
                // k and v appear reversed in the invocation, so we reorder their evaluation
                result = ReverseLastTwoParameterOrder(result);

                BoundExpression?unoptimizedForm = null;
                if (vId != null && vId.Identifier.ValueText == x.Name)
                {
                    // The optimized form.  We store the unoptimized form for analysis
                    unoptimizedForm = result;
                    result          = MakeQueryInvocation(state.selectOrGroup, e, "GroupBy", lambdaLeft, diagnostics);
                    if (unoptimizedForm.HasAnyErrors && !result.HasAnyErrors)
                    {
                        unoptimizedForm = null;
                    }
                }
                else
                {
                    diagnostics.AddRange(d);
                }

                d.Free();
                return(MakeQueryClause(groupClause, result, queryInvocation: result, unoptimizedForm: unoptimizedForm));
            }

            default:
            {
                // there should have been a syntax error if we get here.
                Debug.Assert(state.fromExpression.Type is { });
                return(new BoundBadExpression(
                           state.selectOrGroup, LookupResultKind.OverloadResolutionFailure, ImmutableArray <Symbol?> .Empty,
                           ImmutableArray.Create(state.fromExpression), state.fromExpression.Type));
            }
예제 #9
0
        public static Imports FromSyntax(
            CSharpSyntaxNode declarationSyntax,
            InContainerBinder binder,
            ConsList <TypeSymbol> basesBeingResolved,
            bool inUsing)
        {
            SyntaxList <UsingDirectiveSyntax>       usingDirectives;
            SyntaxList <ExternAliasDirectiveSyntax> externAliasDirectives;

            if (declarationSyntax.Kind() == SyntaxKind.CompilationUnit)
            {
                var compilationUnit = (CompilationUnitSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives       = inUsing ? default(SyntaxList <UsingDirectiveSyntax>) : compilationUnit.Usings;
                externAliasDirectives = compilationUnit.Externs;
            }
            else if (declarationSyntax.Kind() == SyntaxKind.NamespaceDeclaration)
            {
                var namespaceDecl = (NamespaceDeclarationSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives       = inUsing ? default(SyntaxList <UsingDirectiveSyntax>) : namespaceDecl.Usings;
                externAliasDirectives = namespaceDecl.Externs;
            }
            else
            {
                return(Empty);
            }

            if (usingDirectives.Count == 0 && externAliasDirectives.Count == 0)
            {
                return(Empty);
            }

            // define all of the extern aliases first. They may used by the target of a using

            // using Bar=Goo::Bar;
            // using Goo::Baz;
            // extern alias Goo;

            var diagnostics = new DiagnosticBag();

            var compilation = binder.Compilation;

            var externAliases = BuildExternAliases(externAliasDirectives, binder, diagnostics);
            var usings        = ArrayBuilder <NamespaceOrTypeAndUsingDirective> .GetInstance();

            ImmutableDictionary <string, AliasAndUsingDirective> .Builder usingAliases = null;
            if (usingDirectives.Count > 0)
            {
                // A binder that contains the extern aliases but not the usings. The resolution of the target of a using directive or alias
                // should not make use of other peer usings.
                Binder usingsBinder;
                if (declarationSyntax.SyntaxTree.Options.Kind != SourceCodeKind.Regular)
                {
                    usingsBinder = compilation.GetBinderFactory(declarationSyntax.SyntaxTree).GetImportsBinder(declarationSyntax, inUsing: true);
                }
                else
                {
                    var imports = externAliases.Length == 0
                        ? Empty
                        : new Imports(
                        compilation,
                        ImmutableDictionary <string, AliasAndUsingDirective> .Empty,
                        ImmutableArray <NamespaceOrTypeAndUsingDirective> .Empty,
                        externAliases,
                        diagnostics: null);
                    usingsBinder = new InContainerBinder(binder.Container, binder.Next, imports);
                }

                var uniqueUsings = SpecializedSymbolCollections.GetPooledSymbolHashSetInstance <NamespaceOrTypeSymbol>();

                foreach (var usingDirective in usingDirectives)
                {
                    compilation.RecordImport(usingDirective);

                    if (usingDirective.Alias != null)
                    {
                        SyntaxToken identifier = usingDirective.Alias.Name.Identifier;
                        Location    location   = usingDirective.Alias.Name.Location;

                        if (identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
                        {
                            diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, location);
                        }

                        if (usingDirective.StaticKeyword != default(SyntaxToken))
                        {
                            diagnostics.Add(ErrorCode.ERR_NoAliasHere, location);
                        }

                        SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, compilation, diagnostics, location);

                        string identifierValueText = identifier.ValueText;
                        if (usingAliases != null && usingAliases.ContainsKey(identifierValueText))
                        {
                            // Suppress diagnostics if we're already broken.
                            if (!usingDirective.Name.IsMissing)
                            {
                                // The using alias '{0}' appeared previously in this namespace
                                diagnostics.Add(ErrorCode.ERR_DuplicateAlias, location, identifierValueText);
                            }
                        }
                        else
                        {
                            // an O(m*n) algorithm here but n (number of extern aliases) will likely be very small.
                            foreach (var externAlias in externAliases)
                            {
                                if (externAlias.Alias.Name == identifierValueText)
                                {
                                    // The using alias '{0}' appeared previously in this namespace
                                    diagnostics.Add(ErrorCode.ERR_DuplicateAlias, usingDirective.Location, identifierValueText);
                                    break;
                                }
                            }

                            if (usingAliases == null)
                            {
                                usingAliases = ImmutableDictionary.CreateBuilder <string, AliasAndUsingDirective>();
                            }

                            // construct the alias sym with the binder for which we are building imports. That
                            // way the alias target can make use of extern alias definitions.
                            usingAliases.Add(identifierValueText, new AliasAndUsingDirective(new AliasSymbol(usingsBinder, usingDirective.Name, usingDirective.Alias), usingDirective));
                        }
                    }
                    else
                    {
                        if (usingDirective.Name.IsMissing)
                        {
                            //don't try to lookup namespaces inserted by parser error recovery
                            continue;
                        }

                        var directiveDiagnostics = BindingDiagnosticBag.GetInstance();

                        var declarationBinder = usingsBinder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);
                        var imported          = declarationBinder.BindNamespaceOrTypeSymbol(usingDirective.Name, directiveDiagnostics, basesBeingResolved).NamespaceOrTypeSymbol;

                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            Debug.Assert(directiveDiagnostics.DependenciesBag.IsEmpty());

                            if (usingDirective.StaticKeyword != default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingType, usingDirective.Name.Location, imported);
                            }
                            else if (!uniqueUsings.Add(imported))
                            {
                                diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                usings.Add(new NamespaceOrTypeAndUsingDirective(imported, usingDirective, dependencies: default));
                            }
                        }
                        else if (imported.Kind == SymbolKind.NamedType)
                        {
                            if (usingDirective.StaticKeyword == default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingNamespace, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                var importedType = (NamedTypeSymbol)imported;
                                if (uniqueUsings.Contains(importedType))
                                {
                                    diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, importedType);
                                }
                                else
                                {
                                    declarationBinder.ReportDiagnosticsIfObsolete(diagnostics, importedType, usingDirective.Name, hasBaseReceiver: false);

                                    uniqueUsings.Add(importedType);
                                    usings.Add(new NamespaceOrTypeAndUsingDirective(importedType, usingDirective, directiveDiagnostics.DependenciesBag.ToImmutableArray()));
                                }
                            }
                        }
                        else if (imported.Kind != SymbolKind.ErrorType)
                        {
                            // Do not report additional error if the symbol itself is erroneous.

                            // error: '<symbol>' is a '<symbol kind>' but is used as 'type or namespace'
                            diagnostics.Add(ErrorCode.ERR_BadSKknown, usingDirective.Name.Location,
                                            usingDirective.Name,
                                            imported.GetKindText(),
                                            MessageID.IDS_SK_TYPE_OR_NAMESPACE.Localize());
                        }

                        diagnostics.AddRange(directiveDiagnostics.DiagnosticBag);
                        directiveDiagnostics.Free();
                    }
                }

                uniqueUsings.Free();
            }

            if (diagnostics.IsEmptyWithoutResolution)
            {
                diagnostics = null;
            }

            return(new Imports(compilation, usingAliases.ToImmutableDictionaryOrEmpty(), usings.ToImmutableAndFree(), externAliases, diagnostics));
        }
예제 #10
0
        private void Validate()
        {
            if (this == Empty)
            {
                return;
            }

            DiagnosticBag semanticDiagnostics = _compilation.DeclarationDiagnostics;

            // Check constraints within named aliases.
            var diagnostics = BindingDiagnosticBag.GetInstance();

            // Force resolution of named aliases.
            foreach (var(_, alias) in UsingAliases)
            {
                NamespaceOrTypeSymbol target = alias.Alias.GetAliasTarget(basesBeingResolved: null);

                diagnostics.Clear();
                diagnostics.AddRange(alias.Alias.AliasTargetDiagnostics);

                alias.Alias.CheckConstraints(diagnostics);

                semanticDiagnostics.AddRange(diagnostics.DiagnosticBag);
                recordImportDependencies(alias.UsingDirective, target);
            }

            var corLibrary  = _compilation.SourceAssembly.CorLibrary;
            var conversions = new TypeConversions(corLibrary);

            foreach (var @using in Usings)
            {
                diagnostics.Clear();
                diagnostics.AddDependencies(@using.Dependencies);

                NamespaceOrTypeSymbol target = @using.NamespaceOrType;

                // Check if `using static` directives meet constraints.
                UsingDirectiveSyntax usingDirective = @using.UsingDirective;
                if (target.IsType)
                {
                    var typeSymbol = (TypeSymbol)target;
                    var location   = usingDirective?.Name.Location ?? NoLocation.Singleton;
                    typeSymbol.CheckAllConstraints(_compilation, conversions, location, diagnostics);
                }

                semanticDiagnostics.AddRange(diagnostics.DiagnosticBag);
                recordImportDependencies(usingDirective, target);
            }

            // Force resolution of extern aliases.
            foreach (var alias in ExternAliases)
            {
                var target = (NamespaceSymbol)alias.Alias.GetAliasTarget(null);
                Debug.Assert(target.IsGlobalNamespace);

                semanticDiagnostics.AddRange(alias.Alias.AliasTargetDiagnostics.DiagnosticBag);

                if (!Compilation.ReportUnusedImportsInTree(alias.ExternAliasDirective.SyntaxTree))
                {
                    diagnostics.Clear();
                    diagnostics.AddAssembliesUsedByNamespaceReference(target);
                    _compilation.AddUsedAssemblies(diagnostics.DependenciesBag);
                }
            }

            if (_diagnostics != null && !_diagnostics.IsEmptyWithoutResolution)
            {
                semanticDiagnostics.AddRange(_diagnostics.AsEnumerable());
            }

            diagnostics.Free();

            void recordImportDependencies(UsingDirectiveSyntax usingDirective, NamespaceOrTypeSymbol target)
            {
                if (usingDirective is object && Compilation.ReportUnusedImportsInTree(usingDirective.SyntaxTree))
                {
                    _compilation.RecordImportDependencies(usingDirective, diagnostics.DependenciesBag.ToImmutableArray());
                }
                else
                {
                    if (target.IsNamespace)
                    {
                        diagnostics.AddAssembliesUsedByNamespaceReference((NamespaceSymbol)target);
                    }

                    _compilation.AddUsedAssemblies(diagnostics.DependenciesBag);
                }
            }
        }
예제 #11
0
        public static Imports FromGlobalUsings(CSharpCompilation compilation)
        {
            var usings = compilation.Options.Usings;

            if (usings.Length == 0 && compilation.PreviousSubmission == null)
            {
                return(Empty);
            }

            var diagnostics  = new DiagnosticBag();
            var usingsBinder = new InContainerBinder(compilation.GlobalNamespace, new BuckStopsHereBinder(compilation));
            var boundUsings  = ArrayBuilder <NamespaceOrTypeAndUsingDirective> .GetInstance();

            var uniqueUsings = PooledHashSet <NamespaceOrTypeSymbol> .GetInstance();

            foreach (string @using in usings)
            {
                if ([email protected]())
                {
                    continue;
                }

                string[]   identifiers   = @using.Split('.');
                NameSyntax qualifiedName = SyntaxFactory.IdentifierName(identifiers[0]);

                for (int j = 1; j < identifiers.Length; j++)
                {
                    qualifiedName = SyntaxFactory.QualifiedName(left: qualifiedName, right: SyntaxFactory.IdentifierName(identifiers[j]));
                }

                var directiveDiagnostics = BindingDiagnosticBag.GetInstance();

                var imported = usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, directiveDiagnostics).NamespaceOrTypeSymbol;
                if (uniqueUsings.Add(imported))
                {
                    boundUsings.Add(new NamespaceOrTypeAndUsingDirective(imported, null, dependencies: directiveDiagnostics.DependenciesBag.ToImmutableArray()));
                }

                diagnostics.AddRange(directiveDiagnostics.DiagnosticBag);
                directiveDiagnostics.Free();
            }

            if (diagnostics.IsEmptyWithoutResolution)
            {
                diagnostics = null;
            }

            var previousSubmissionImports = compilation.PreviousSubmission?.GlobalImports;

            if (previousSubmissionImports != null)
            {
                // Currently, only usings are supported.
                Debug.Assert(previousSubmissionImports.UsingAliases.IsEmpty);
                Debug.Assert(previousSubmissionImports.ExternAliases.IsEmpty);

                var expandedImports = ExpandPreviousSubmissionImports(previousSubmissionImports, compilation);

                foreach (var previousUsing in expandedImports.Usings)
                {
                    if (uniqueUsings.Add(previousUsing.NamespaceOrType))
                    {
                        boundUsings.Add(previousUsing);
                    }
                }
            }

            uniqueUsings.Free();

            if (boundUsings.Count == 0)
            {
                boundUsings.Free();
                return(Empty);
            }

            return(new Imports(compilation, ImmutableDictionary <string, AliasAndUsingDirective> .Empty, boundUsings.ToImmutableAndFree(), ImmutableArray <AliasAndExternAliasDirective> .Empty, diagnostics));
        }