private void AddExterns( ref CompilationUnitSyntax root, ref NamespaceDeclarationSyntax namespaceToUpdate, ExternAliasDirectiveSyntax externAliasDirective) { if (namespaceToUpdate != null) { namespaceToUpdate = namespaceToUpdate.AddExterns(externAliasDirective); } else { root = root.AddExterns(externAliasDirective); } }
private async Task <CompilationUnitSyntax> AddImportWorkerAsync( Document document, CompilationUnitSyntax root, SyntaxNode contextNode, INamespaceOrTypeSymbol namespaceOrTypeSymbol, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var simpleUsingDirective = GetUsingDirective(root, namespaceOrTypeSymbol, semanticModel, fullyQualify: false); var externAliasUsingDirective = GetExternAliasUsingDirective(root, namespaceOrTypeSymbol, semanticModel); if (externAliasUsingDirective != null) { root = root.AddExterns( externAliasUsingDirective .WithAdditionalAnnotations(Formatter.Annotation)); } if (simpleUsingDirective == null) { return(root); } // Because of the way usings can be nested inside of namespace declarations, // we need to check if the usings must be fully qualified so as not to be // ambiguous with the containing namespace. if (UsingsAreContainedInNamespace(contextNode)) { // When we add usings we try and place them, as best we can, where the user // wants them according to their settings. This means we can't just add the fully- // qualified usings and expect the simplifier to take care of it, the usings have to be // simplified before we attempt to add them to the document. // You might be tempted to think that we could call // AddUsings -> Simplifier -> SortUsings // But this will clobber the users using settings without asking. Instead we create a new // Document and check if our using can be simplified. Worst case we need to back out the // fully qualified change and reapply with the simple name. var fullyQualifiedUsingDirective = GetUsingDirective(root, namespaceOrTypeSymbol, semanticModel, fullyQualify: true); var newRoot = root.AddUsingDirective( fullyQualifiedUsingDirective, contextNode, placeSystemNamespaceFirst, Formatter.Annotation); var newUsing = newRoot .DescendantNodes().OfType <UsingDirectiveSyntax>() .Where(uds => uds.IsEquivalentTo(fullyQualifiedUsingDirective, topLevel: true)) .Single(); newRoot = newRoot.TrackNodes(newUsing); var documentWithSyntaxRoot = document.WithSyntaxRoot(newRoot); var options = document.Project.Solution.Workspace.Options; var simplifiedDocument = await Simplifier.ReduceAsync(documentWithSyntaxRoot, newUsing.Span, options, cancellationToken).ConfigureAwait(false); newRoot = (CompilationUnitSyntax)await simplifiedDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var simplifiedUsing = newRoot.GetCurrentNode(newUsing); if (simplifiedUsing.Name.IsEquivalentTo(newUsing.Name, topLevel: true)) { // Not fully qualifying the using causes to refer to a different namespace so we need to keep it as is. return((CompilationUnitSyntax)await documentWithSyntaxRoot.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false)); } else { // It does not matter if it is fully qualified or simple so lets return the simple name. return(root.AddUsingDirective( simplifiedUsing.WithoutAnnotations(), contextNode, placeSystemNamespaceFirst, Formatter.Annotation)); } } else { // simple form return(root.AddUsingDirective( simpleUsingDirective, contextNode, placeSystemNamespaceFirst, Formatter.Annotation)); } }