From a741ec0dd89b4daccc684589d34b92ea3566b36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Wed, 30 Jan 2013 10:03:31 +0100 Subject: [PATCH] Introduce constant action can now replace more than one occurence (like declare local variable action). --- .../CodeActions/DeclareLocalVariableAction.cs | 2 +- .../CodeActions/IntroduceConstantAction.cs | 71 +++++++++++++++++-- .../CodeActions/IntroduceConstantTests.cs | 24 +++++++ 3 files changed, 89 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/DeclareLocalVariableAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/DeclareLocalVariableAction.cs index 62f8fa7504..a049b04f69 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/DeclareLocalVariableAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/DeclareLocalVariableAction.cs @@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } - class SearchNodeVisitior : DepthFirstAstVisitor + internal class SearchNodeVisitior : DepthFirstAstVisitor { readonly AstNode searchForNode; public readonly List Matches = new List (); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs index 37235016cc..e7d39c1cb6 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/IntroduceConstantAction.cs @@ -43,6 +43,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring yield break; } + var visitor = new DeclareLocalVariableAction.SearchNodeVisitior(pexpr); + + var node = context.GetNode (); + if (node != null) + node.AcceptVisitor(visitor); + var resolveResult = context.Resolve(pexpr); yield return new CodeAction(context.TranslateString("Create local constant"), script => { @@ -50,39 +56,90 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); if (service != null) name = service.CheckName(context, name, AffectedEntity.LocalConstant); - + var initializer = new VariableInitializer(name, pexpr.Clone()); var decl = new VariableDeclarationStatement() { Type = context.CreateShortType(resolveResult.Type), Modifiers = Modifiers.Const, Variables = { initializer } }; - + script.InsertBefore(statement, decl); var variableUsage = new IdentifierExpression(name); script.Replace(pexpr, variableUsage); script.Link(initializer.NameToken, variableUsage); }); - + yield return new CodeAction(context.TranslateString("Create constant field"), script => { string name = CreateMethodDeclarationAction.CreateBaseName(pexpr, resolveResult.Type); var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); if (service != null) name = service.CheckName(context, name, AffectedEntity.ConstantField); - + var initializer = new VariableInitializer(name, pexpr.Clone()); - + var decl = new FieldDeclaration() { ReturnType = context.CreateShortType(resolveResult.Type), Modifiers = Modifiers.Const, Variables = { initializer } }; - + var variableUsage = new IdentifierExpression(name); script.Replace(pexpr, variableUsage); -// script.Link(initializer.NameToken, variableUsage); + // script.Link(initializer.NameToken, variableUsage); script.InsertWithCursor(context.TranslateString("Create constant"), Script.InsertPosition.Before, decl); }); + + if (visitor.Matches.Count > 1) { + yield return new CodeAction(string.Format(context.TranslateString("Create local constant (replace '{0}' occurrences)"), visitor.Matches.Count), script => { + string name = CreateMethodDeclarationAction.CreateBaseName(pexpr, resolveResult.Type); + var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); + if (service != null) + name = service.CheckName(context, name, AffectedEntity.LocalConstant); + + var initializer = new VariableInitializer(name, pexpr.Clone()); + var decl = new VariableDeclarationStatement() { + Type = context.CreateShortType(resolveResult.Type), + Modifiers = Modifiers.Const, + Variables = { initializer } + }; + + script.InsertBefore(statement, decl); + + var linkedNodes = new List(); + linkedNodes.Add(initializer.NameToken); + for (int i = 0; i < visitor.Matches.Count; i++) { + var identifierExpression = new IdentifierExpression(name); + linkedNodes.Add(identifierExpression); + script.Replace(visitor.Matches [i], identifierExpression); + } + script.Link(linkedNodes.ToArray ()); + }); + + yield return new CodeAction(string.Format(context.TranslateString("Create constant field (replace '{0}' occurrences)"), visitor.Matches.Count), script => { + string name = CreateMethodDeclarationAction.CreateBaseName(pexpr, resolveResult.Type); + var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); + if (service != null) + name = service.CheckName(context, name, AffectedEntity.ConstantField); + + var initializer = new VariableInitializer(name, pexpr.Clone()); + + var decl = new FieldDeclaration() { + ReturnType = context.CreateShortType(resolveResult.Type), + Modifiers = Modifiers.Const, + Variables = { initializer } + }; + + var linkedNodes = new List(); + linkedNodes.Add(initializer.NameToken); + for (int i = 0; i < visitor.Matches.Count; i++) { + var identifierExpression = new IdentifierExpression(name); + linkedNodes.Add(identifierExpression); + script.Replace(visitor.Matches [i], identifierExpression); + } + script.InsertWithCursor(context.TranslateString("Create constant"), Script.InsertPosition.Before, decl); + }); + } } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs index 54d99b2e35..b0a253b276 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/IntroduceConstantTests.cs @@ -89,5 +89,29 @@ namespace ICSharpCode.NRefactory.CSharp.CodeActions } }", 1); } + + + [Test()] + public void TestLocalConstantReplaceAll () + { + Test (@"class TestClass +{ + public void Hello () + { + System.Console.WriteLine ($""Hello World""); + System.Console.WriteLine (""Hello World""); + System.Console.WriteLine (""Hello World""); + } +}", @"class TestClass +{ + public void Hello () + { + const string helloWorld = ""Hello World""; + System.Console.WriteLine (helloWorld); + System.Console.WriteLine (helloWorld); + System.Console.WriteLine (helloWorld); + } +}", 2); + } } } \ No newline at end of file