Example #1
0
        /// <summary>
        /// Returns binder that binds usings and aliases
        /// </summary>
        /// <param name="unit">
        /// Specify <see cref="NamespaceDeclarationSyntax"/> imports in the corresponding namespace, or
        /// <see cref="CompilationUnitSyntax"/> for top-level imports.
        /// </param>
        /// <param name="inUsing">True if the binder will be used to bind a using directive.</param>
        internal InContainerBinder GetImportsBinder(CSharpSyntaxNode unit, bool inUsing = false)
        {
            switch (unit.Kind())
            {
            case SyntaxKind.NamespaceDeclaration:
            {
                BinderFactoryVisitor visitor = _binderFactoryVisitorPool.Allocate();
                visitor.Initialize(0, null, null);
                InContainerBinder result = visitor.VisitNamespaceDeclaration((NamespaceDeclarationSyntax)unit, unit.SpanStart, inBody: true, inUsing: inUsing);
                _binderFactoryVisitorPool.Free(visitor);
                return(result);
            }

            case SyntaxKind.CompilationUnit:
                // imports are bound by the Script class binder:
            {
                BinderFactoryVisitor visitor = _binderFactoryVisitorPool.Allocate();
                visitor.Initialize(0, null, null);
                InContainerBinder result = visitor.VisitCompilationUnit((CompilationUnitSyntax)unit, inUsing: inUsing, inScript: InScript);
                _binderFactoryVisitorPool.Free(visitor);
                return(result);
            }

            default:
                return(null);
            }
        }
Example #2
0
        public static Imports FromGlobalUsings(CSharpCompilation compilation)
        {
            var usings       = compilation.Options.Usings;
            var diagnostics  = DiagnosticBag.GetInstance();
            var usingsBinder = new InContainerBinder(compilation.GlobalNamespace, new BuckStopsHereBinder(compilation));
            var boundUsings  = ArrayBuilder <NamespaceOrTypeAndUsingDirective> .GetInstance();

            foreach (string ns in usings)
            {
                if (!ns.IsValidClrNamespaceName())
                {
                    continue;
                }

                string[]   identifiers   = ns.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]));
                }

                boundUsings.Add(new NamespaceOrTypeAndUsingDirective(usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, diagnostics), null));
            }

            return(new Imports(compilation, null, boundUsings.ToImmutableAndFree(), ImmutableArray <AliasAndExternAliasDirective> .Empty, diagnostics.ToReadOnlyAndFree()));
        }
Example #3
0
        private static ImmutableArray <AliasAndExternAliasDirective> BuildExternAliases(
            SyntaxList <ExternAliasDirectiveSyntax> syntaxList,
            InContainerBinder binder,
            DiagnosticBag diagnostics
            )
        {
            CSharpCompilation compilation = binder.Compilation;

            var builder = ArrayBuilder <AliasAndExternAliasDirective> .GetInstance();

            foreach (ExternAliasDirectiveSyntax aliasSyntax in syntaxList)
            {
                compilation.RecordImport(aliasSyntax);

                // Extern aliases not allowed in interactive submissions:
                if (compilation.IsSubmission)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternAliasNotAllowed, aliasSyntax.Location);
                    continue;
                }

                // some n^2 action, but n should be very small.
                foreach (var existingAlias in builder)
                {
                    if (existingAlias.Alias.Name == aliasSyntax.Identifier.ValueText)
                    {
                        diagnostics.Add(
                            ErrorCode.ERR_DuplicateAlias,
                            existingAlias.Alias.Locations[0],
                            existingAlias.Alias.Name
                            );
                        break;
                    }
                }

                if (aliasSyntax.Identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
                {
                    diagnostics.Add(
                        ErrorCode.ERR_GlobalExternAlias,
                        aliasSyntax.Identifier.GetLocation()
                        );
                }

                builder.Add(
                    new AliasAndExternAliasDirective(
                        new AliasSymbol(binder, aliasSyntax),
                        aliasSyntax
                        )
                    );
            }

            return(builder.ToImmutableAndFree());
        }
Example #4
0
        public static Imports FromGlobalUsings(CSharpCompilation compilation)
        {
            var usings       = compilation.Options.Usings;
            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 imported = usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, diagnostics);
                if (uniqueUsings.Add(imported))
                {
                    boundUsings.Add(new NamespaceOrTypeAndUsingDirective(imported, null));
                }
            }

            uniqueUsings.Free();

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

            return(new Imports(compilation, ImmutableDictionary <string, AliasAndUsingDirective> .Empty, boundUsings.ToImmutableAndFree(), ImmutableArray <AliasAndExternAliasDirective> .Empty, diagnostics));
        }
Example #5
0
        public static Imports FromSyntax(
            CSharpSyntaxNode declarationSyntax,
            InContainerBinder binder,
            ConsList <Symbol> 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 = PooledHashSet <NamespaceOrTypeSymbol> .GetInstance();

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

                    if (usingDirective.Alias != null)
                    {
                        if (usingDirective.Alias.Name.Identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
                        {
                            diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, usingDirective.Alias.Name.Location);
                        }

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

                        string identifierValueText = usingDirective.Alias.Name.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, usingDirective.Alias.Name.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), usingDirective));
                        }
                    }
                    else
                    {
                        if (usingDirective.Name.IsMissing)
                        {
                            //don't try to lookup namespaces inserted by parser error recovery
                            continue;
                        }

                        var declarationBinder = usingsBinder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);
                        var imported          = declarationBinder.BindNamespaceOrTypeSymbol(usingDirective.Name, diagnostics, basesBeingResolved).NamespaceOrTypeSymbol;
                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            if (usingDirective.StaticKeyword != default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingType, usingDirective.Name.Location, imported);
                            }
                            else if (uniqueUsings.Contains(imported))
                            {
                                diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                uniqueUsings.Add(imported);
                                usings.Add(new NamespaceOrTypeAndUsingDirective(imported, usingDirective));
                            }
                        }
                        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));
                                }
                            }
                        }
                        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());
                        }
                    }
                }

                uniqueUsings.Free();
            }

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

            return(new Imports(compilation, usingAliases.ToImmutableDictionaryOrEmpty(), usings.ToImmutableAndFree(), externAliases, diagnostics));
        }
Example #6
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 imported = usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, diagnostics).NamespaceOrTypeSymbol;
                if (uniqueUsings.Add(imported))
                {
                    boundUsings.Add(new NamespaceOrTypeAndUsingDirective(imported, null));
                }
            }

            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));
        }
Example #7
0
        public static Imports FromSyntax(
            CSharpSyntaxNode declarationSyntax,
            InContainerBinder binder,
            ConsList <Symbol> basesBeingResolved,
            bool inUsing)
        {
            SyntaxList <UsingDirectiveSyntax>       usingDirectives;
            SyntaxList <ExternAliasDirectiveSyntax> externAliasDirectives;

            if (declarationSyntax.Kind == SyntaxKind.CompilationUnit)
            {
                var compilation = (CompilationUnitSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives       = inUsing ? default(SyntaxList <UsingDirectiveSyntax>) : compilation.Usings;
                externAliasDirectives = compilation.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);
            }

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

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

            var diagnostics = DiagnosticBag.GetInstance();

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

            Dictionary <string, AliasAndUsingDirective> 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.
                InContainerBinder usingsBinder;
                if (binder.Container.IsSubmissionClass)
                {
                    // Top-level usings in interactive code are resolved in the context of global namespace, w/o extern aliases:
                    usingsBinder = new InContainerBinder(binder.Compilation.GlobalNamespace, new BuckStopsHereBinder(binder.Compilation));
                }
                else
                {
                    usingsBinder = new InContainerBinder(binder.Container, binder.Next,
                                                         new Imports(binder.Compilation, null, ImmutableArray <NamespaceOrTypeAndUsingDirective> .Empty, externAliases, default(ImmutableArray <Diagnostic>)));
                }

                var uniqueUsings = new HashSet <NamespaceOrTypeSymbol>();

                foreach (var u in usingDirectives)
                {
                    binder.Compilation.RecordImport(u);

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

                            if (usingAliases == null)
                            {
                                usingAliases = new Dictionary <string, AliasAndUsingDirective>();
                            }

                            // EDMAURER 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, u), u));
                        }
                    }
                    else
                    {
                        if (u.Name.IsMissing)
                        {
                            //don't try to lookup namespaces inserted by parser error recovery
                            continue;
                        }

                        var imported = usingsBinder.BindNamespaceOrTypeSymbol(u.Name, diagnostics, basesBeingResolved);
                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            if (uniqueUsings.Contains(imported))
                            {
                                diagnostics.Add(ErrorCode.WRN_DuplicateUsing, u.Name.Location, imported);
                            }
                            else
                            {
                                uniqueUsings.Add(imported);
                                usings.Add(new NamespaceOrTypeAndUsingDirective(imported, u));
                            }
                        }
                        else if (imported.Kind == SymbolKind.NamedType)
                        {
                            var importedType = (NamedTypeSymbol)imported;
                            if (!binder.AllowStaticClassUsings)
                            {
                                // error: A using directive can only be applied to namespace; '{0}' is a type not a namespace
                                diagnostics.Add(ErrorCode.ERR_BadUsingNamespace, u.Name.Location, importedType);
                            }
                            else if (importedType.IsStatic && importedType.TypeKind == TypeKind.Class)
                            {
                                if (uniqueUsings.Contains(importedType))
                                {
                                    diagnostics.Add(ErrorCode.WRN_DuplicateUsing, u.Name.Location, importedType);
                                }
                                else
                                {
                                    uniqueUsings.Add(importedType);
                                    usings.Add(new NamespaceOrTypeAndUsingDirective(importedType, u));
                                }
                            }
                            else
                            {
                                // error: A using directive can only be applied to classes that are static; '{0}' is not a static class
                                diagnostics.Add(ErrorCode.ERR_BadUsingType, u.Name.Location, importedType);
                            }
                        }
                        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, u.Name.Location,
                                            u.Name,
                                            imported.GetKindText(),
                                            MessageID.IDS_SK_TYPE_OR_NAMESPACE.Localize());
                        }
                    }
                }
            }

            return(new Imports(binder.Compilation, usingAliases, usings.ToImmutableAndFree(), externAliases, diagnostics.ToReadOnlyAndFree()));
        }
Example #8
0
        public static Imports FromSyntax(
            CSharpSyntaxNode declarationSyntax,
            InContainerBinder binder,
            ConsList<Symbol> basesBeingResolved,
            bool inUsing)
        {
            SyntaxList<UsingDirectiveSyntax> usingDirectives;
            SyntaxList<ExternAliasDirectiveSyntax> externAliasDirectives;
            if (declarationSyntax.Kind() == SyntaxKind.CompilationUnit)
            {
                var compilation = (CompilationUnitSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives = inUsing ? default(SyntaxList<UsingDirectiveSyntax>) : compilation.Usings;
                externAliasDirectives = compilation.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=Foo::Bar;
            // using Foo::Baz;
            // extern alias Foo;

            var diagnostics = new DiagnosticBag();

            var externAliases = BuildExternAliases(externAliasDirectives, binder, diagnostics);
            var usings = ArrayBuilder<NamespaceOrTypeAndUsingDirective>.GetInstance();
            Dictionary<string, AliasAndUsingDirective> 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.
                var usingsBinder = binder.IsSubmissionClass ?
                    // Top-level usings in interactive code are resolved in the context of global namespace, w/o extern aliases:
                    new InContainerBinder(binder.Compilation.GlobalNamespace, new BuckStopsHereBinder(binder.Compilation)) :
                    new InContainerBinder(binder.Container, binder.Next,
                        new Imports(binder.Compilation, null, ImmutableArray<NamespaceOrTypeAndUsingDirective>.Empty, externAliases, null));

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

                foreach (var usingDirective in usingDirectives)
                {
                    binder.Compilation.RecordImport(usingDirective);

                    if (usingDirective.Alias != null)
                    {
                        if (usingDirective.StaticKeyword != default(SyntaxToken))
                        {
                            diagnostics.Add(ErrorCode.ERR_NoAliasHere, usingDirective.Alias.Name.Location);
                        }

                        string identifierValueText = usingDirective.Alias.Name.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, usingDirective.Alias.Name.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 = new Dictionary<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), usingDirective));
                        }
                    }
                    else
                    {
                        if (usingDirective.Name.IsMissing)
                        {
                            //don't try to lookup namespaces inserted by parser error recovery
                            continue;
                        }

                        var imported = usingsBinder.BindNamespaceOrTypeSymbol(usingDirective.Name, diagnostics, basesBeingResolved);
                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            if (usingDirective.StaticKeyword != default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingType, usingDirective.Name.Location, imported);
                            }
                            else if (uniqueUsings.Contains(imported))
                            {
                                diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                uniqueUsings.Add(imported);
                                usings.Add(new NamespaceOrTypeAndUsingDirective(imported, usingDirective));
                            }
                        }
                        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
                                {
                                    uniqueUsings.Add(importedType);
                                    usings.Add(new NamespaceOrTypeAndUsingDirective(importedType, usingDirective));
                                }
                            }
                        }
                        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());
                        }
                    }
                }

                uniqueUsings.Free();
            }

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

            return new Imports(binder.Compilation, usingAliases, usings.ToImmutableAndFree(), externAliases, diagnostics);
        }
Example #9
0
        private static ImmutableArray<AliasAndExternAliasDirective> BuildExternAliases(
            SyntaxList<ExternAliasDirectiveSyntax> syntaxList,
            InContainerBinder binder,
            DiagnosticBag diagnostics)
        {
            CSharpCompilation compilation = binder.Compilation;

            var builder = ArrayBuilder<AliasAndExternAliasDirective>.GetInstance();

            foreach (ExternAliasDirectiveSyntax aliasSyntax in syntaxList)
            {
                compilation.RecordImport(aliasSyntax);

                // Extern aliases not allowed in interactive submissions:
                if (compilation.IsSubmission)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternAliasNotAllowed, aliasSyntax.Location);
                    continue;
                }

                // some n^2 action, but n should be very small.
                foreach (var existingAlias in builder)
                {
                    if (existingAlias.Alias.Name == aliasSyntax.Identifier.ValueText)
                    {
                        diagnostics.Add(ErrorCode.ERR_DuplicateAlias, existingAlias.Alias.Locations[0], existingAlias.Alias.Name);
                        break;
                    }
                }

                if (aliasSyntax.Identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
                {
                    diagnostics.Add(ErrorCode.ERR_GlobalExternAlias, aliasSyntax.Identifier.GetLocation());
                }

                builder.Add(new AliasAndExternAliasDirective(new AliasSymbol(binder, aliasSyntax), aliasSyntax));
            }

            return builder.ToImmutableAndFree();
        }
Example #10
0
        public static Imports FromGlobalUsings(CSharpCompilation compilation)
        {
            var usings = compilation.Options.Usings;
            var diagnostics = new DiagnosticBag();
            var usingsBinder = new InContainerBinder(compilation.GlobalNamespace, new BuckStopsHereBinder(compilation));
            var boundUsings = ArrayBuilder<NamespaceOrTypeAndUsingDirective>.GetInstance();

            foreach (string ns in usings)
            {
                if (!ns.IsValidClrNamespaceName())
                {
                    continue;
                }

                string[] identifiers = ns.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]));
                }

                boundUsings.Add(new NamespaceOrTypeAndUsingDirective(usingsBinder.BindNamespaceOrTypeSymbol(qualifiedName, diagnostics), null));
            }

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

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