diff options
Diffstat (limited to 'main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.InitializerRewriter.cs')
-rw-r--r-- | main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.InitializerRewriter.cs | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.InitializerRewriter.cs b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.InitializerRewriter.cs new file mode 100644 index 0000000000..e6866a9f25 --- /dev/null +++ b/main/src/addins/CSharpBinding/MonoDevelop.CSharp.CodeRefactorings/InlineTemporary/InlineTemporaryCodeRefactoringProvider.InitializerRewriter.cs @@ -0,0 +1,107 @@ +// 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 Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Extensions; +using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Simplification; +using Microsoft.CodeAnalysis.CSharp; +using ICSharpCode.NRefactory6.CSharp; + +namespace MonoDevelop.CSharp.CodeRefactorings.InlineTemporary +{ + internal partial class InlineTemporaryCodeRefactoringProvider + { + /// <summary> + /// This class handles rewriting initializer expressions that refer to the variable + /// being initialized into a simpler form. For example, in "int x = x = 1", we want to + /// get just "1" back as the initializer. + /// </summary> + private class InitializerRewriter : CSharpSyntaxRewriter + { + private readonly SemanticModel _semanticModel; + private readonly ILocalSymbol _localSymbol; + private readonly ExpressionSyntax _initializer; + + private InitializerRewriter(ExpressionSyntax initializer, ILocalSymbol localSymbol, SemanticModel semanticModel) + { + _semanticModel = semanticModel; + _localSymbol = localSymbol; + _initializer = initializer; + } + + private bool IsReference(SimpleNameSyntax name) + { + if (name.Identifier.ValueText != _localSymbol.Name) + { + return false; + } + + var symbol = _semanticModel.GetSymbolInfo(name).Symbol; + return symbol != null + && symbol.Equals(_localSymbol); + } + + public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node) + { + // Note - leave this as SyntaxNode for now, we might have already re-written it + var newNode = base.VisitAssignmentExpression(node); + + if (newNode.Kind() == SyntaxKind.SimpleAssignmentExpression) + { + // It's okay to just look at the text, since we're explicitly looking for an + // identifier standing alone, and we know we're in a local's initializer. + // The text can only bind to the initializer. + var assignment = (AssignmentExpressionSyntax)newNode; + var name = assignment.Left.Kind() == SyntaxKind.IdentifierName + ? (IdentifierNameSyntax)assignment.Left + : null; + + if (name != null && IsReference(name)) + { + return assignment.Right; + } + } + + return newNode; + } + + public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) + { + if (IsReference(node)) + { + var assignmentExpression = node.Parent as AssignmentExpressionSyntax; + if (assignmentExpression != null) + { + if (assignmentExpression.IsCompoundAssignExpression() && + assignmentExpression.Left == node) + { + return node.Update(node.Identifier.WithAdditionalAnnotations(CreateConflictAnnotation())); + } + } + } + + return base.VisitIdentifierName(node); + } + + public override SyntaxNode VisitParenthesizedExpression(ParenthesizedExpressionSyntax node) + { + var newNode = base.VisitParenthesizedExpression(node); + + if (node != newNode && newNode.Kind() == SyntaxKind.ParenthesizedExpression) + { + return newNode.WithAdditionalAnnotations(Simplifier.Annotation); + } + + return newNode; + } + + public static ExpressionSyntax Visit(ExpressionSyntax initializer, ILocalSymbol local, SemanticModel semanticModel) + { + var simplifier = new InitializerRewriter(initializer, local, semanticModel); + return (ExpressionSyntax)simplifier.Visit(initializer); + } + } + } +} |