Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CSharpRemoveUnnecessaryImportsService.cs « RemoveUnnecessaryImports « MonoDevelop.CSharp.Features « CSharpBinding « addins « src « main - github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fd5496194c962560ee306814da5968d7bdfac2b9 (plain)
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Composition;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis;

namespace ICSharpCode.NRefactory6.CSharp.Features.RemoveUnnecessaryImports
{
	partial class CSharpRemoveUnnecessaryImportsService
	{
		public static IEnumerable<SyntaxNode> GetUnnecessaryImports(SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken)
		{
			var diagnostics = semanticModel.GetDiagnostics(cancellationToken: cancellationToken);
			if (!diagnostics.Any())
			{
				return null;
			}

			var unnecessaryImports = new HashSet<UsingDirectiveSyntax>();

			foreach (var diagnostic in diagnostics)
			{
				if (diagnostic.Id == "CS8019")
				{
					var node = root.FindNode(diagnostic.Location.SourceSpan) as UsingDirectiveSyntax;

					if (node != null)
					{
						unnecessaryImports.Add(node);
					}
				}
			}

			if (cancellationToken.IsCancellationRequested || !unnecessaryImports.Any())
			{
				return null;
			}

			return unnecessaryImports;
		}

		public Document RemoveUnnecessaryImports(Document document, SemanticModel model, SyntaxNode root, CancellationToken cancellationToken)
		{
			var unnecessaryImports = GetUnnecessaryImports(model, root, cancellationToken) as ISet<UsingDirectiveSyntax>;
			if (unnecessaryImports == null)
			{
				return document;
			}

			var oldRoot = (CompilationUnitSyntax)root;
			if (unnecessaryImports.Any(import => oldRoot.OverlapsHiddenPosition(cancellationToken)))
			{
				return document;
			}

			var newRoot = (CompilationUnitSyntax)new Rewriter(unnecessaryImports, cancellationToken).Visit(oldRoot);
			if (cancellationToken.IsCancellationRequested)
			{
				return null;
			}

			return document.WithSyntaxRoot(FormatResult(document, newRoot, cancellationToken));
		}

		private SyntaxNode FormatResult(Document document, CompilationUnitSyntax newRoot, CancellationToken cancellationToken)
		{
			var spans = new List<TextSpan>();
			AddFormattingSpans(newRoot, spans, cancellationToken);
			return Formatter.Format(newRoot, spans, document.Project.Solution.Workspace, document.Project.Solution.Workspace.Options, cancellationToken: cancellationToken);
		}

		private void AddFormattingSpans(
			CompilationUnitSyntax compilationUnit,
			List<TextSpan> spans,
			CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			spans.Add(TextSpan.FromBounds(0, GetEndPosition(compilationUnit, compilationUnit.Members)));

			foreach (var @namespace in compilationUnit.Members.OfType<NamespaceDeclarationSyntax>())
			{
				AddFormattingSpans(@namespace, spans, cancellationToken);
			}
		}

		private void AddFormattingSpans(
			NamespaceDeclarationSyntax namespaceMember,
			List<TextSpan> spans,
			CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();
			spans.Add(TextSpan.FromBounds(namespaceMember.SpanStart, GetEndPosition(namespaceMember, namespaceMember.Members)));

			foreach (var @namespace in namespaceMember.Members.OfType<NamespaceDeclarationSyntax>())
			{
				AddFormattingSpans(@namespace, spans, cancellationToken);
			}
		}

		private int GetEndPosition(SyntaxNode container, SyntaxList<MemberDeclarationSyntax> list)
		{
			return list.Count > 0 ? list[0].SpanStart : container.Span.End;
		}
	}
}