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 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)); }