forked from dotnet/roslynator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DeclareUsingDirectiveOnTopLevelRefactoring.cs
82 lines (63 loc) · 3.16 KB
/
DeclareUsingDirectiveOnTopLevelRefactoring.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Roslynator.CSharp.Refactorings;
internal static class DeclareUsingDirectiveOnTopLevelRefactoring
{
private static readonly SymbolDisplayFormat _symbolDisplayFormat = new(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters);
public static async Task<Document> RefactorAsync(
Document document,
NamespaceDeclarationSyntax namespaceDeclaration,
CancellationToken cancellationToken = default)
{
SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var compilationUnit = (CompilationUnitSyntax)root;
SyntaxList<UsingDirectiveSyntax> usings = namespaceDeclaration.Usings;
UsingDirectiveSyntax[] newUsings = usings
.Select(f => EnsureFullyQualifiedName(f, semanticModel, cancellationToken))
.ToArray();
newUsings[0] = newUsings[0].WithoutLeadingTrivia();
newUsings[newUsings.Length - 1] = newUsings[newUsings.Length - 1].WithoutTrailingTrivia();
CompilationUnitSyntax newCompilationUnit = compilationUnit
.RemoveNodes(usings, SyntaxRemoveOptions.KeepUnbalancedDirectives)
.AddUsings(
keepSingleLineCommentsOnTop: true,
usings: newUsings);
return document.WithSyntaxRoot(newCompilationUnit);
}
private static UsingDirectiveSyntax EnsureFullyQualifiedName(UsingDirectiveSyntax usingDirective, SemanticModel semanticModel, CancellationToken cancellationToken)
{
NameSyntax name = usingDirective.Name;
NameSyntax newName = EnsureFullyQualifiedName();
newName = newName.WithTriviaFrom(name);
return usingDirective.WithName(newName).WithFormatterAnnotation();
NameSyntax EnsureFullyQualifiedName()
{
ISymbol symbol = semanticModel.GetSymbol(name, cancellationToken);
if (symbol is not null)
{
if (semanticModel.GetAliasInfo(name, cancellationToken) is not null
|| !symbol.ContainingNamespace.IsGlobalNamespace)
{
SymbolKind kind = symbol.Kind;
if (kind == SymbolKind.Namespace)
{
return SyntaxFactory.ParseName(symbol.ToString()).WithTriviaFrom(name);
}
else if (kind == SymbolKind.NamedType)
{
return (NameSyntax)((INamedTypeSymbol)symbol).ToTypeSyntax(_symbolDisplayFormat).WithTriviaFrom(name);
}
}
}
return name;
}
}
}