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

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeFixes/RemoveUnnecessaryCast/RemoveUnnecessaryCastCodeFixProvider.cs')
-rw-r--r--main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeFixes/RemoveUnnecessaryCast/RemoveUnnecessaryCastCodeFixProvider.cs122
1 files changed, 122 insertions, 0 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeFixes/RemoveUnnecessaryCast/RemoveUnnecessaryCastCodeFixProvider.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeFixes/RemoveUnnecessaryCast/RemoveUnnecessaryCastCodeFixProvider.cs
new file mode 100644
index 0000000000..63770abbdf
--- /dev/null
+++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeFixes/RemoveUnnecessaryCast/RemoveUnnecessaryCastCodeFixProvider.cs
@@ -0,0 +1,122 @@
+// 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;
+using System.Collections.Immutable;
+using System.Composition;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeActions;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp.Extensions;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Microsoft.CodeAnalysis.Formatting;
+using Microsoft.CodeAnalysis.Shared.Extensions;
+using Microsoft.CodeAnalysis.Simplification;
+using Microsoft.CodeAnalysis.Text;
+using Microsoft.CodeAnalysis;
+using MonoDevelop.CSharp.Diagnostics;
+using ICSharpCode.NRefactory6.CSharp;
+using MonoDevelop.Core;
+using ICSharpCode.NRefactory6.CSharp.Refactoring;
+using Microsoft.CodeAnalysis.CSharp;
+
+namespace MonoDevelop.CSharp.CodeFixes.RemoveUnnecessaryCast
+{
+ [ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnnecessaryCast), Shared]
+ [ExtensionOrder(After = PredefinedCodeFixProviderNames.ImplementInterface)]
+ internal partial class RemoveUnnecessaryCastCodeFixProvider : CodeFixProvider
+ {
+ public sealed override ImmutableArray<string> FixableDiagnosticIds
+ {
+ get { return ImmutableArray.Create(IDEDiagnosticIds.RemoveUnnecessaryCastDiagnosticId); }
+ }
+
+// public sealed override FixAllProvider GetFixAllProvider()
+// {
+// return RemoveUnnecessaryCastFixAllProvider.Instance;
+// }
+//
+ private static CastExpressionSyntax GetCastNode(SyntaxNode root, SemanticModel model, TextSpan span, CancellationToken cancellationToken)
+ {
+ var token = root.FindToken(span.Start);
+ if (!token.Span.IntersectsWith(span))
+ {
+ return null;
+ }
+
+ return token.GetAncestors<CastExpressionSyntax>()
+ .FirstOrDefault(c => c.Span.IntersectsWith(span) && c.IsUnnecessaryCast(model, cancellationToken));
+ }
+
+ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
+ {
+ var document = context.Document;
+ var span = context.Span;
+ var cancellationToken = context.CancellationToken;
+
+ var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
+ var node = GetCastNode(root, model, span, cancellationToken);
+ if (node == null)
+ {
+ return;
+ }
+
+ context.RegisterCodeFix(
+ new DocumentChangeAction(node.Span, DiagnosticSeverity.Warning,
+ GettextCatalog.GetString ("Remove Unnecessary Cast"),
+ (c) => RemoveUnnecessaryCastAsync(document, node, c)),
+ context.Diagnostics);
+ }
+
+ private static async Task<Document> RemoveUnnecessaryCastAsync(Document document, CastExpressionSyntax cast, CancellationToken cancellationToken)
+ {
+ var annotatedCast = cast.WithAdditionalAnnotations(Simplifier.Annotation);
+
+ if (annotatedCast.Expression is ParenthesizedExpressionSyntax)
+ {
+ annotatedCast = annotatedCast.WithExpression(
+ annotatedCast.Expression.WithAdditionalAnnotations(Simplifier.Annotation));
+ }
+ else
+ {
+ annotatedCast = annotatedCast.WithExpression(
+ annotatedCast.Expression.Parenthesize());
+ }
+
+ ExpressionSyntax oldNode = cast;
+ ExpressionSyntax newNode = annotatedCast;
+
+ // Ensure that we simplify any parenting parenthesized expressions not just on the syntax tree level but also on Token based
+ // Case 1:
+ // In the syntax, (((Task<Action>)x).Result)()
+ // oldNode = (Task<Action>)x
+ // newNode = (Task<Action>)(x)
+ // Final newNode will be (((Task<Action>)(x)).Result)
+ while (oldNode.Parent.IsKind(SyntaxKind.ParenthesizedExpression) || oldNode.GetFirstToken().GetPreviousToken().Parent.IsKind(SyntaxKind.ParenthesizedExpression))
+ {
+ var parenthesizedExpression = (ParenthesizedExpressionSyntax)oldNode.GetFirstToken().GetPreviousToken().Parent;
+ newNode = parenthesizedExpression.ReplaceNode(oldNode, newNode)
+ .WithAdditionalAnnotations(Simplifier.Annotation);
+ oldNode = parenthesizedExpression;
+ }
+
+ newNode = newNode.WithAdditionalAnnotations(Formatter.Annotation);
+
+ var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
+ var newRoot = root.ReplaceNode(oldNode, newNode);
+
+ return document.WithSyntaxRoot(newRoot);
+ }
+//
+// private class MyCodeAction : CodeAction.DocumentChangeAction
+// {
+// public MyCodeAction(string title, Func<CancellationToken, Task<Document>> createChangedDocument) :
+// base(title, createChangedDocument)
+// {
+// }
+// }
+ }
+}