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

ExtractMethodCodeRefactoringProvider.cs « ExtractMethod « MonoDevelop.CSharp.CodeRefactorings « CSharpBinding « addins « src « main - github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 9ad0da43567b7a31ac645ecd09e8e3d8057f8e4a (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
// 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.Composition;
using Microsoft.CodeAnalysis.CodeRefactorings;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using System;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
using System.Threading;
using ICSharpCode.NRefactory6.CSharp.ExtractMethod;
using ICSharpCode.NRefactory6.CSharp.Refactoring;
using MonoDevelop.Core;
using MonoDevelop.Ide;
using ICSharpCode.NRefactory6.CSharp;

namespace MonoDevelop.CSharp.CodeRefactorings.ExtractMethod
{
	[ExportCodeRefactoringProvider(LanguageNames.CSharp, Name = PredefinedCodeRefactoringProviderNames.ExtractMethod), Shared]
	internal class ExtractMethodCodeRefactoringProvider : CodeRefactoringProvider
	{
		public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
		{
			// Don't bother if there isn't a selection
			var textSpan = context.Span;
			if (textSpan.IsEmpty)
			{
				return;
			}
			var document = context.Document;
			var cancellationToken = context.CancellationToken;

			var workspace = document.Project.Solution.Workspace;
			if (workspace.Kind == WorkspaceKind.MiscellaneousFiles)
			{
				return;
			}

			var activeInlineRenameSession = IdeApp.Workbench.ActiveDocument.Editor.EditMode != MonoDevelop.Ide.Editor.EditMode.Edit;
			if (activeInlineRenameSession)
			{
				return;
			}
			var model = await context.Document.GetSemanticModelAsync (context.CancellationToken).ConfigureAwait (false);
			if (model.IsFromGeneratedCode (context.CancellationToken))
				return;
			
			if (cancellationToken.IsCancellationRequested)
			{
				return;
			}

			var action = await GetCodeActionAsync(document, textSpan, cancellationToken: cancellationToken).ConfigureAwait(false);
			if (action == null)
			{
				return;
			}

			context.RegisterRefactoring(action.Item1);
		}

		static CSharpExtractMethodService service = new CSharpExtractMethodService ();

		private async Task<Tuple<CodeAction, string>> GetCodeActionAsync(
			Document document,
			TextSpan textSpan,
			CancellationToken cancellationToken)
		{
			var options = document.Project.Solution.Workspace.Options;
			try {
				var result = await service.ExtractMethodAsync(
					document,
					textSpan,
					options,
					cancellationToken).ConfigureAwait(false);

				if (result.Succeeded || result.SucceededWithSuggestion)
				{
					var description = options.GetOption(ExtractMethodOptions.AllowMovingDeclaration, document.Project.Language) ?
						GettextCatalog.GetString ("Extract Method + Local") : GettextCatalog.GetString ("Extract Method");

					var codeAction = new DocumentChangeAction(textSpan, DiagnosticSeverity.Info, description, (c) => AddRenameAnnotationAsync(result.Document, result.InvocationNameToken, c));
					var methodBlock = result.MethodDeclarationNode;

					return Tuple.Create<CodeAction, string>(codeAction, methodBlock.ToString());
				}
			} catch (Exception) {
				// currently the extract method refactoring crashes often. Ignore the roslyn issues for now.
			}
			return null;
		}

		private async Task<Document> AddRenameAnnotationAsync(Document document, SyntaxToken invocationNameToken, CancellationToken cancellationToken)
		{
			var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

			var finalRoot = root.ReplaceToken(
				invocationNameToken,
				invocationNameToken.WithAdditionalAnnotations(RenameAnnotation.Create()));

			return document.WithSyntaxRoot(finalRoot);
		}
	}
}