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