/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs

http://github.com/icsharpcode/ILSpy · C# · 129 lines · 93 code · 11 blank · 25 comment · 31 complexity · 44bf76349e4449dea30fd84bcc722967 MD5 · raw file

  1. //
  2. // CreateLocalVariable.cs
  3. //
  4. // Author:
  5. // Mike Krüger <mkrueger@novell.com>
  6. //
  7. // Copyright (c) 2011 Novell, Inc (http://www.novell.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. using System;
  27. using ICSharpCode.NRefactory.PatternMatching;
  28. using System.Linq;
  29. using System.Collections.Generic;
  30. using ICSharpCode.NRefactory.TypeSystem;
  31. namespace ICSharpCode.NRefactory.CSharp.Refactoring
  32. {
  33. public class CreateLocalVariable : IContextAction
  34. {
  35. public List<IdentifierExpression> GetUnresolvedArguments (RefactoringContext context)
  36. {
  37. var expressions = new List<IdentifierExpression> ();
  38. var invocation = GetInvocation (context);
  39. if (invocation != null) {
  40. foreach (var arg in invocation.Arguments) {
  41. IdentifierExpression identifier;
  42. if (arg is DirectionExpression) {
  43. identifier = ((DirectionExpression)arg).Expression as IdentifierExpression;
  44. } else if (arg is NamedArgumentExpression) {
  45. identifier = ((NamedArgumentExpression)arg).Expression as IdentifierExpression;
  46. } else {
  47. identifier = arg as IdentifierExpression;
  48. }
  49. if (identifier == null)
  50. continue;
  51. if (context.Resolve (identifier) == null && GuessType (context, identifier) != null)
  52. expressions.Insert (0, identifier);
  53. }
  54. }
  55. return expressions;
  56. }
  57. public bool IsValid (RefactoringContext context)
  58. {
  59. if (GetUnresolvedArguments (context).Count > 0)
  60. return true;
  61. var identifier = CreateField.GetIdentifier (context);
  62. if (identifier == null)
  63. return false;
  64. if (context.GetNode<Statement> () == null)
  65. return false;
  66. return context.Resolve (identifier) == null && GuessType (context, identifier) != null;
  67. }
  68. public void Run (RefactoringContext context)
  69. {
  70. var stmt = context.GetNode<Statement> ();
  71. var unresolvedArguments = GetUnresolvedArguments (context);
  72. if (unresolvedArguments.Count > 0) {
  73. using (var script = context.StartScript ()) {
  74. foreach (var id in unresolvedArguments) {
  75. script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, id));
  76. }
  77. }
  78. return;
  79. }
  80. using (var script = context.StartScript ()) {
  81. script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, CreateField.GetIdentifier (context)));
  82. }
  83. }
  84. AstNode GenerateLocalVariableDeclaration (RefactoringContext context, IdentifierExpression identifier)
  85. {
  86. return new VariableDeclarationStatement () {
  87. Type = GuessType (context, identifier),
  88. Variables = { new VariableInitializer (identifier.Identifier) }
  89. };
  90. }
  91. InvocationExpression GetInvocation (RefactoringContext context)
  92. {
  93. return context.GetNode<InvocationExpression> ();
  94. }
  95. AstType GuessType (RefactoringContext context, IdentifierExpression identifier)
  96. {
  97. var type = CreateField.GuessType (context, identifier);
  98. if (type != null)
  99. return type;
  100. if (identifier != null && (identifier.Parent is InvocationExpression || identifier.Parent.Parent is InvocationExpression)) {
  101. var invocation = (identifier.Parent as InvocationExpression) ?? (identifier.Parent.Parent as InvocationExpression);
  102. var result = context.Resolve (invocation).Type.GetDelegateInvokeMethod ();
  103. if (result == null)
  104. return null;
  105. int i = 0;
  106. foreach (var arg in invocation.Arguments) {
  107. if (arg.Contains (identifier.StartLocation))
  108. break;
  109. i++;
  110. }
  111. if (result.Parameters.Count < i)
  112. return null;
  113. return context.CreateShortType (result.Parameters[i].Type);
  114. }
  115. return null;
  116. }
  117. }
  118. }