private (UsingDirectiveSyntax, bool hasExistingImport) GetUsingDirective(
            Document document,
            INamespaceOrTypeSymbol namespaceOrTypeSymbol,
            SemanticModel semanticModel,
            CompilationUnitSyntax root,
            SyntaxNode contextNode)
        {
            var addImportService = document.GetLanguageService <IAddImportsService>();
            var generator        = SyntaxGenerator.GetGenerator(document);

            var nameSyntax = namespaceOrTypeSymbol.GenerateNameSyntax();

            // We need to create our using in two passes.  This is because we need a using
            // directive so we can figure out where to put it.  Then, once we figure out
            // where to put it, we might need to change it a bit (e.g. removing 'global'
            // from it if necessary).  So we first create a dummy using directive just to
            // determine which container we're going in.  Then we'll use the container to
            // help create the final using.
            var dummyUsing = SyntaxFactory.UsingDirective(nameSyntax);

            var container        = addImportService.GetImportContainer(root, contextNode, dummyUsing);
            var namespaceToAddTo = container as NamespaceDeclarationSyntax;

            // Replace the alias that GenerateTypeSyntax added if we want this to be looked
            // up off of an extern alias.
            var(externAliasDirective, _) = GetExternAliasDirective(
                namespaceOrTypeSymbol, semanticModel, contextNode);

            var externAlias = externAliasDirective?.Identifier.ValueText;

            if (externAlias != null)
            {
                nameSyntax = AddOrReplaceAlias(nameSyntax, SyntaxFactory.IdentifierName(externAlias));
            }
            else
            {
                // The name we generated will have the global:: alias on it.  We only need
                // that if the name of our symbol is actually ambiguous in this context.
                // If so, keep global:: on it, otherwise remove it.
                //
                // Note: doing this has a couple of benefits.  First, it's easy for us to see
                // if we have an existing using for this with the same syntax.  Second,
                // it's easy to sort usings properly.  If "global::" was attached to the
                // using directive, then it would make both of those operations more difficult
                // to achieve.
                nameSyntax = RemoveGlobalAliasIfUnnecessary(semanticModel, nameSyntax, namespaceToAddTo);
            }

            var usingDirective = SyntaxFactory.UsingDirective(nameSyntax)
                                 .WithAdditionalAnnotations(Formatter.Annotation);

            usingDirective = namespaceOrTypeSymbol.IsKind(SymbolKind.Namespace)
                ? usingDirective
                : usingDirective.WithStaticKeyword(SyntaxFactory.Token(SyntaxKind.StaticKeyword));

            return(usingDirective, addImportService.HasExistingImport(semanticModel.Compilation, root, contextNode, usingDirective, generator));
        }
Exemple #2
0
        private UsingDirectiveSyntax TryGetUsingDirective(
            INamespaceOrTypeSymbol namespaceOrTypeSymbol,
            SemanticModel semanticModel,
            CompilationUnitSyntax root,
            SyntaxNode contextNode)
        {
            var namespaceToAddTo = GetFirstContainingNamespaceWithUsings(contextNode);
            var usingDirectives  = namespaceToAddTo?.Usings ?? root.Usings;

            var nameSyntax = namespaceOrTypeSymbol.GenerateNameSyntax();

            // Replace the alias that GenerateTypeSyntax added if we want this to be looked
            // up off of an extern alias.
            var externAliasDirective = TryGetExternAliasDirective(
                namespaceOrTypeSymbol, semanticModel, contextNode,
                checkForExistingExternAlias: false);

            var externAlias = externAliasDirective?.Identifier.ValueText;

            if (externAlias != null)
            {
                nameSyntax = AddOrReplaceAlias(nameSyntax, SyntaxFactory.IdentifierName(externAlias));
            }
            else
            {
                // The name we generated will have the global:: alias on it.  We only need
                // that if the name of our symbol is actually ambiguous in this context.
                // If so, keep global:: on it, otherwise remove it.
                //
                // Note: doing this has a couple of benefits.  First, it's easy for us to see
                // if we have an existing using for this with the same syntax.  Second,
                // it's easy to sort usings properly.  If "global::" was attached to the
                // using directive, then it would make both of those operations more difficult
                // to achieve.
                nameSyntax = RemoveGlobalAliasIfUnnecessary(semanticModel, nameSyntax, namespaceToAddTo);
            }

            var usingDirective = SyntaxFactory.UsingDirective(nameSyntax)
                                 .WithAdditionalAnnotations(Formatter.Annotation);

            if (HasExistingUsingDirective(root, namespaceToAddTo, usingDirective))
            {
                return(null);
            }

            return(namespaceOrTypeSymbol.IsKind(SymbolKind.Namespace)
                ? usingDirective
                : usingDirective.WithStaticKeyword(SyntaxFactory.Token(SyntaxKind.StaticKeyword)));
        }