Browse Source

Update to NRefactory commit 'a99a93972cc4e82c969af72568f015019a4d8a96'

pull/59/merge
Daniel Grunwald 13 years ago
parent
commit
cf3995f1a5
  1. 14
      SharpDevelop.Tests.sln
  2. 14
      SharpDevelop.sln
  3. 5
      samples/PortSD4AddInToSD5/PortSD4AddInToSD5.csproj
  4. 11
      samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs
  5. 5
      src/AddIns/Analysis/CodeQuality/CodeQuality.csproj
  6. 4
      src/AddIns/Analysis/UnitTesting/Test/UnitTesting.Tests.csproj
  7. 258
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  8. 5
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  9. 14
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
  10. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  11. 8
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeActionProviderDoozer.cs
  12. 9
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpSyntaxIssue.cs
  13. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs
  14. 24
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  15. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRedundantUsingIssue.cs
  16. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs
  17. 8
      src/AddIns/BackendBindings/CSharpBinding/Tests/CSharpBinding.Tests.csproj
  18. 27
      src/AddIns/BackendBindings/CSharpBinding/Tests/RegistrationTests.cs
  19. 4
      src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj
  20. 5
      src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj
  21. 17
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs
  22. 8
      src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
  23. 5
      src/Libraries/NRefactory/.gitattributes
  24. 136
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/ICSharpCode.NRefactory.CSharp.AstVerifier.csproj
  25. 198
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AbstractAndVirtualConversionAction.cs
  26. 89
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddAnotherAccessorAction.cs
  27. 205
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddArgumentNameAction.cs
  28. 57
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddBracesAction.cs
  29. 60
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddCatchTypeAction.cs
  30. 84
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddExceptionDescriptionAction.cs
  31. 134
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddOptionalParameterToInvocationAction.cs
  32. 156
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddUsingAction.cs
  33. 435
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AutoLinqSumAction.cs
  34. 71
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CS1520MethodMustHaveAReturnTypeAction.cs
  35. 175
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ChangeAccessModifierAction.cs
  36. 94
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CheckIfParameterIsNullAction.cs
  37. 53
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ComputeConstantValueAction.cs
  38. 95
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAnonymousDelegateToLambdaAction.cs
  39. 58
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAsToCastAction.cs
  40. 81
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAssignmentToIfAction.cs
  41. 110
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertBitwiseFlagComparisonToHasFlagsAction.cs
  42. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertCastToAsAction.cs
  43. 52
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertDecToHexAction.cs
  44. 70
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertDoWhileToWhileLoopAction.cs
  45. 88
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertEqualityOperatorToEqualsAction.cs
  46. 83
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertEqualsToEqualityOperatorAction.cs
  47. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs
  48. 56
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertForToWhileAction.cs
  49. 218
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertForeachToForAction.cs
  50. 78
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertHasFlagsToBitwiseFlagComparisonAction.cs
  51. 53
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertHexToDecAction.cs
  52. 89
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToConditionalTernaryExpressionAction.cs
  53. 165
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToNullCoalescingExpressionAction.cs
  54. 115
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToReturnStatementAction.cs
  55. 196
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToSwitchStatementAction.cs
  56. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs
  57. 63
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaBodyExpressionToStatementAction.cs
  58. 74
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaBodyStatementToExpressionAction.cs
  59. 99
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaToAnonymousDelegateAction.cs
  60. 78
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMethodGroupToAnonymousMethodAction.cs
  61. 77
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMethodGroupToLambdaAction.cs
  62. 67
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMultiplyToShiftAction.cs
  63. 54
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertNullCoalescingToConditionalExpressionAction.cs
  64. 78
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertReturnStatementToIfAction.cs
  65. 61
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertShiftToMultiplyAction.cs
  66. 147
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertSwitchToIfAction.cs
  67. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs
  68. 207
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitInitializationsAction.cs
  69. 109
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/ConvertToInitializerAction.cs
  70. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs
  71. 60
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertWhileToDoWhileLoopAction.cs
  72. 69
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CopyCommentsFromBase.cs
  73. 82
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CopyCommentsFromInterface.cs
  74. 80
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateBackingStoreAction.cs
  75. 86
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateChangedEventAction.cs
  76. 330
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateClassDeclarationAction.cs
  77. 64
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateConstructorDeclarationAction.cs
  78. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateCustomEventImplementationAction.cs
  79. 71
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateDelegateAction.cs
  80. 85
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateEnumValue.cs
  81. 144
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateEventInvocatorAction.cs
  82. 98
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateFieldAction.cs
  83. 102
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateIndexerAction.cs
  84. 73
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateLocalVariableAction.cs
  85. 379
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateMethodDeclarationAction.cs
  86. 154
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs
  87. 131
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreatePropertyAction.cs
  88. 188
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/DeclareLocalVariableAction.cs
  89. 69
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtensionMethodInvocationToStaticMethodInvocationAction.cs
  90. 120
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractAnonymousMethodAction.cs
  91. 125
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractFieldAction.cs
  92. 243
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/ExtractMethodAction.cs
  93. 85
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/StaticVisitor.cs
  94. 135
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/VariableLookupVisitor.cs
  95. 0
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/VariableUsageAnalyzation.cs
  96. 68
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractWhileConditionToInternalIfStatementAction.cs
  97. 96
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/FlipEqualsTargetAndArgumentAction.cs
  98. 61
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/FlipOperatorArgumentsAction.cs
  99. 101
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/GenerateGetterAction.cs
  100. 108
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/GeneratePropertyAction.cs
  101. Some files were not shown because too many files have changed in this diff Show More

14
SharpDevelop.Tests.sln

@ -43,6 +43,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Xml" @@ -43,6 +43,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Xml"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Tests", "src\Libraries\NRefactory\ICSharpCode.NRefactory.Tests\ICSharpCode.NRefactory.Tests.csproj", "{63D3B27A-D966-4902-90B3-30290E1692F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Cecil", "src\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj", "{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSharp.Refactoring", "src\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory.CSharp.Refactoring.csproj", "{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvalonDock", "src\Libraries\AvalonDock\AvalonDock\AvalonDock.csproj", "{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "src\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}"
@ -305,6 +309,10 @@ Global @@ -305,6 +309,10 @@ Global
{63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}.Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -633,6 +641,10 @@ Global @@ -633,6 +641,10 @@ Global
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Release|Any CPU.Build.0 = Release|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -655,6 +667,8 @@ Global @@ -655,6 +667,8 @@ Global
{53DCA265-3C3C-42F9-B647-F72BA678122B} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{63D3B27A-D966-4902-90B3-30290E1692F1} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}
{4139CCF6-FB49-4A9D-B2CF-331E9EA3198D} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}

14
SharpDevelop.sln

@ -35,6 +35,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSha @@ -35,6 +35,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSha
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Xml", "src\Libraries\NRefactory\ICSharpCode.NRefactory.Xml\ICSharpCode.NRefactory.Xml.csproj", "{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Cecil", "src\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj", "{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSharp.Refactoring", "src\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory.CSharp.Refactoring.csproj", "{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvalonDock", "src\Libraries\AvalonDock\AvalonDock\AvalonDock.csproj", "{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "src\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}"
@ -243,6 +247,10 @@ Global @@ -243,6 +247,10 @@ Global
{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}.Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -499,6 +507,10 @@ Global @@ -499,6 +507,10 @@ Global
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DF4060F-5EE0-41CF-8096-F27355FD5511}.Release|Any CPU.Build.0 = Release|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Debug|Any CPU.ActiveCfg = net_4_5_Debug|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Debug|Any CPU.Build.0 = net_4_5_Debug|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Release|Any CPU.ActiveCfg = net_4_5_Release|Any CPU
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}.Release|Any CPU.Build.0 = net_4_5_Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -517,6 +529,8 @@ Global @@ -517,6 +529,8 @@ Global
{3B2A5653-EC97-4001-BB9B-D90F1AF2C371} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{53DCA265-3C3C-42F9-B647-F72BA678122B} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{DC393B66-92ED-4CAD-AB25-CFEF23F3D7C6} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{2B8F4F83-C2B3-4E84-A27B-8DEE1BE0E006} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{2A705FC6-1A9E-4941-9E47-254D79F2D9D5} = {E5A0F4D8-37FD-4A30-BEB0-4409DC4E0865}
{2FF700C2-A38A-48BD-A637-8CAFD4FE6237} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}
{4139CCF6-FB49-4A9D-B2CF-331E9EA3198D} = {2A232EF1-EB95-41C6-B63A-C106E0C95D3C}

5
samples/PortSD4AddInToSD5/PortSD4AddInToSD5.csproj

@ -65,6 +65,11 @@ @@ -65,6 +65,11 @@
<Compile Include="WorkbenchSingletonIssueProvider.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory.CSharp.Refactoring.csproj">
<Project>{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}</Project>
<Name>ICSharpCode.NRefactory.CSharp.Refactoring</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\src\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

11
samples/PortSD4AddInToSD5/WorkbenchSingletonIssueProvider.cs

@ -22,11 +22,10 @@ namespace PortSD4AddInToSD5 @@ -22,11 +22,10 @@ namespace PortSD4AddInToSD5
[IssueDescription ("Usage of SD4 WorkbenchSingleton",
Description = "Usage of SD4 WorkbenchSingleton",
Category = "SD4->SD5",
Severity = Severity.Warning,
IssueMarker = IssueMarker.Underline)]
public class WorkbenchSingletonIssueProvider : ICodeIssueProvider
Severity = Severity.Warning)]
public class WorkbenchSingletonIssueProvider : CodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues (BaseRefactoringContext context)
public override IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context, string subIssue = null)
{
foreach (var mre in context.RootNode.Descendants.OfType<MemberReferenceExpression>()) {
var rr = context.Resolve(mre);
@ -129,8 +128,8 @@ namespace PortSD4AddInToSD5 @@ -129,8 +128,8 @@ namespace PortSD4AddInToSD5
if (invocationExpression.Clone().Invoke("FireAndForget").IsMatch(invocationExpression.Parent.Parent)) {
var ident = invocationExpression.Parent.GetChildByRole(Roles.Identifier);
yield return new CodeIssue(
"Use InvokeAsyncAndForget() instead",
ident.StartLocation, ident.EndLocation,
"Use InvokeAsyncAndForget() instead",
new CodeAction("Use InvokeAsyncAndForget() instead",
script => {
var newInvocation = (InvocationExpression)invocationExpression.Clone();
@ -146,7 +145,7 @@ namespace PortSD4AddInToSD5 @@ -146,7 +145,7 @@ namespace PortSD4AddInToSD5
CodeIssue Issue(AstNode node, Action<Script> fix = null)
{
return new CodeIssue("WorkbenchSingleton is obsolete", node.StartLocation, node.EndLocation,
return new CodeIssue(node.StartLocation, node.EndLocation, "WorkbenchSingleton is obsolete",
fix != null ? new CodeAction("Use SD5 API", fix, node) : null);
}
}

5
src/AddIns/Analysis/CodeQuality/CodeQuality.csproj

@ -132,6 +132,11 @@ @@ -132,6 +132,11 @@
<Name>Mono.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

4
src/AddIns/Analysis/UnitTesting/Test/UnitTesting.Tests.csproj

@ -103,6 +103,10 @@ @@ -103,6 +103,10 @@
<Compile Include="Utils\NRefactoryHelper.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

258
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
<Doozer name="CSharpCodeActionProvider" class="CSharpBinding.Refactoring.CSharpCodeActionProviderDoozer"/>
</Import>
<Import assembly = ":ICSharpCode.SharpDevelop"/>
<Import assembly = ":ICSharpCode.NRefactory.CSharp"/>
<Import assembly = ":ICSharpCode.NRefactory.CSharp.Refactoring"/>
</Runtime>
<Path name = "/SharpDevelop/Workbench/Ambiences">
@ -165,103 +165,254 @@ @@ -165,103 +165,254 @@
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders">
<Class class = "CSharpBinding.Refactoring.CSharpSyntaxIssue" />
<Class class = "CSharpBinding.Refactoring.SDRedundantUsingIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AssignmentMadeToSameVariableIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.BitwiseOperationOnNonFlagsEnumIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.BaseMethodCallWithDefaultParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AccessToDisposedClosureIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AccessToModifiedClosureIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AccessToStaticMemberViaDerivedTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AdditionalOfTypeIssues" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ArrayCreationCanBeReplacedWithArrayInitializerIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.AutoAsyncIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.BaseMemberHasParamsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.BaseMethodParameterNameMismatchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.BitwiseOperatorOnEnumWithoutFlagsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CallToObjectEqualsViaBaseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CallToVirtualFunctionFromConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CanBeReplacedWithTryCastAndCheckForNullIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CastExpressionOfIncompatibleTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CompareBooleanWithTrueOrFalseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CompareFloatWithEqualityOperatorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionalToNullCoalescingIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CheckNamespaceIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CompareNonConstrainedGenericWithNullIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CompareOfFloatsByEqualityOperatorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionalTernaryEqualBranchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionIsAlwaysTrueOrFalseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConstantConditionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConstantNullCoalescingConditionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertClosureToMethodGroupIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertConditionalTernaryToNullCoalescingIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfDoToWhileIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToConditionalTernaryExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToNullCoalescingExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToSwitchStatementIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfToAndExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfToOrExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertNullableToShortFormIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertToAutoPropertyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertToConstantIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertToLambdaExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertToStaticTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0029InvalidConversionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0126ReturnMustBeFollowedByAnyExpression" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0127ReturnMustNotBeFollowedByAnyExpression" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DoubleNegationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DuplicateExpressionsInConditionsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DuplicateIfInIfChainIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0152DuplicateCaseLabelValueIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0183ExpressionIsAlwaysOfProvidedTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0659ClassOverrideEqualsWithoutGetHashCode" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS0759RedundantPartialMethodIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1573ParameterHasNoMatchingParamTagIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1717AssignmentMadeToSameVariableIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1729TypeHasNoConstructorWithNArgumentsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DelegateSubtractionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DisposeMethodInNonIDisposableTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DoNotCallOverridableMethodsInConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DontUseLinqWhenItsVerboseAndInefficientIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DoubleNegationOperatorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.DuplicatedLinqToListOrArrayIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyDestructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyEmbeddedStatementIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyGeneralCatchClauseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyNamespaceIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EmptyStatementIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EnumUnderlyingTypeIsIntIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EqualExpressionComparisonIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.EventUnsubscriptionViaAnonymousDelegateIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExceptionRethrowIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExplicitConversionInForEachIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExpressionIsAlwaysOfProvidedTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExpressionIsNeverOfProvidedTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ForControlVariableNotModifiedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.FormatStringIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.IdenticalConditionalBranchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.FieldCanBeMadeReadOnlyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ForCanBeConvertedToForeachIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ForControlVariableIsNeverModifiedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.FormatStringProblemIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ForStatementConditionIsTrueIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.FunctionNeverReturnsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.InconsistentNamingIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.IncorrectCallToObjectGetHashCodeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.IncorrectExceptionParameterOrderingIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvokeAsExtensionMethodIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.LocalVariableHidesMemberIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.LocalVariableNotUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MethodNeverReturnsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.LockThisIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.LongLiteralEndingLowerLIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MemberCanBeMadeStaticIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MemberHidesStaticFromOuterClassIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MethodOverloadHidesOptionalParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MissingStringComparisonIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MethodOverloadWithOptionalParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.MissingInterfaceMemberImplementationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NegativeRelationalExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NoDefaultConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NonPublicMethodWithTestAttributeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NonReadonlyReferencedInGetHashCodeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NotImplementedExceptionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.NotResolvedInTextIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ObjectCreationAsStatementIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.OperatorIsCanBeUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.OptionalParameterCouldBeSkippedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ParameterCanBeDemotedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.OptionalParameterHierarchyMismatchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.OptionalParameterRefOutIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ParameterCanBeDeclaredWithBaseTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ParameterHidesMemberIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ParameterNotUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ParameterOnlyAssignedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PartialMethodParameterNameMismatchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PartialTypeWithSinglePartIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PolymorphicFieldLikeEventInvocationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PossibleAssignmentToReadonlyFieldIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PossibleMistakenCallToGetTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ProhibitedModifiersIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.PublicConstructorInAbstractClassIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantArrayInitializerCommaIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantAnonymousTypePropertyNameIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantArgumentDefaultValueIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantArgumentNameIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantAttributeParenthesesIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantBaseConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantBaseConstructorCallIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantBaseQualifierIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantBlockInDifferentBranchesIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantBoolCompareIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantCaseLabelIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantCatchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantConstructorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantElseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantFieldInitializerIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantCatchClauseIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantCheckBeforeAssignmentIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantCommaInArrayInitializerIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantComparisonWithNullIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantDefaultFieldInitializerIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantDelegateCreationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantEmptyDefaultSwitchBranchIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantEmptyFinallyBlockIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantEnumerableCastCallIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantExplicitArrayCreationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantExplicitArraySizeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantExplicitNullableCreationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantExtendsListEntryIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantIfElseBlockIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantInternalIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantNamespaceUsageIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantNullCheckIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantLambdaParameterTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantLambdaSignatureParenthesesIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantLogicalConditionalExpressionOperandIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantNameQualifierIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantNotNullAttributeInNonNullableTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantObjectCreationArgumentListIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantObjectOrCollectionInitializerIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantOverridenMemberIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantParamsIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantPrivateIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantThisIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantToStringIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantWhereWithPredicateIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReferenceEqualsCalledWithValueTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReferenceToStaticMemberViaDerivedTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantStringToCharArrayCallIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantTernaryExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantThisQualifierIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantToStringCallForValueTypesIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantToStringCallIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantUnsafeContextIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReferenceEqualsWithValueTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRedundantOrStatementIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithFirstOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithLastOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeAnyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeCountIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeFirstIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeFirstOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeLastIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeLastOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeLongCountIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeSingleIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeSingleOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOfTypeWhereIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSimpleAssignmentIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToAnyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToCountIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToFirstIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToFirstOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToLastIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToLastOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToLongCountIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToSingleIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithSingleCallToSingleOrDefaultIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithStringIsNullOrEmptyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ResultOfAsyncCallShouldNotBeIgnoredIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyAnonymousMethodToDelegateIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticConstructorAccessModifierIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.RewriteIfReturnToReturnIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SameGuardConditionExpressionInIfelseBranchesIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SealedMemberInSealedClassIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyConditionalTernaryExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyLinqExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticConstructorParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticFieldInGenericTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringIsNullOrEmptyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ThreadStaticOnInstanceFieldIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.TypeParameterNotUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringCompareIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringCompareToIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringEndsWithIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringIndexOfIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringLastIndexOfIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringStartsWithIsCultureSpecificIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.SuggestUseVarKeywordEvidentIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ThreadStaticAtInstanceFieldIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnassignedReadonlyFieldIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnmatchedSizeSpecificationInArrayCreationIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnreachableCodeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseBlockInsteadColonIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeywordIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ValueParameterUnusedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnusedAnonymousMethodSignatureIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnusedLabelIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnusedParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UnusedTypeParameterIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseArrayCreationExpressionIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseIsOperatorIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodAnyIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseMethodIsInstanceOfTypeIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseOfMemberOfNullReference" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.ValueParameterNotUsedIssue" />
<Class class = "ICSharpCode.NRefactory.CSharp.Refactoring.XmlDocIssue" />
</Path>
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/ContextActions">
<!-- In this path, you can add SD context action providers using <Class>,
or you can add NR5 code action providers using <CSharpCodeActionProvider> -->
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AbstractAndVirtualConversionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddAnotherAccessorAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddArgumentNameAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddBracesAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddCatchTypeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddExceptionDescriptionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddOptionalParameterToInvocationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddUsingAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.AutoLinqSumAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ChangeAccessModifierAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CheckIfParameterIsNullAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ComputeConstantValueAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertAnonymousDelegateToLambdaAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertAssignmentToIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertAsToCastAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertBitwiseFlagComparisonToHasFlagsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertCastToAsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertConditionalToIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertDecToHexAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertDoWhileToWhileLoopAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertEqualityOperatorToEqualsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertEqualsToEqualityOperatorAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertExplicitToImplicitImplementationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertForeachToForAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertForToWhileAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertHasFlagsToBitwiseFlagComparisonAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertHexToDecAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfToConditionalAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfToSwitchAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToConditionalTernaryExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToNullCoalescingExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToReturnStatementAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertIfStatementToSwitchStatementAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertImplicitToExplicitImplementationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertInitializerToExplicitInitializationsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertLambdaBodyExpressionToStatementAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertLambdaBodyStatementToExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertLambdaToAnonymousDelegateAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertMethodGroupToAnonymousMethodAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertMethodGroupToLambdaAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertMultiplyToShiftAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertNullCoalescingToConditionalExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertReturnStatementToIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertShiftToMultiplyAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertSwitchToIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertToInitializerAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertWhileToDoWhileLoopAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CopyCommentsFromBase" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CopyCommentsFromInterface" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateBackingStoreAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateChangedEvent" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateChangedEventAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateClassDeclarationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateConstructorDeclarationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateCustomEventImplementationAction" />
@ -274,11 +425,14 @@ @@ -274,11 +425,14 @@
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateMethodDeclarationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateOverloadWithoutParameterAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreatePropertyAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.CS1520MethodMustHaveAReturnTypeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.DeclareLocalVariableAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtensionMethodInvocationToStaticMethodInvocationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractAnonymousMethodAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractFieldAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod.ExtractMethodAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ExtractWhileConditionToInternalIfStatementAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipEqualsTargetAndArgumentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArgumentsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetterAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.GeneratePropertyAction" />
@ -286,31 +440,43 @@ @@ -286,31 +440,43 @@
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementAbstractMembersAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementInterfaceAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementInterfaceExplicitAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ImplementNotImplementedProperty" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InlineLocalVariableAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InsertAnonymousMethodSignatureAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.IntroduceConstantAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.IntroduceFormatItemAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertConditionalOperatorAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertIfAndSimplify" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertLogicalExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.IterateViaForeachAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.JoinDeclarationAndAssignmentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.JoinStringAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.LinqFluentToQueryAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.LinqQueryToFluentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.MergeNestedIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.MoveToOuterScopeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.NegateIsExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.NegateRelationalExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.PutInsideUsingAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBackingStoreAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBracesAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRedundantCatchTypeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceAssignmentWithPostfixExpressionAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyStringAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceOperatorAssignmentWithAssignmentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplacePostfixExpressionWithAssignmentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceWithOperatorAssignmentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReverseDirectionForForLoopAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyIfFlowAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SimplifyIfInLoopsFlowAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SortUsingsAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitDeclarationAndAssignmentAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitDeclarationListAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitIfAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitStringAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.StaticMethodInvocationToExtensionMethodInvocationAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseAsAndNullCheckAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitTypeAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseStringFormatAction" />
<CSharpCodeActionProvider class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeywordAction" />

5
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -169,6 +169,11 @@ @@ -169,6 +169,11 @@
<Name>ICSharpCode.AvalonEdit</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory.CSharp.Refactoring.csproj">
<Project>{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}</Project>
<Name>ICSharpCode.NRefactory.CSharp.Refactoring</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

14
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs

@ -46,7 +46,7 @@ namespace CSharpBinding.Completion @@ -46,7 +46,7 @@ namespace CSharpBinding.Completion
};
}
ICompletionData ICompletionDataFactory.CreateTypeCompletionData(IType type, bool showFullName, bool isInAttributeContext)
ICompletionData ICompletionDataFactory.CreateTypeCompletionData(IType type, bool showFullName, bool isInAttributeContext, bool addForTypeCreation)
{
var data = new TypeCompletionData(type);
if (showFullName) {
@ -135,7 +135,7 @@ namespace CSharpBinding.Completion @@ -135,7 +135,7 @@ namespace CSharpBinding.Completion
return completionContext.ParseInformation.SyntaxTree.ConditionalSymbols.Select(def => new CompletionData(def));
}
ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName)
ICompletionData ICompletionDataFactory.CreateImportCompletionData(IType type, bool useFullName, bool addForTypeCreation)
{
ITypeDefinition typeDef = type.GetDefinition();
if (typeDef != null)
@ -143,6 +143,16 @@ namespace CSharpBinding.Completion @@ -143,6 +143,16 @@ namespace CSharpBinding.Completion
else
throw new InvalidOperationException("Should never happen");
}
ICompletionData ICompletionDataFactory.CreateFormatItemCompletionData(string format, string description, object example)
{
return new CompletionData("TODO: format item completion");
}
ICompletionData ICompletionDataFactory.CreateXmlDocCompletionData(string tag, string description, string tagInsertionText)
{
return new CompletionData("TODO: XmlDoc completion");
}
#endregion
#region IParameterCompletionDataFactory implementation

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs

@ -186,7 +186,7 @@ namespace CSharpBinding.Parser @@ -186,7 +186,7 @@ namespace CSharpBinding.Parser
typeof(Uri).Assembly,
typeof(Enumerable).Assembly
};
return assemblies.Select(asm => new CecilLoader().LoadAssemblyFile(asm.Location)).ToArray();
return assemblies.Select(asm => SD.AssemblyParserService.GetAssembly(FileName.Create(asm.Location))).ToArray();
});
public ICompilation CreateCompilationForSingleFile(FileName fileName, IUnresolvedFile unresolvedFile)

8
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeActionProviderDoozer.cs

@ -37,8 +37,8 @@ namespace CSharpBinding.Refactoring @@ -37,8 +37,8 @@ namespace CSharpBinding.Refactoring
LoggingService.Error("[ContextAction] attribute is missing on " + providerType.FullName);
return null;
}
if (!typeof(ICodeActionProvider).IsAssignableFrom(providerType)) {
LoggingService.Error(providerType.FullName + " does nto implement ICodeActionProvider");
if (!typeof(CodeActionProvider).IsAssignableFrom(providerType)) {
LoggingService.Error(providerType.FullName + " does not implement CodeActionProvider");
return null;
}
return new CSharpContextActionProviderWrapper((ContextActionAttribute)attributes[0], providerType);
@ -55,13 +55,13 @@ namespace CSharpBinding.Refactoring @@ -55,13 +55,13 @@ namespace CSharpBinding.Refactoring
this.type = type;
}
ICodeActionProvider codeActionProvider;
CodeActionProvider codeActionProvider;
bool CreateCodeActionProvider()
{
lock (this) {
if (codeActionProvider == null) {
codeActionProvider = (ICodeActionProvider)Activator.CreateInstance(type);
codeActionProvider = (CodeActionProvider)Activator.CreateInstance(type);
}
return true;
}

9
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpSyntaxIssue.cs

@ -16,11 +16,10 @@ namespace CSharpBinding.Refactoring @@ -16,11 +16,10 @@ namespace CSharpBinding.Refactoring
[IssueDescription("C# syntax error",
Description = "Displays syntax errors",
Category = IssueCategories.CompilerErrors,
Severity = Severity.Error,
IssueMarker = IssueMarker.Underline)]
public class CSharpSyntaxIssue : ICodeIssueProvider
Severity = Severity.Error)]
public class CSharpSyntaxIssue : CodeIssueProvider
{
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
public override IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context, string subIssue = null)
{
var refactoringContext = context as SDRefactoringContext;
if (refactoringContext == null)
@ -50,7 +49,7 @@ namespace CSharpBinding.Refactoring @@ -50,7 +49,7 @@ namespace CSharpBinding.Refactoring
}
TextLocation end = document.GetLocation(offset + length);
return new CodeIssue(error.Message, begin, end);
return new CodeIssue(begin, end, error.Message);
}
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/EditorScript.cs

@ -81,6 +81,7 @@ namespace CSharpBinding.Refactoring @@ -81,6 +81,7 @@ namespace CSharpBinding.Refactoring
return completedTask;
}
/*
public override Task InsertWithCursor(string operation, InsertPosition defaultPosition, IEnumerable<AstNode> nodes)
{
AstNode contextNode = context.GetNode();
@ -107,6 +108,7 @@ namespace CSharpBinding.Refactoring @@ -107,6 +108,7 @@ namespace CSharpBinding.Refactoring
}
return completedTask;
}
*/
public override void Dispose()
{

24
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -28,7 +28,7 @@ namespace CSharpBinding.Refactoring @@ -28,7 +28,7 @@ namespace CSharpBinding.Refactoring
public class IssueManager : IDisposable, IContextActionProvider
{
static readonly Lazy<IReadOnlyList<IssueProvider>> issueProviders = new Lazy<IReadOnlyList<IssueProvider>>(
() => AddInTree.BuildItems<ICodeIssueProvider>("/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders", null, false)
() => AddInTree.BuildItems<CodeIssueProvider>("/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders", null, false)
.Select(p => new IssueProvider(p)).ToList());
internal static IReadOnlyList<IssueProvider> IssueProviders {
@ -40,7 +40,7 @@ namespace CSharpBinding.Refactoring @@ -40,7 +40,7 @@ namespace CSharpBinding.Refactoring
public readonly Type ProviderType;
public readonly IssueDescriptionAttribute Attribute;
public IssueProvider(ICodeIssueProvider provider)
public IssueProvider(CodeIssueProvider provider)
{
if (provider == null)
throw new ArgumentNullException("provider");
@ -51,7 +51,7 @@ namespace CSharpBinding.Refactoring @@ -51,7 +51,7 @@ namespace CSharpBinding.Refactoring
if (attributes.Length == 1) {
this.Attribute = (IssueDescriptionAttribute)attributes[0];
defaultSeverity = this.Attribute.Severity;
IsRedundancy = this.Attribute.Category == IssueCategories.Redundancies;
IsRedundancy = this.Attribute.Category == IssueCategories.RedundanciesInCode || this.Attribute.Category == IssueCategories.RedundanciesInDeclarations;
} else {
SD.Log.Warn("Issue provider without attribute: " + ProviderType);
}
@ -62,15 +62,11 @@ namespace CSharpBinding.Refactoring @@ -62,15 +62,11 @@ namespace CSharpBinding.Refactoring
public Severity CurrentSeverity { get; set; }
public bool IsRedundancy { get; set; }
public IssueMarker MarkerType {
get { return Attribute != null ? Attribute.IssueMarker : IssueMarker.Underline; }
}
public IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context)
{
// use a separate instance for every call, this is necessary
// for thread-safety
var provider = (ICodeIssueProvider)Activator.CreateInstance(ProviderType);
var provider = (CodeIssueProvider)Activator.CreateInstance(ProviderType);
return provider.GetIssues(context);
}
}
@ -119,8 +115,9 @@ namespace CSharpBinding.Refactoring @@ -119,8 +115,9 @@ namespace CSharpBinding.Refactoring
public readonly int EndOffset;
public readonly IReadOnlyList<IContextAction> Actions;
public readonly Severity Severity;
public readonly IssueMarker MarkerType;
public InspectionTag(IssueManager manager, IssueProvider provider, ITextSourceVersion inspectedVersion, string description, int startOffset, int endOffset, IEnumerable<CodeAction> actions)
public InspectionTag(IssueManager manager, IssueProvider provider, ITextSourceVersion inspectedVersion, string description, int startOffset, int endOffset, IssueMarker markerType, IEnumerable<CodeAction> actions)
{
this.manager = manager;
this.Provider = provider;
@ -129,6 +126,7 @@ namespace CSharpBinding.Refactoring @@ -129,6 +126,7 @@ namespace CSharpBinding.Refactoring
this.StartOffset = startOffset;
this.EndOffset = endOffset;
this.Severity = provider.CurrentSeverity;
this.MarkerType = markerType;
this.Actions = actions.Select(Wrap).ToList();
}
@ -175,10 +173,13 @@ namespace CSharpBinding.Refactoring @@ -175,10 +173,13 @@ namespace CSharpBinding.Refactoring
marker.MarkerColor = color;
if (!Provider.IsRedundancy)
marker.MarkerTypes = TextMarkerTypes.ScrollBarRightTriangle;
switch (Provider.MarkerType) {
case IssueMarker.Underline:
switch (MarkerType) {
case IssueMarker.WavedLine:
marker.MarkerTypes |= TextMarkerTypes.SquigglyUnderline;
break;
case IssueMarker.DottedLine:
marker.MarkerTypes |= TextMarkerTypes.DottedUnderline;
break;
case IssueMarker.GrayOut:
marker.ForegroundColor = SystemColors.GrayTextColor;
break;
@ -272,6 +273,7 @@ namespace CSharpBinding.Refactoring @@ -272,6 +273,7 @@ namespace CSharpBinding.Refactoring
issue.Description,
context.GetOffset(issue.Start),
context.GetOffset(issue.End),
issue.IssueMarker,
issue.Actions));
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRedundantUsingIssue.cs

@ -6,7 +6,7 @@ using ICSharpCode.NRefactory.CSharp.Refactoring; @@ -6,7 +6,7 @@ using ICSharpCode.NRefactory.CSharp.Refactoring;
namespace CSharpBinding.Refactoring
{
public class SDRedundantUsingIssue : RedundantUsingIssue
public class SDRedundantUsingIssue : RedundantUsingDirectiveIssue
{
public SDRedundantUsingIssue()
{

6
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs

@ -146,6 +146,12 @@ namespace CSharpBinding.Refactoring @@ -146,6 +146,12 @@ namespace CSharpBinding.Refactoring
}
}
public override string DefaultNamespace {
get {
return string.Empty; // TODO: get namespace from current project
}
}
public override string GetText(int offset, int length)
{
return textSource.GetText(offset, length);

8
src/AddIns/BackendBindings/CSharpBinding/Tests/CSharpBinding.Tests.csproj

@ -81,6 +81,14 @@ @@ -81,6 +81,14 @@
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory.CSharp.Refactoring.csproj">
<Project>{2A705FC6-1A9E-4941-9E47-254D79F2D9D5}</Project>
<Name>ICSharpCode.NRefactory.CSharp.Refactoring</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

27
src/AddIns/BackendBindings/CSharpBinding/Tests/RegistrationTests.cs

@ -21,12 +21,13 @@ namespace CSharpBinding.Tests @@ -21,12 +21,13 @@ namespace CSharpBinding.Tests
public class RegistrationTests
{
Type[] exceptions = {
typeof(MultipleEnumerationIssue), // disabled due to https://github.com/icsharpcode/NRefactory/issues/123
typeof(PossibleMultipleEnumerationIssue), // disabled due to https://github.com/icsharpcode/NRefactory/issues/123
typeof(RedundantAssignmentIssue), // disabled due to https://github.com/icsharpcode/NRefactory/issues/123
typeof(RedundantTypeCastIssue), // disabled due to plenty of false positives (e.g. when cast is necessary for overload resolution)
typeof(RedundantCastIssue), // disabled due to plenty of false positives (e.g. when cast is necessary for overload resolution)
};
Assembly NRCSharp = typeof(ICodeIssueProvider).Assembly;
Assembly NRCSharp = typeof(CodeIssueProvider).Assembly;
Assembly NRCSharpRefactoring = typeof(AddBracesAction).Assembly;
Assembly CSharpBinding = typeof(SDRefactoringContext).Assembly;
AddIn addIn;
@ -37,7 +38,7 @@ namespace CSharpBinding.Tests @@ -37,7 +38,7 @@ namespace CSharpBinding.Tests
Type FindType(string @class)
{
return CSharpBinding.GetType(@class, false) ?? NRCSharp.GetType(@class, true);
return CSharpBinding.GetType(@class, false) ?? NRCSharpRefactoring.GetType(@class, false);
}
[TestFixtureSetUpAttribute]
@ -47,12 +48,22 @@ namespace CSharpBinding.Tests @@ -47,12 +48,22 @@ namespace CSharpBinding.Tests
addIn = AddIn.Load(addInTree, "CSharpBinding.addin");
registeredIssueProviders = addIn.Paths["/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders"].Codons
.Select(c => FindType(c.Properties["class"])).ToList();
NRissueProviders = NRCSharp.ExportedTypes.Where(t => t.GetCustomAttribute<IssueDescriptionAttribute>() != null).ToList();
.Select(c => FindType(c.Properties["class"])).Where(t => t != null).ToList();
NRissueProviders = NRCSharpRefactoring.ExportedTypes.Where(t => t.GetCustomAttribute<IssueDescriptionAttribute>() != null).ToList();
registeredContextActions = addIn.Paths["/SharpDevelop/ViewContent/TextEditor/C#/ContextActions"].Codons
.Select(c => FindType(c.Properties["class"])).ToList();
NRcontextActions = NRCSharp.ExportedTypes.Where(t => t.GetCustomAttribute<ContextActionAttribute>() != null).ToList();
.Select(c => FindType(c.Properties["class"])).Where(t => t != null).ToList();
NRcontextActions = NRCSharpRefactoring.ExportedTypes.Where(t => t.GetCustomAttribute<ContextActionAttribute>() != null).ToList();
}
[Test]
public void NoMissingClasses()
{
var classNames = addIn.Paths["/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders"].Codons
.Concat(addIn.Paths["/SharpDevelop/ViewContent/TextEditor/C#/ContextActions"].Codons)
.Select(c => c.Properties["class"]);
Assert.IsEmpty(classNames.Where(c => FindType(c) == null));
}
[Test]

4
src/AddIns/BackendBindings/XamlBinding/XamlBinding.Tests/XamlBinding.Tests.csproj

@ -93,6 +93,10 @@ @@ -93,6 +93,10 @@
<Project>{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}</Project>
<Name>ICSharpCode.AvalonEdit</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>

5
src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj

@ -131,6 +131,11 @@ @@ -131,6 +131,11 @@
<Name>Mono.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory.Cecil\ICSharpCode.NRefactory.Cecil.csproj">
<Project>{B2BBC7BC-837C-40ED-A6DB-D5AE8626212F}</Project>
<Name>ICSharpCode.NRefactory.Cecil</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\..\Libraries\NRefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>

17
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/TextMarkerService.cs

@ -168,13 +168,14 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -168,13 +168,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
drawingContext.DrawGeometry(brush, null, geometry);
}
}
if ((marker.MarkerTypes & (TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline)) != 0) {
var underlineMarkerTypes = TextMarkerTypes.SquigglyUnderline | TextMarkerTypes.NormalUnderline | TextMarkerTypes.DottedUnderline;
if ((marker.MarkerTypes & underlineMarkerTypes) != 0) {
foreach (Rect r in BackgroundGeometryBuilder.GetRectsForSegment(textView, marker)) {
Point startPoint = r.BottomLeft;
Point endPoint = r.BottomRight;
Pen usedPen = new Pen(new SolidColorBrush(marker.MarkerColor), 1);
usedPen.Freeze();
Brush usedBrush = new SolidColorBrush(marker.MarkerColor);
usedBrush.Freeze();
if ((marker.MarkerTypes & TextMarkerTypes.SquigglyUnderline) != 0) {
double offset = 2.5;
@ -189,9 +190,19 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -189,9 +190,19 @@ namespace ICSharpCode.AvalonEdit.AddIn
geometry.Freeze();
Pen usedPen = new Pen(usedBrush, 1);
usedPen.Freeze();
drawingContext.DrawGeometry(Brushes.Transparent, usedPen, geometry);
}
if ((marker.MarkerTypes & TextMarkerTypes.NormalUnderline) != 0) {
Pen usedPen = new Pen(usedBrush, 1);
usedPen.Freeze();
drawingContext.DrawLine(usedPen, startPoint, endPoint);
}
if ((marker.MarkerTypes & TextMarkerTypes.DottedUnderline) != 0) {
Pen usedPen = new Pen(usedBrush, 1);
usedPen.DashStyle = DashStyles.Dot;
usedPen.Freeze();
drawingContext.DrawLine(usedPen, startPoint, endPoint);
}
}

8
src/Libraries/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs

@ -115,8 +115,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -115,8 +115,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
{
string oldNamespace = currentNamespace;
foreach (Identifier ident in namespaceDeclaration.Identifiers) {
currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name);
foreach (string ident in namespaceDeclaration.Identifiers) {
currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
transform.declaredNamespaces.Add(currentNamespace);
}
base.VisitNamespaceDeclaration(namespaceDeclaration, data);
@ -154,8 +154,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -154,8 +154,8 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
{
string oldNamespace = currentNamespace;
foreach (Identifier ident in namespaceDeclaration.Identifiers) {
currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name);
foreach (string ident in namespaceDeclaration.Identifiers) {
currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
}
base.VisitNamespaceDeclaration(namespaceDeclaration, data);
currentNamespace = oldNamespace;

5
src/Libraries/NRefactory/.gitattributes vendored

@ -1,2 +1,3 @@ @@ -1,2 +1,3 @@
*.sln -crlf
*.csproj -crlf
*.cs text diff=csharp
*.sln text eol=crlf
*.csproj text eol=crlf

136
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.AstVerifier/ICSharpCode.NRefactory.CSharp.AstVerifier.csproj

@ -1,69 +1,69 @@ @@ -1,69 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{961DADFA-7CE6-429F-BC22-47630D6DB826}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ICSharpCode.NRefactory.CSharp.AstVerifier</RootNamespace>
<AssemblyName>AstVerifier</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\net_4_5_Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\net_4_5_Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{961DADFA-7CE6-429F-BC22-47630D6DB826}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>ICSharpCode.NRefactory.CSharp.AstVerifier</RootNamespace>
<AssemblyName>AstVerifier</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\net_4_5_Debug\</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'net_4_5_Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\net_4_5_Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj">
<Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project>
<Name>ICSharpCode.NRefactory.CSharp</Name>
</ProjectReference>
<ProjectReference Include="..\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj">
<Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project>
<Name>ICSharpCode.NRefactory</Name>
</ProjectReference>
</ItemGroup>
</Project>

198
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AbstractAndVirtualConversionAction.cs

@ -0,0 +1,198 @@ @@ -0,0 +1,198 @@
//
// AbstractAndVirtualConversionAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Make abstract member virtual", Description = "Implements an abstract member as a virtual one")]
public class AbstractAndVirtualConversionAction : CodeActionProvider
{
static BlockStatement CreateNotImplementedBody(RefactoringContext context, out ThrowStatement throwStatement)
{
throwStatement = new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")));
return new BlockStatement { throwStatement };
}
static ThrowStatement ImplementStub (RefactoringContext context, EntityDeclaration newNode)
{
ThrowStatement throwStatement = null;
if (newNode is PropertyDeclaration || newNode is IndexerDeclaration) {
var setter = newNode.GetChildByRole(PropertyDeclaration.SetterRole);
if (!setter.IsNull)
setter.AddChild(CreateNotImplementedBody(context, out throwStatement), Roles.Body);
var getter = newNode.GetChildByRole(PropertyDeclaration.GetterRole);
if (!getter.IsNull)
getter.AddChild(CreateNotImplementedBody(context, out throwStatement), Roles.Body);
} else {
newNode.AddChild(CreateNotImplementedBody(context, out throwStatement), Roles.Body);
}
return throwStatement;
}
static bool CheckBody(EntityDeclaration node)
{
var custom = node as CustomEventDeclaration;
if (custom != null && !(IsValidBody (custom.AddAccessor.Body) || IsValidBody (custom.RemoveAccessor.Body)))
return false;
if (node is PropertyDeclaration || node is IndexerDeclaration) {
var setter = node.GetChildByRole(PropertyDeclaration.SetterRole);
var getter = node.GetChildByRole(PropertyDeclaration.GetterRole);
return IsValidBody(setter.Body) && IsValidBody(getter.Body);
}
return IsValidBody(node.GetChildByRole(Roles.Body));
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<EntityDeclaration>();
if (node == null || node.HasModifier(Modifiers.Override))
yield break;
var parent = node.Parent as TypeDeclaration;
if (parent == null)
yield break;
var custom = node as CustomEventDeclaration;
if (custom != null) {
if (!custom.PrivateImplementationType.IsNull)
yield break;
}
var selectedNode = node.GetNodeAt(context.Location);
if (selectedNode == null)
yield break;
if (selectedNode != node.NameToken) {
if ((node is EventDeclaration && node is CustomEventDeclaration || selectedNode.Role != Roles.Identifier) &&
selectedNode.Role != IndexerDeclaration.ThisKeywordRole) {
var modToken = selectedNode as CSharpModifierToken;
if (modToken == null || (modToken.Modifier & (Modifiers.Abstract | Modifiers.Virtual)) == 0)
yield break;
} else {
if (!(node is EventDeclaration || node is CustomEventDeclaration) && selectedNode.Parent != node)
yield break;
}
}
if (!node.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole).IsNull)
yield break;
if (parent.HasModifier(Modifiers.Abstract)) {
if ((node.Modifiers & Modifiers.Abstract) != 0) {
yield return new CodeAction(context.TranslateString("To non-abstract"), script => {
var newNode = (EntityDeclaration)node.Clone();
newNode.Modifiers &= ~Modifiers.Abstract;
var throwStmt = ImplementStub (context, newNode);
script.Replace(node, newNode);
if (throwStmt != null)
script.Select(throwStmt);
}, selectedNode);
} else {
if (CheckBody(node)) {
yield return new CodeAction(context.TranslateString("To abstract"), script => {
var newNode = CloneNodeWithoutBodies(node);
newNode.Modifiers &= ~Modifiers.Virtual;
newNode.Modifiers &= ~Modifiers.Static;
newNode.Modifiers |= Modifiers.Abstract;
script.Replace(node, newNode);
}, selectedNode);
}
}
}
if ((node.Modifiers & Modifiers.Virtual) != 0) {
yield return new CodeAction(context.TranslateString("To non-virtual"), script => {
script.ChangeModifier(node, node.Modifiers & ~Modifiers.Virtual);
}, selectedNode);
} else {
if ((node.Modifiers & Modifiers.Abstract) != 0) {
yield return new CodeAction(context.TranslateString("To virtual"), script => {
var newNode = CloneNodeWithoutBodies(node);
newNode.Modifiers &= ~Modifiers.Abstract;
newNode.Modifiers &= ~Modifiers.Static;
newNode.Modifiers |= Modifiers.Virtual;
var throwStmt = ImplementStub (context, newNode);
script.Replace(node, newNode);
if (throwStmt != null)
script.Select(throwStmt);
}, selectedNode);
} else {
yield return new CodeAction(context.TranslateString("To virtual"), script => {
script.ChangeModifier(node, (node.Modifiers & ~Modifiers.Static) | Modifiers.Virtual);
}, selectedNode);
}
}
}
static EntityDeclaration CloneNodeWithoutBodies(EntityDeclaration node)
{
EntityDeclaration newNode;
var custom = node as CustomEventDeclaration;
if (custom == null) {
newNode = (EntityDeclaration)node.Clone();
if (newNode is PropertyDeclaration || node is IndexerDeclaration) {
var getter = newNode.GetChildByRole(PropertyDeclaration.GetterRole);
if (!getter.IsNull)
getter.Body.Remove();
var setter = newNode.GetChildByRole(PropertyDeclaration.SetterRole);
if (!setter.IsNull)
setter.Body.Remove();
} else {
newNode.GetChildByRole(Roles.Body).Remove();
}
} else {
newNode = new EventDeclaration {
Modifiers = custom.Modifiers,
ReturnType = custom.ReturnType.Clone(),
Variables = {
new VariableInitializer {
Name = custom.Name
}
}
};
}
return newNode;
}
static bool IsValidBody(BlockStatement body)
{
if (body.IsNull)
return true;
var first = body.Statements.FirstOrDefault();
if (first == null)
return true;
if (first.GetNextSibling(s => s.Role == BlockStatement.StatementRole) != null)
return false;
return first is EmptyStatement || first is ThrowStatement;
}
}
}

89
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddAnotherAccessorAction.cs

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
//
// AddAnotherAccessor.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Add another accessor to a property declaration that has only one.
/// </summary>
[ContextAction("Add another accessor", Description = "Adds second accessor to a property.")]
public class AddAnotherAccessorAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var pdecl = context.GetNode<PropertyDeclaration> ();
if (pdecl == null || !pdecl.Getter.IsNull && !pdecl.Setter.IsNull || !pdecl.NameToken.Contains(context.Location)) {
yield break;
}
var type = pdecl.Parent as TypeDeclaration;
if (type != null && type.ClassType == ClassType.Interface) {
yield break;
}
yield return new CodeAction (pdecl.Setter.IsNull ? context.TranslateString("Add setter") : context.TranslateString("Add getter"), script => {
Statement accessorStatement = null;
var accessor = new Accessor ();
if (!pdecl.Getter.IsNull && !pdecl.Getter.Body.IsNull || !pdecl.Setter.IsNull && !pdecl.Setter.Body.IsNull) {
accessorStatement = BuildAccessorStatement(context, pdecl);
accessor.Body = new BlockStatement { accessorStatement };
}
accessor.Role = pdecl.Setter.IsNull ? PropertyDeclaration.SetterRole : PropertyDeclaration.GetterRole;
if (pdecl.Setter.IsNull && !pdecl.Getter.IsNull) {
script.InsertAfter(pdecl.Getter, accessor);
} else if (pdecl.Getter.IsNull && !pdecl.Setter.IsNull) {
script.InsertBefore(pdecl.Setter, accessor);
} else {
script.InsertBefore(pdecl.Getter, accessor);
}
script.FormatText(pdecl);
if (accessorStatement != null)
script.Select(accessorStatement);
}, pdecl.NameToken);
}
static Statement BuildAccessorStatement (RefactoringContext context, PropertyDeclaration pdecl)
{
if (pdecl.Setter.IsNull && !pdecl.Getter.IsNull) {
var field = RemoveBackingStoreAction.ScanGetter (context, pdecl);
if (field != null && !field.IsReadOnly && !field.IsConst)
return new AssignmentExpression (new IdentifierExpression (field.Name), AssignmentOperatorType.Assign, new IdentifierExpression ("value"));
}
if (!pdecl.Setter.IsNull && pdecl.Getter.IsNull) {
var field = RemoveBackingStoreAction.ScanSetter (context, pdecl);
if (field != null)
return new ReturnStatement (new IdentifierExpression (field.Name));
}
return new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "NotImplementedException")));
}
}
}

205
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddArgumentNameAction.cs

@ -0,0 +1,205 @@ @@ -0,0 +1,205 @@
//
// AddArgumentNameAction.cs
//
// Author:
// Ji Kun <jikun.nus@gmail.com>
//
// Copyright (c) 2013 Ji Kun <jikun.nus@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.Refactoring;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Add name for argument
/// </summary>
using System;
using System.Collections.Generic;
[ContextAction("Add name for argument", Description = "Add name for argument including method, indexer invocation and Attibute Usage")]
public class AddArgumentNameAction : SpecializedCodeAction<Expression>
{
List<Expression> CollectNodes(AstNode parant, AstNode node)
{
List<Expression> returned = new List<Expression>();
var children = parant.GetChildrenByRole(Roles.Argument);
for (int i = 0; i< children.Count(); i++) {
if (children.ElementAt(i).Equals(node)) {
for (int j = i; j< children.Count(); j++) {
if (children.ElementAt(j) is Expression && children.ElementAt(j).Role == Roles.Argument && !(children.ElementAt(j) is NamedArgumentExpression)) {
returned.Add(children.ElementAt(j));
} else {
break;
}
}
}
}
return returned;
}
protected override CodeAction GetAction(RefactoringContext context, Expression expression)
{
if (expression == null)
return null;
if (expression.Role != Roles.Argument || expression is NamedArgumentExpression)
return null;
if (context.Location != expression.StartLocation)
return null;
var parent = expression.Parent;
if (!(parent is CSharp.Attribute) && !(parent is IndexerExpression) && !(parent is InvocationExpression))
return null;
if (parent is CSharp.Attribute) {
var resolvedResult = context.Resolve(parent as CSharp.Attribute);
if (resolvedResult.IsError)
return null;
var arguments = (parent as CSharp.Attribute).Arguments;
IMember member = (resolvedResult as CSharpInvocationResolveResult).Member;
int index = 0;
int temp = 0;
List<Expression> nodes = new List<Expression>();
foreach (var argument in arguments) {
if (argument.Equals(expression)) {
nodes = CollectNodes(parent, expression);
break;
}
temp++;
}
index = temp;
if (!nodes.Any())
return null;
var method = member as IMethod;
if (method == null || method.Parameters.Count == 0 || method.Parameters.Last().IsParams)
return null;
var parameterMap = (resolvedResult as CSharpInvocationResolveResult).GetArgumentToParameterMap();
var parameters = method.Parameters;
if (index >= parameterMap.Count)
return null;
var name = parameters.ElementAt(parameterMap [index]).Name;
return new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
for (int i = 0; i < nodes.Count; i++) {
int p = index + i;
if (p >= parameterMap.Count)
break;
name = parameters.ElementAt(parameterMap [p]).Name;
var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
script.Replace(arguments.ElementAt(p), namedArgument);
}},
expression
);
}
if (parent is IndexerExpression) {
var resolvedResult = context.Resolve(parent as IndexerExpression);
if (resolvedResult.IsError)
return null;
var arguments = (parent as IndexerExpression).Arguments;
IMember member = (resolvedResult as CSharpInvocationResolveResult).Member;
int index = 0;
int temp = 0;
List<Expression> nodes = new List<Expression>();
foreach (var argument in arguments) {
if (argument.Equals(expression)) {
nodes = CollectNodes(parent, expression);
break;
}
temp++;
}
index = temp;
if (!nodes.Any())
return null;
var property = member as IProperty;
if (property == null || property.Parameters.Count == 0 || property.Parameters.Last().IsParams) {
return null;
}
var parameterMap = (resolvedResult as CSharpInvocationResolveResult).GetArgumentToParameterMap();
var parameters = property.Parameters;
if (index >= parameterMap.Count)
return null;
var name = parameters.ElementAt(parameterMap [index]).Name;
return new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
for (int i = 0; i< nodes.Count; i++) {
int p = index + i;
if (p >= parameterMap.Count)
break;
name = parameters.ElementAt(parameterMap [p]).Name;
var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
script.Replace(arguments.ElementAt(p), namedArgument);
}},
expression
);
}
if (parent is InvocationExpression) {
var resolvedResult = context.Resolve(parent as InvocationExpression);
if (resolvedResult.IsError)
return null;
var arguments = (parent as InvocationExpression).Arguments;
IMember member = (resolvedResult as CSharpInvocationResolveResult).Member;
int index = 0;
int temp = 0;
List<Expression> nodes = new List<Expression>();
foreach (var argument in arguments) {
if (argument.Equals(expression)) {
nodes = CollectNodes(parent, expression);
break;
}
temp++;
}
index = temp;
if (!nodes.Any())
return null;
var method = member as IMethod;
if (method == null || method.Parameters.Count == 0 || method.Parameters.Last().IsParams)
return null;
var parameterMap = (resolvedResult as CSharpInvocationResolveResult).GetArgumentToParameterMap();
var parameters = method.Parameters;
if (index >= parameterMap.Count)
return null;
var name = parameters.ElementAt(parameterMap [index]).Name;
return new CodeAction(string.Format(context.TranslateString("Add argument name '{0}'"), name), script => {
for (int i = 0; i< nodes.Count; i++) {
int p = index + i;
if (p >= parameterMap.Count)
break;
name = parameters.ElementAt(parameterMap [p]).Name;
var namedArgument = new NamedArgumentExpression(name, arguments.ElementAt(p).Clone());
script.Replace(arguments.ElementAt(p), namedArgument);
}},
expression
);
}
return null;
}
}
}

57
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddBracesAction.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
//
// AddBracesAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Add braces", Description = "Removes redundant braces around a statement.")]
public class AddBracesAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
string keyword;
Statement embeddedStatement;
// BlockStatement block;
var curNode = context.GetNode();
if (!RemoveBracesAction.IsSpecialNode(curNode, out keyword, out embeddedStatement))
yield break;
if (embeddedStatement is BlockStatement)
yield break;
yield return new CodeAction (
string.Format(context.TranslateString("Add braces to '{0}'"), keyword),
script => {
script.Replace(embeddedStatement, new BlockStatement { embeddedStatement.Clone() });
},
curNode
);
}
}
}

60
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddCatchTypeAction.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
//
// AddCatchTypeAction.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Add type to general catch clause",
Description = "Adds an exception type specifier to general catch clauses.")]
public class AddCatchTypeAction : CodeActionProvider
{
#region ICodeActionProvider implementation
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var catchClause = context.GetNode<CatchClause>();
if (catchClause == null)
yield break;
if (!catchClause.Type.IsNull)
yield break;
yield return new CodeAction(context.TranslateString("Add type specifier"), script => {
var newType = context.CreateShortType("System", "Exception");
var namingHelper = new NamingHelper(context);
var newIdentifier = Identifier.Create(namingHelper.GenerateVariableName(newType, "e"));
script.Replace(catchClause, new CatchClause {
Type = newType,
VariableNameToken = newIdentifier,
Body = catchClause.Body.Clone() as BlockStatement
});
script.Select(newType);
}, catchClause);
}
#endregion
}
}

84
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddExceptionDescriptionAction.cs

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
//
// AddExceptionDescriptionAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.NRefactory.Documentation;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Add an exception description to the xml documentation",
Description = "Add an exception description to the xml documentation")]
public class AddExceptionDescriptionAction : SpecializedCodeAction<ThrowStatement>
{
static AstNode SearchInsertionNode (AstNode entity)
{
AstNode result = entity;
while (result != null && (result.Role == Roles.Comment || result.Role == Roles.NewLine || result.Role == Roles.Whitespace))
result = result.NextSibling;
return result;
}
protected override CodeAction GetAction (RefactoringContext context, ThrowStatement node)
{
var entity = node.GetParent<EntityDeclaration> ();
if (entity == null)
return null;
var rr = context.Resolve (entity) as MemberResolveResult;
if (rr == null || rr.IsError)
return null;
var expr = context.Resolve (node.Expression);
if (expr == null || expr.IsError || expr.Type.GetDefinition () == null)
return null;
var docElement = XmlDocumentationElement.Get (rr.Member);
if (docElement == null || docElement.Children.Count == 0)
return null;
foreach (var de in docElement.Children) {
if (de.Name == "exception") {
if (de.ReferencedEntity == expr.Type)
return null;
}
}
return new CodeAction (
context.TranslateString ("Add exception to xml documentation"),
script => {
var startText = string.Format (" <exception cref=\"{0}\">", expr.Type.GetDefinition ().GetIdString ());
var comment = new Comment (startText +"</exception>", CommentType.Documentation);
script.InsertBefore (
SearchInsertionNode (entity.FirstChild) ?? entity,
comment
);
script.Select (script.GetSegment (comment).Offset + ("///" + startText).Length, 0);
},
node
);
}
}
}

134
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddOptionalParameterToInvocationAction.cs

@ -0,0 +1,134 @@ @@ -0,0 +1,134 @@
//
// AddOptionalParameterToInvocationAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.Xml;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Add one or more optional parameters to an invocation, using their default values",
Description = "Add one or more optional parameters to an invocation.")]
public class AddOptionalParameterToInvocationAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var invocationExpression = context.GetNode<InvocationExpression>();
if (invocationExpression == null)
yield break;
var resolveResult = context.Resolve(invocationExpression) as InvocationResolveResult;
if (resolveResult == null) {
yield break;
}
var method = (IMethod)resolveResult.Member;
bool foundOptionalParameter = false;
foreach (var parameter in method.Parameters) {
if (parameter.IsParams) {
yield break;
}
if (parameter.IsOptional) {
foundOptionalParameter = true;
break;
}
}
if (!foundOptionalParameter) {
yield break;
}
//Basic sanity checks done, now see if there are any missing optional arguments
var missingParameters = new List<IParameter>(method.Parameters);
if (resolveResult.Arguments.Count != invocationExpression.Arguments.Count) {
//Extension method
missingParameters.RemoveAt (0);
}
foreach (var argument in invocationExpression.Arguments) {
var namedArgument = argument as NamedArgumentExpression;
if (namedArgument == null) {
missingParameters.RemoveAt(0);
} else {
missingParameters.RemoveAll(parameter => parameter.Name == namedArgument.Name);
}
}
foreach (var parameterToAdd in missingParameters) {
//Add specific parameter
yield return new CodeAction(string.Format(context.TranslateString("Add optional parameter \"{0}\""),
parameterToAdd.Name),
script => {
var newInvocation = (InvocationExpression)invocationExpression.Clone();
AddArgument(newInvocation, parameterToAdd, parameterToAdd == missingParameters.First());
script.Replace(invocationExpression, newInvocation);
}, invocationExpression);
}
if (missingParameters.Count > 1) {
//Add all parameters at once
yield return new CodeAction(context.TranslateString("Add all optional parameters"),
script => {
var newInvocation = (InvocationExpression)invocationExpression.Clone();
foreach (var parameterToAdd in missingParameters) {
//We'll add the remaining parameters, in the order they were declared in the function
AddArgument(newInvocation, parameterToAdd, true);
}
script.Replace(invocationExpression, newInvocation);
}, invocationExpression);
}
}
static void AddArgument(InvocationExpression newNode, IParameter parameterToAdd, bool isNextInSequence)
{
Expression defaultValue;
if (parameterToAdd.ConstantValue == null) {
defaultValue = new NullReferenceExpression();
}
else {
defaultValue = new PrimitiveExpression(parameterToAdd.ConstantValue);
}
Expression newArgument;
if (newNode.Arguments.Any(argument => argument is NamedExpression) || !isNextInSequence) {
newArgument = new NamedArgumentExpression(parameterToAdd.Name, defaultValue);
}
else {
newArgument = defaultValue;
}
newNode.Arguments.Add(newArgument);
}
}
}

156
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AddUsingAction.cs

@ -0,0 +1,156 @@ @@ -0,0 +1,156 @@
// Copyright (c) 2013 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// 1) When a type cannot be resolved, offers to add a using declaration
/// or to replace it with the fully qualified type name.
/// 2) When an extension method cannot be resolved, offers to add a using declaration.
/// 3) When the caret is on a namespace name, offers to add a using declaration
/// and simplify the type references to use the new shorter option.
/// </summary>
[ContextAction ("Add using", Description = "Add missing using declaration.")]
public class AddUsingAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
AstNode node = context.GetNode();
if (node is Identifier)
node = node.Parent;
if (node is SimpleType || node is IdentifierExpression) {
return GetActionsForType(context, node)
.Concat(GetActionsForAddNamespaceUsing(context, node));
} else if (node is MemberReferenceExpression && node.Parent is InvocationExpression) {
return GetActionsForExtensionMethodInvocation(context, (InvocationExpression)node.Parent);
} else if (node is MemberReferenceExpression) {
return GetActionsForAddNamespaceUsing(context, node);
} else {
return EmptyList<CodeAction>.Instance;
}
}
IEnumerable<CodeAction> GetActionsForType(RefactoringContext context, AstNode node)
{
var rr = context.Resolve(node) as UnknownIdentifierResolveResult;
if (rr == null)
return EmptyList<CodeAction>.Instance;
string identifier = rr.Identifier;
int tc = rr.TypeArgumentCount;
string attributeIdentifier = null;
if (node.Parent is Attribute)
attributeIdentifier = identifier + "Attribute";
var lookup = new MemberLookup(null, context.Compilation.MainAssembly);
List<CodeAction> actions = new List<CodeAction>();
foreach (var typeDefinition in context.Compilation.GetAllTypeDefinitions()) {
if ((typeDefinition.Name == identifier || typeDefinition.Name == attributeIdentifier)
&& typeDefinition.TypeParameterCount == tc
&& lookup.IsAccessible(typeDefinition, false))
{
if (typeDefinition.DeclaringTypeDefinition == null) {
actions.Add(NewUsingAction(context, node, typeDefinition.Namespace));
}
actions.Add(ReplaceWithFullTypeNameAction(context, node, typeDefinition));
}
}
return actions;
}
CodeAction NewUsingAction(RefactoringContext context, AstNode node, string ns)
{
return new CodeAction("using " + ns + ";", s => UsingHelper.InsertUsingAndRemoveRedundantNamespaceUsage(context, s, ns), node);
}
CodeAction ReplaceWithFullTypeNameAction(RefactoringContext context, AstNode node, ITypeDefinition typeDefinition)
{
AstType astType = context.CreateShortType(typeDefinition);
string textWithoutGenerics = astType.ToString();
foreach (var typeArg in node.GetChildrenByRole(Roles.TypeArgument)) {
astType.AddChild(typeArg.Clone(), Roles.TypeArgument);
}
return new CodeAction(textWithoutGenerics, s => s.Replace(node, astType), node);
}
IEnumerable<CodeAction> GetActionsForExtensionMethodInvocation(RefactoringContext context, InvocationExpression invocation)
{
var rr = context.Resolve(invocation) as UnknownMethodResolveResult;
if (rr == null)
return EmptyList<CodeAction>.Instance;
var lookup = new MemberLookup(null, context.Compilation.MainAssembly);
HashSet<string> namespaces = new HashSet<string>();
List<CodeAction> result = new List<CodeAction>();
foreach (var typeDefinition in context.Compilation.GetAllTypeDefinitions()) {
if (!(typeDefinition.HasExtensionMethods && lookup.IsAccessible(typeDefinition, false))) {
continue;
}
foreach (var method in typeDefinition.Methods.Where(m => m.IsExtensionMethod && m.Name == rr.MemberName)) {
IType[] inferredTypes;
if (CSharpResolver.IsEligibleExtensionMethod(rr.TargetType, method, true, out inferredTypes)) {
// avoid offering the same namespace twice
if (namespaces.Add(typeDefinition.Namespace)) {
result.Add(NewUsingAction(context, invocation, typeDefinition.Namespace));
}
break; // continue with the next type
}
}
}
return result;
}
IEnumerable<CodeAction> GetActionsForAddNamespaceUsing(RefactoringContext context, AstNode node)
{
var nrr = context.Resolve(node) as NamespaceResolveResult;
if (nrr == null)
return EmptyList<CodeAction>.Instance;
var trr = context.Resolve(node.Parent) as TypeResolveResult;
if (trr == null)
return EmptyList<CodeAction>.Instance;
ITypeDefinition typeDef = trr.Type.GetDefinition();
if (typeDef == null)
return EmptyList<CodeAction>.Instance;
IList<IType> typeArguments;
ParameterizedType parameterizedType = trr.Type as ParameterizedType;
if (parameterizedType != null)
typeArguments = parameterizedType.TypeArguments;
else
typeArguments = EmptyList<IType>.Instance;
var resolver = context.GetResolverStateBefore(node.Parent);
if (resolver.ResolveSimpleName(typeDef.Name, typeArguments) is UnknownIdentifierResolveResult) {
// It's possible to remove the explicit namespace usage and introduce a using instead
return new[] { NewUsingAction(context, node, typeDef.Namespace) };
}
return EmptyList<CodeAction>.Instance;
}
}
}

435
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/AutoLinqSumAction.cs

@ -0,0 +1,435 @@ @@ -0,0 +1,435 @@
//
// AutoLinqSum.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis <luiscubal@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convers a loop to a Linq expression.
/// </summary>
[ContextAction("Convert loop to Linq expression", Description = "Converts a loop to a Linq expression")]
public class AutoLinqSumAction : CodeActionProvider
{
// Disabled for nullables, since int? x = 3; x += null; has result x = null,
// but LINQ Sum behaves differently : nulls are treated as zero
static readonly IEnumerable<string> LinqSummableTypes = new string[] {
"System.UInt16",
"System.Int16",
"System.UInt32",
"System.Int32",
"System.UInt64",
"System.Int64",
"System.Single",
"System.Double",
"System.Decimal"
};
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var loop = GetForeachStatement (context);
if (loop == null) {
yield break;
}
if (context.GetResolverStateBefore(loop)
.LookupSimpleNameOrTypeName("Enumerable", new List<IType>(), NameLookupMode.Type)
.Type.FullName != "System.Linq.Enumerable") {
yield break;
}
var outputStatement = GetTransformedAssignmentExpression (context, loop);
if (outputStatement == null) {
yield break;
}
yield return new CodeAction(context.TranslateString("Convert foreach loop to LINQ expression"), script => {
var prevSibling = loop.GetPrevSibling(node => node is Statement);
Expression leftSide = outputStatement.Left;
Expression rightSide = outputStatement.Right;
Expression expressionToReplace = GetExpressionToReplace(prevSibling, leftSide);
if (expressionToReplace != null) {
Expression replacementExpression = rightSide.Clone();
if (!IsZeroPrimitive(expressionToReplace)) {
replacementExpression = new BinaryOperatorExpression(ParenthesizeIfNeeded(expressionToReplace).Clone(),
BinaryOperatorType.Add,
replacementExpression);
}
script.Replace(expressionToReplace, replacementExpression);
script.Remove(loop);
}
else {
script.Replace(loop, new ExpressionStatement(outputStatement));
}
}, loop);
}
bool IsZeroPrimitive(Expression expr)
{
//We want a very simple check -- no looking at constants, no constant folding, etc.
//So 1+1 should return false, but (0) should return true
var parenthesizedExpression = expr as ParenthesizedExpression;
if (parenthesizedExpression != null) {
return IsZeroPrimitive(parenthesizedExpression.Expression);
}
var zeroLiteralInteger = new PrimitiveExpression(0);
var zeroLiteralFloat = new PrimitiveExpression(0.0f);
var zeroLiteralDouble = new PrimitiveExpression(0.0);
var zeroLiteralDecimal = new PrimitiveExpression(0.0m);
return SameNode(zeroLiteralInteger, expr) ||
SameNode(zeroLiteralFloat, expr) ||
SameNode(zeroLiteralDouble, expr) ||
SameNode(zeroLiteralDecimal, expr);
}
Expression GetExpressionToReplace(AstNode prevSibling, Expression requiredLeftSide)
{
if (prevSibling == null) {
return null;
}
var declarationStatement = prevSibling as VariableDeclarationStatement;
if (declarationStatement != null)
{
if (declarationStatement.Variables.Count != 1) {
return null;
}
var identifierExpr = requiredLeftSide as IdentifierExpression;
if (identifierExpr == null) {
return null;
}
var variableDecl = declarationStatement.Variables.First();
if (!SameNode(identifierExpr.IdentifierToken, variableDecl.NameToken)) {
return null;
}
return variableDecl.Initializer;
}
var exprStatement = prevSibling as ExpressionStatement;
if (exprStatement != null) {
var assignment = exprStatement.Expression as AssignmentExpression;
if (assignment != null) {
if (assignment.Operator != AssignmentOperatorType.Assign &&
assignment.Operator != AssignmentOperatorType.Add) {
return null;
}
if (!SameNode(requiredLeftSide, assignment.Left)) {
return null;
}
return assignment.Right;
}
}
return null;
}
bool IsUnaryModifierExpression(UnaryOperatorExpression expr)
{
return expr.Operator == UnaryOperatorType.Increment || expr.Operator == UnaryOperatorType.PostIncrement || expr.Operator == UnaryOperatorType.Decrement || expr.Operator == UnaryOperatorType.PostDecrement;
}
AssignmentExpression GetTransformedAssignmentExpression (RefactoringContext context, ForeachStatement foreachStatement)
{
var enumerableToIterate = foreachStatement.InExpression.Clone();
Statement statement = foreachStatement.EmbeddedStatement;
Expression leftExpression, rightExpression;
if (!ExtractExpression(statement, out leftExpression, out rightExpression)) {
return null;
}
if (leftExpression == null || rightExpression == null) {
return null;
}
var type = context.Resolve(leftExpression).Type;
if (!IsLinqSummableType(type)) {
return null;
}
if (rightExpression.DescendantsAndSelf.OfType<AssignmentExpression>().Any()) {
// Reject loops such as
// int k = 0;
// foreach (var x in y) { k += (z = 2); }
return null;
}
if (rightExpression.DescendantsAndSelf.OfType<UnaryOperatorExpression>().Any(IsUnaryModifierExpression)) {
// int k = 0;
// foreach (var x in y) { k += (z++); }
return null;
}
var zeroLiteral = new PrimitiveExpression(0);
Expression baseExpression = enumerableToIterate;
for (;;) {
ConditionalExpression condition = rightExpression as ConditionalExpression;
if (condition == null) {
break;
}
if (SameNode(zeroLiteral, condition.TrueExpression)) {
baseExpression = new InvocationExpression(new MemberReferenceExpression(baseExpression.Clone(), "Where"),
BuildLambda(foreachStatement.VariableName, CSharpUtil.InvertCondition(condition.Condition)));
rightExpression = condition.FalseExpression.Clone();
continue;
}
if (SameNode(zeroLiteral, condition.FalseExpression)) {
baseExpression = new InvocationExpression(new MemberReferenceExpression(baseExpression.Clone(), "Where"),
BuildLambda(foreachStatement.VariableName, condition.Condition.Clone()));
rightExpression = condition.TrueExpression.Clone();
continue;
}
break;
}
var primitiveOne = new PrimitiveExpression(1);
bool isPrimitiveOne = SameNode(primitiveOne, rightExpression);
var arguments = new List<Expression>();
string method = isPrimitiveOne ? "Count" : "Sum";
if (!isPrimitiveOne && !IsIdentifier(rightExpression, foreachStatement.VariableName)) {
var lambda = BuildLambda(foreachStatement.VariableName, rightExpression);
arguments.Add(lambda);
}
var rightSide = new InvocationExpression(new MemberReferenceExpression(baseExpression, method), arguments);
return new AssignmentExpression(leftExpression.Clone(), AssignmentOperatorType.Add, rightSide);
}
static LambdaExpression BuildLambda(string variableName, Expression expression)
{
var lambda = new LambdaExpression();
lambda.Parameters.Add(new ParameterDeclaration() {
Name = variableName
});
lambda.Body = expression.Clone();
return lambda;
}
bool IsIdentifier(Expression expr, string variableName)
{
var identifierExpr = expr as IdentifierExpression;
if (identifierExpr != null) {
return identifierExpr.Identifier == variableName;
}
var parenthesizedExpr = expr as ParenthesizedExpression;
if (parenthesizedExpr != null) {
return IsIdentifier(parenthesizedExpr.Expression, variableName);
}
return false;
}
bool IsLinqSummableType(IType type) {
return LinqSummableTypes.Contains(type.FullName);
}
bool ExtractExpression (Statement statement, out Expression leftSide, out Expression rightSide) {
ExpressionStatement expression = statement as ExpressionStatement;
if (expression != null) {
AssignmentExpression assignment = expression.Expression as AssignmentExpression;
if (assignment != null) {
if (assignment.Operator == AssignmentOperatorType.Add) {
leftSide = assignment.Left;
rightSide = assignment.Right;
return true;
}
if (assignment.Operator == AssignmentOperatorType.Subtract) {
leftSide = assignment.Left;
rightSide = new UnaryOperatorExpression(UnaryOperatorType.Minus, assignment.Right.Clone());
return true;
}
leftSide = null;
rightSide = null;
return false;
}
UnaryOperatorExpression unary = expression.Expression as UnaryOperatorExpression;
if (unary != null) {
leftSide = unary.Expression;
if (unary.Operator == UnaryOperatorType.Increment || unary.Operator == UnaryOperatorType.PostIncrement) {
rightSide = new PrimitiveExpression(1);
return true;
} else if (unary.Operator == UnaryOperatorType.Decrement || unary.Operator == UnaryOperatorType.PostDecrement) {
rightSide = new PrimitiveExpression(-1);
return true;
} else {
leftSide = null;
rightSide = null;
return false;
}
}
}
if (statement is EmptyStatement || statement.IsNull) {
leftSide = null;
rightSide = null;
return true;
}
BlockStatement block = statement as BlockStatement;
if (block != null) {
leftSide = null;
rightSide = null;
foreach (Statement child in block.Statements) {
Expression newLeft, newRight;
if (!ExtractExpression(child, out newLeft, out newRight)) {
leftSide = null;
rightSide = null;
return false;
}
if (newLeft == null) {
continue;
}
if (leftSide == null) {
leftSide = newLeft;
rightSide = newRight;
} else if (SameNode(leftSide, newLeft)) {
rightSide = new BinaryOperatorExpression(ParenthesizeIfNeeded(rightSide).Clone(),
BinaryOperatorType.Add,
ParenthesizeIfNeeded(newRight).Clone());
} else {
return false;
}
}
return true;
}
IfElseStatement condition = statement as IfElseStatement;
if (condition != null) {
Expression ifLeft, ifRight;
if (!ExtractExpression(condition.TrueStatement, out ifLeft, out ifRight)) {
leftSide = null;
rightSide = null;
return false;
}
Expression elseLeft, elseRight;
if (!ExtractExpression(condition.FalseStatement, out elseLeft, out elseRight)) {
leftSide = null;
rightSide = null;
return false;
}
if (ifLeft == null && elseLeft == null) {
leftSide = null;
rightSide = null;
return true;
}
if (ifLeft != null && elseLeft != null && !SameNode(ifLeft, elseLeft)) {
leftSide = null;
rightSide = null;
return false;
}
ifRight = ifRight ?? new PrimitiveExpression(0);
elseRight = elseRight ?? new PrimitiveExpression(0);
leftSide = ifLeft ?? elseLeft;
rightSide = new ConditionalExpression(condition.Condition.Clone(), ifRight.Clone(), elseRight.Clone());
return true;
}
leftSide = null;
rightSide = null;
return false;
}
Expression ParenthesizeIfNeeded(Expression expr)
{
if (expr is ConditionalExpression) {
return new ParenthesizedExpression(expr.Clone());
}
var binaryExpression = expr as BinaryOperatorExpression;
if (binaryExpression != null) {
if (binaryExpression.Operator != BinaryOperatorType.Multiply &&
binaryExpression.Operator != BinaryOperatorType.Divide &&
binaryExpression.Operator != BinaryOperatorType.Modulus) {
return new ParenthesizedExpression(expr.Clone());
}
}
return expr;
}
bool SameNode(INode expr1, INode expr2)
{
Match m = expr1.Match(expr2);
return m.Success;
}
static ForeachStatement GetForeachStatement (RefactoringContext context)
{
var foreachStatement = context.GetNode<ForeachStatement>();
if (foreachStatement == null || !foreachStatement.ForeachToken.Contains(context.Location))
return null;
return foreachStatement;
}
}
}

71
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CS1520MethodMustHaveAReturnTypeAction.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
//
// CS1520MethodMustHaveAReturnTypeAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Class, struct or interface method must have a return type", Description = "Found method without return type.")]
public class CS1520MethodMustHaveAReturnTypeAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var entity = context.GetNode<ConstructorDeclaration>();
if (entity == null)
yield break;
var type = entity.Parent as TypeDeclaration;
if (type == null || entity.Name == type.Name)
yield break;
var typeDeclaration = entity.GetParent<TypeDeclaration>();
yield return new CodeAction(context.TranslateString("This is a constructor"), script => script.Replace(entity.NameToken, Identifier.Create(typeDeclaration.Name, TextLocation.Empty)), entity) {
Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error
};
yield return new CodeAction(context.TranslateString("This is a void method"), script => {
var generatedMethod = new MethodDeclaration();
generatedMethod.Modifiers = entity.Modifiers;
generatedMethod.ReturnType = new PrimitiveType("void");
generatedMethod.Name = entity.Name;
generatedMethod.Parameters.AddRange(entity.Parameters.Select(parameter => (ParameterDeclaration)parameter.Clone()));
generatedMethod.Body = (BlockStatement)entity.Body.Clone();
generatedMethod.Attributes.AddRange(entity.Attributes.Select(attribute => (AttributeSection)attribute.Clone()));
script.Replace(entity, generatedMethod);
}, entity) {
Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error
};
}
}
}

175
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ChangeAccessModifierAction.cs

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
//
// ChangeAccessModifierAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Changes the access level of an entity declaration
/// </summary>
[ContextAction("Change the access level of an entity declaration", Description = "Changes the access level of an entity declaration")]
public class ChangeAccessModifierAction : CodeActionProvider
{
Dictionary<string, Modifiers> accessibilityLevels = new Dictionary<string, Modifiers> {
{ "private", Modifiers.Private },
{ "protected", Modifiers.Protected },
{ "protected internal", Modifiers.Protected | Modifiers.Internal },
{ "internal", Modifiers.Internal },
{ "public", Modifiers.Public }
};
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<EntityDeclaration>();
if (node == null)
yield break;
var selectedNode = node.GetNodeAt(context.Location);
if (selectedNode == null)
yield break;
if (selectedNode.Role != PropertyDeclaration.SetKeywordRole &&
selectedNode.Role != PropertyDeclaration.GetKeywordRole &&
selectedNode != node.NameToken) {
if (selectedNode.Role == EntityDeclaration.ModifierRole) {
var mod = (CSharpModifierToken)selectedNode;
if ((mod.Modifier & Modifiers.VisibilityMask) == 0)
yield break;
} else {
yield break;
}
}
if (node is EnumMemberDeclaration) {
yield break;
}
if (node.HasModifier(Modifiers.Override))
yield break;
var parentTypeDeclaration = node.GetParent<TypeDeclaration>();
if (parentTypeDeclaration != null && parentTypeDeclaration.ClassType == ClassType.Interface) {
//Interface members have no access modifiers
yield break;
}
var resolveResult = context.Resolve(node) as MemberResolveResult;
if (resolveResult != null) {
if (resolveResult.Member.ImplementedInterfaceMembers.Any())
yield break;
}
foreach (var accessName in accessibilityLevels.Keys) {
var access = accessibilityLevels [accessName];
if (parentTypeDeclaration == null && ((access & (Modifiers.Private | Modifiers.Protected)) != 0)) {
//Top-level declarations can only be public or internal
continue;
}
var accessor = node as Accessor;
if (accessor != null) {
//Allow only converting to modifiers stricter than the parent entity
var actualParentAccess = GetActualAccess(parentTypeDeclaration, accessor.GetParent<EntityDeclaration>());
if (access != actualParentAccess && !IsStricterThan (access, actualParentAccess)) {
continue;
}
}
if (GetActualAccess(parentTypeDeclaration, node) != access) {
yield return GetActionForLevel(context, accessName, access, node, selectedNode);
}
}
}
static bool IsStricterThan(Modifiers access1, Modifiers access2)
{
//First cover the basic cases
if (access1 == access2) {
return false;
}
if (access1 == Modifiers.Private) {
return true;
}
if (access2 == Modifiers.Private) {
return false;
}
if (access1 == Modifiers.Public) {
return false;
}
if (access2 == Modifiers.Public) {
return true;
}
return access2 == (Modifiers.Protected | Modifiers.Internal);
}
static Modifiers GetActualAccess(AstNode parentTypeDeclaration, EntityDeclaration node)
{
Modifiers nodeAccess = node.Modifiers & Modifiers.VisibilityMask;
if (nodeAccess == Modifiers.None && node is Accessor) {
EntityDeclaration parent = node.GetParent<EntityDeclaration>();
nodeAccess = parent.Modifiers & Modifiers.VisibilityMask;
}
if (nodeAccess == Modifiers.None) {
if (parentTypeDeclaration == null) {
return Modifiers.Internal;
}
return Modifiers.Private;
}
return nodeAccess & Modifiers.VisibilityMask;
}
CodeAction GetActionForLevel(RefactoringContext context, string accessName, Modifiers access, EntityDeclaration node, AstNode selectedNode)
{
return new CodeAction(context.TranslateString("To " + accessName), script => {
Modifiers newModifiers = node.Modifiers;
newModifiers &= ~Modifiers.VisibilityMask;
if (!(node is Accessor) || access != (node.GetParent<EntityDeclaration>().Modifiers & Modifiers.VisibilityMask)) {
//Do not add access modifier for accessors if the new access level is the same as the parent
//That is, in public int X { $private get; } if access == public, then the result should not have the modifier
newModifiers |= access;
}
script.ChangeModifier(node, newModifiers);
}, selectedNode);
}
}
}

94
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CheckIfParameterIsNullAction.cs

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
//
// CheckIfParameterIsNull.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.PatternMatching;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Creates a 'if (param == null) throw new System.ArgumentNullException ();' contruct for a parameter.
/// </summary>
[ContextAction("Check if parameter is null", Description = "Checks function parameter is not null.")]
public class CheckIfParameterIsNullAction : SpecializedCodeAction<ParameterDeclaration>
{
protected override CodeAction GetAction(RefactoringContext context, ParameterDeclaration parameter)
{
if (!parameter.NameToken.Contains(context.Location))
return null;
BlockStatement bodyStatement;
if (parameter.Parent is LambdaExpression) {
bodyStatement = parameter.Parent.GetChildByRole (LambdaExpression.BodyRole) as BlockStatement;
} else {
bodyStatement = parameter.Parent.GetChildByRole (Roles.Body);
}
if (bodyStatement == null || bodyStatement.IsNull)
return null;
var type = context.ResolveType(parameter.Type);
if (type.IsReferenceType == false || HasNullCheck(parameter))
return null;
return new CodeAction(context.TranslateString("Add null check for parameter"), script => {
var statement = new IfElseStatement() {
Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()),
TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name)))
};
script.AddTo(bodyStatement, statement);
}, parameter.NameToken);
}
static bool HasNullCheck (ParameterDeclaration parameter)
{
var visitor = new CheckNullVisitor (parameter);
parameter.Parent.AcceptVisitor (visitor, null);
return visitor.ContainsNullCheck;
}
class CheckNullVisitor : DepthFirstAstVisitor<object, object>
{
readonly Expression pattern;
internal bool ContainsNullCheck;
public CheckNullVisitor (ParameterDeclaration parameter)
{
pattern = PatternHelper.CommutativeOperator(new IdentifierExpression(parameter.Name), BinaryOperatorType.Any, new NullReferenceExpression());
}
public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data)
{
if (ifElseStatement.Condition is BinaryOperatorExpression) {
var binOp = ifElseStatement.Condition as BinaryOperatorExpression;
if ((binOp.Operator == BinaryOperatorType.Equality || binOp.Operator == BinaryOperatorType.InEquality) && pattern.IsMatch(binOp)) {
ContainsNullCheck = true;
}
}
return base.VisitIfElseStatement (ifElseStatement, data);
}
}
}
}

53
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ComputeConstantValueAction.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
//
// ComputeConstantValueAction.cs
//
// Author:
// Ji Kun <jikun.nus@gmail.com>
//
// Copyright (c) 2013 Ji Kun <jikun.nus@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Compute constant value", Description = "Computes the value of the current expression and replaces it.")]
public class ComputeConstantValueAction : CodeActionProvider
{
public override System.Collections.Generic.IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var expression = context.GetNode(i => i is BinaryOperatorExpression || i is UnaryOperatorExpression);
if (expression == null)
yield break;
var node = context.GetNode();
if (node == null || !(node is PrimitiveExpression) && node.StartLocation != context.Location)
yield break;
var rr = context.Resolve(expression);
if (rr.ConstantValue == null)
yield break;
yield return new CodeAction(
context.TranslateString("Compute constant value"),
script => script.Replace(expression, new PrimitiveExpression(rr.ConstantValue)),
node
);
}
}
}

95
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAnonymousDelegateToLambdaAction.cs

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
//
// ConvertAnonymousDelegateToExpression.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert anonymous delegate to lambda",
Description = "Converts an anonymous delegate into a lambda")]
public class ConvertAnonymousDelegateToLambdaAction : SpecializedCodeAction<AnonymousMethodExpression>
{
#region implemented abstract members of SpecializedCodeAction
protected override CodeAction GetAction(RefactoringContext context, AnonymousMethodExpression node)
{
if (context.Location < node.DelegateToken.StartLocation || context.Location >= node.Body.StartLocation)
return null;
Expression convertExpression = null;
var stmt = node.Body.Statements.FirstOrDefault();
if (stmt.GetNextSibling(s => s.Role == BlockStatement.StatementRole) == null) {
var exprStmt = stmt as ExpressionStatement;
if (exprStmt != null) {
convertExpression = exprStmt.Expression;
}
}
IType guessedType = null;
if (!node.HasParameterList) {
guessedType = TypeGuessing.GuessType(context, node);
if (guessedType.Kind != TypeKind.Delegate)
return null;
}
return new CodeAction(context.TranslateString("Convert to lambda"),
script => {
var parent = node.Parent;
while (!(parent is Statement))
parent = parent.Parent;
bool explicitLambda = parent is VariableDeclarationStatement && ((VariableDeclarationStatement)parent).Type.IsVar();
var lambda = new LambdaExpression ();
if (convertExpression != null) {
lambda.Body = convertExpression.Clone();
} else {
lambda.Body = node.Body.Clone();
}
if (node.HasParameterList) {
foreach (var parameter in node.Parameters) {
if (explicitLambda) {
lambda.Parameters.Add(new ParameterDeclaration { Type = parameter.Type.Clone(), Name = parameter.Name });
} else {
lambda.Parameters.Add(new ParameterDeclaration { Name = parameter.Name });
}
}
} else {
var method = guessedType.GetDelegateInvokeMethod ();
foreach (var parameter in method.Parameters) {
lambda.Parameters.Add(new ParameterDeclaration { Name = parameter.Name });
}
}
script.Replace(node, lambda);
},
node);
}
#endregion
}
}

58
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAsToCastAction.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
//
// ConvertAsToCastAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Converts an 'as' expression to a cast expression
/// </summary>
[ContextAction("Convert 'as' to cast.", Description = "Convert 'as' to cast.")]
public class ConvertAsToCastAction : SpecializedCodeAction <AsExpression>
{
static InsertParenthesesVisitor insertParentheses = new InsertParenthesesVisitor ();
protected override CodeAction GetAction (RefactoringContext context, AsExpression node)
{
if (!node.AsToken.Contains (context.Location))
return null;
return new CodeAction (context.TranslateString ("Convert 'as' to cast"), script => {
var castExpr = new CastExpression (node.Type.Clone (), node.Expression.Clone ());
var parenthesizedExpr = node.Parent as ParenthesizedExpression;
if (parenthesizedExpr != null && parenthesizedExpr.Parent is Expression) {
// clone parent expression and replace the ParenthesizedExpression with castExpr to remove
// parentheses, then insert parentheses if necessary
var parentExpr = (Expression)parenthesizedExpr.Parent.Clone ();
parentExpr.GetNodeContaining (parenthesizedExpr.StartLocation, parenthesizedExpr.EndLocation)
.ReplaceWith (castExpr);
parentExpr.AcceptVisitor (insertParentheses);
script.Replace (parenthesizedExpr.Parent, parentExpr);
} else {
castExpr.AcceptVisitor (insertParentheses);
script.Replace (node, castExpr);
}
}, node.AsToken);
}
}
}

81
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertAssignmentToIfAction.cs

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
//
// ConvertAssignmentToIfAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert assignment to 'if'",
Description = "Convert assignment to 'if'")]
public class ConvertAssignmentToIfAction : SpecializedCodeAction<AssignmentExpression>
{
protected override CodeAction GetAction(RefactoringContext context, AssignmentExpression node)
{
if (!node.OperatorToken.Contains(context.Location) || !(node.Parent is ExpressionStatement))
return null;
if (node.Right is ConditionalExpression)
return CreateForConditionalExpression(context, node, (ConditionalExpression)node.Right);
var bOp = node.Right as BinaryOperatorExpression;
if (bOp != null && bOp.Operator == BinaryOperatorType.NullCoalescing)
return CreateForNullCoalesingExpression(context, node, bOp);
return null;
}
static CodeAction CreateForConditionalExpression(RefactoringContext ctx, AssignmentExpression node, ConditionalExpression conditionalExpression)
{
return new CodeAction (
ctx.TranslateString("Replace with 'if' statement"),
script => {
var ifStatement = new IfElseStatement(
conditionalExpression.Condition.Clone(),
new AssignmentExpression(node.Left.Clone(), node.Operator, conditionalExpression.TrueExpression.Clone()),
new AssignmentExpression(node.Left.Clone(), node.Operator, conditionalExpression.FalseExpression.Clone())
);
script.Replace(node.Parent, ifStatement);
},
node.OperatorToken
);
}
static CodeAction CreateForNullCoalesingExpression(RefactoringContext ctx, AssignmentExpression node, BinaryOperatorExpression bOp)
{
return new CodeAction (
ctx.TranslateString("Replace with 'if' statement"),
script => {
var ifStatement = new IfElseStatement(
new BinaryOperatorExpression(bOp.Left.Clone(), BinaryOperatorType.InEquality, new NullReferenceExpression()),
new AssignmentExpression(node.Left.Clone(), node.Operator, bOp.Left.Clone()),
new AssignmentExpression(node.Left.Clone(), node.Operator, bOp.Right.Clone())
);
script.Replace(node.Parent, ifStatement);
},
node.OperatorToken
);
}
}
}

110
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertBitwiseFlagComparisonToHasFlagsAction.cs

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
//
// ConvertBitwiseFlagComparisonToHasFlagsAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Replace bitwise flag comparison with call to 'Enum.HasFlag'", Description = "Replace bitwise flag comparison with call to 'Enum.HasFlag'")]
public class ConvertBitwiseFlagComparisonToHasFlagsAction : SpecializedCodeAction<BinaryOperatorExpression>
{
static readonly AstNode truePattern = new Choice {
new BinaryOperatorExpression (new ParenthesizedExpression(new BinaryOperatorExpression (PatternHelper.OptionalParentheses(new AnyNode("target")), BinaryOperatorType.BitwiseAnd, PatternHelper.OptionalParentheses(new AnyNode("expr")))), BinaryOperatorType.InEquality, PatternHelper.OptionalParentheses(new PrimitiveExpression(0))),
new BinaryOperatorExpression (new ParenthesizedExpression(new BinaryOperatorExpression (PatternHelper.OptionalParentheses(new AnyNode("target")), BinaryOperatorType.BitwiseAnd, PatternHelper.OptionalParentheses(new AnyNode("expr")))), BinaryOperatorType.Equality, PatternHelper.OptionalParentheses(new Backreference("expr")))
};
static readonly AstNode falsePattern = new Choice {
new BinaryOperatorExpression (new ParenthesizedExpression(new BinaryOperatorExpression (PatternHelper.OptionalParentheses(new AnyNode("target")), BinaryOperatorType.BitwiseAnd, PatternHelper.OptionalParentheses(new AnyNode("expr")))), BinaryOperatorType.Equality, PatternHelper.OptionalParentheses(new PrimitiveExpression(0))),
new BinaryOperatorExpression (new ParenthesizedExpression(new BinaryOperatorExpression (PatternHelper.OptionalParentheses(new AnyNode("target")), BinaryOperatorType.BitwiseAnd, PatternHelper.OptionalParentheses(new AnyNode("expr")))), BinaryOperatorType.InEquality, PatternHelper.OptionalParentheses(new Backreference("expr")))
};
internal static Expression MakeFlatExpression (Expression expr, BinaryOperatorType opType)
{
var bOp = expr as BinaryOperatorExpression;
if (bOp == null)
return expr.Clone();
return new BinaryOperatorExpression(
MakeFlatExpression(bOp.Left, opType),
opType,
MakeFlatExpression(bOp.Right, opType)
);
}
static Expression BuildHasFlagExpression (Expression target, Expression expr)
{
var bOp = expr as BinaryOperatorExpression;
if (bOp == null)
return new InvocationExpression(new MemberReferenceExpression(target.Clone(), "HasFlag"), expr.Clone());
if (bOp.Operator == BinaryOperatorType.BitwiseOr) {
return new BinaryOperatorExpression(
BuildHasFlagExpression(target, bOp.Left),
BinaryOperatorType.BitwiseOr,
BuildHasFlagExpression(target, bOp.Right)
);
}
return new InvocationExpression(new MemberReferenceExpression(target.Clone(), "HasFlag"), MakeFlatExpression (bOp, BinaryOperatorType.BitwiseOr));
}
static CodeAction CreateAction(BaseRefactoringContext context, Match match, bool negateMatch, BinaryOperatorExpression node)
{
var target = match.Get<Expression>("target").Single();
var expr = match.Get<Expression>("expr").Single();
if (!expr.DescendantsAndSelf.All(x => !(x is BinaryOperatorExpression) || ((BinaryOperatorExpression)x).Operator == BinaryOperatorType.BitwiseOr) &&
!expr.DescendantsAndSelf.All(x => !(x is BinaryOperatorExpression) || ((BinaryOperatorExpression)x).Operator == BinaryOperatorType.BitwiseAnd))
return null;
var rr = context.Resolve(target);
if (rr.Type.Kind != ICSharpCode.NRefactory.TypeSystem.TypeKind.Enum)
return null;
return new CodeAction(
context.TranslateString("Replace with 'Enum.HasFlag'"),
script => {
Expression newExpr = BuildHasFlagExpression (target, expr);
if (negateMatch)
newExpr = new UnaryOperatorExpression(UnaryOperatorType.Not, newExpr);
script.Replace(node, newExpr);
},
node.OperatorToken);
}
protected override CodeAction GetAction(RefactoringContext context, BinaryOperatorExpression node)
{
if (!node.OperatorToken.Contains(context.Location))
return null;
var match = truePattern.Match(node);
if (match.Success)
return CreateAction(context, match, false, node);
match = falsePattern.Match(node);
if (match.Success)
return CreateAction(context, match, true, node);
return null;
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertCastToAsAction.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertCastToAsAction.cs

52
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertDecToHexAction.cs

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
//
// ConvertDecToHex.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convert a dec numer to hex. For example: 16 -> 0x10
/// </summary>
[ContextAction("Convert dec to hex.", Description = "Convert dec to hex.")]
public class ConvertDecToHexAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var pexpr = context.GetNode<PrimitiveExpression>();
if (pexpr == null || pexpr.LiteralValue.StartsWith("0X", System.StringComparison.OrdinalIgnoreCase))
yield break;
var value = pexpr.Value;
if (value is string || value is bool || value is float || value is double || value is char)
yield break;
yield return new CodeAction(context.TranslateString("Convert to hex"), script => {
script.Replace(pexpr, new PrimitiveExpression (value, string.Format("0x{0:x}", value)));
}, pexpr);
}
}
}

70
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertDoWhileToWhileLoopAction.cs

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
//
// ConvertDoWhileToWhileLoopAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convert do...while to while. For instance, { do x++; while (Foo(x)); } becomes { while(Foo(x)) x++; }.
/// Note that this action will often change the semantics of the code.
/// </summary>
[ContextAction("Convert do...while to while.", Description = "Converts a do...while to a while loop (changing semantics).")]
public class ConvertDoWhileToWhileLoopAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<DoWhileStatement>();
if (node == null)
yield break;
var target = node.DoToken;
if (!target.Contains(context.Location)) {
target = node.WhileToken;
if (!target.Contains(context.Location)) {
yield break;
}
}
yield return new CodeAction(context.TranslateString("Convert to while loop"),
script => ConvertToWhileLoop(script, node),
target);
}
static void ConvertToWhileLoop(Script script, DoWhileStatement originalStatement)
{
script.Replace(originalStatement, new WhileStatement {
Condition = originalStatement.Condition.Clone(),
EmbeddedStatement = originalStatement.EmbeddedStatement.Clone()
});
}
}
}

88
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertEqualityOperatorToEqualsAction.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
//
// ConvertEqualityOperatorToEqualsAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convert do...while to while. For instance, { do x++; while (Foo(x)); } becomes { while(Foo(x)) x++; }.
/// Note that this action will often change the semantics of the code.
/// </summary>
[ContextAction("Convert '==' to 'Equals'", Description = "Converts '==' to call to 'object.Equals'")]
public class ConvertEqualityOperatorToEqualsAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<BinaryOperatorExpression>();
if (node == null ||
(node.Operator != BinaryOperatorType.Equality && node.Operator != BinaryOperatorType.InEquality) ||
!node.OperatorToken.Contains(context.Location))
yield break;
yield return new CodeAction(
context.TranslateString("Use 'Equals'"),
script => {
Expression expr = new InvocationExpression(GenerateTarget(context, node), node.Left.Clone(), node.Right.Clone());
if (node.Operator == BinaryOperatorType.InEquality)
expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
script.Replace(node, expr);
},
node.OperatorToken
);
}
readonly IList<IType> emptyTypes = new IType[0];
bool HasDifferentEqualsMethod(IEnumerable<IMethod> methods)
{
foreach (var method in methods) {
if (method.Parameters.Count == 2 && method.FullName != "System.Object.Equals") {
return true;
}
}
return false;
}
Expression GenerateTarget(RefactoringContext context, BinaryOperatorExpression bOp)
{
var rr = context.Resolver.GetResolverStateBefore(bOp).LookupSimpleNameOrTypeName("Equals", emptyTypes, NameLookupMode.Expression) as MethodGroupResolveResult;
if (rr == null || rr.IsError || HasDifferentEqualsMethod (rr.Methods)) {
return new MemberReferenceExpression(
new PrimitiveType ("object"),
"Equals"
);
}
return new IdentifierExpression("Equals");
}
}
}

83
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertEqualsToEqualityOperatorAction.cs

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
//
// ConvertEqualsToEqualityOperatorAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.CSharp;
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convert do...while to while. For instance, { do x++; while (Foo(x)); } becomes { while(Foo(x)) x++; }.
/// Note that this action will often change the semantics of the code.
/// </summary>
[ContextAction("Convert 'Equals' to '=='", Description = "Converts 'Equals' call to '=='")]
public class ConvertEqualsToEqualityOperatorAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var node = context.GetNode<InvocationExpression>();
if (node == null)
yield break;
if ((node.Target is IdentifierExpression) && !node.Target.IsInside(context.Location))
yield break;
var memberRefExpr = node.Target as MemberReferenceExpression;
if ((memberRefExpr != null) && !memberRefExpr.MemberNameToken.IsInside(context.Location))
yield break;
var rr = context.Resolve(node) as CSharpInvocationResolveResult;
if (rr == null || rr.IsError || rr.Member.Name != "Equals" || !rr.Member.DeclaringType.IsKnownType(KnownTypeCode.Object))
yield break;
Expression expr = node;
bool useEquality = true;
var uOp = node.Parent as UnaryOperatorExpression;
if (uOp != null && uOp.Operator == UnaryOperatorType.Not) {
expr = uOp;
useEquality = false;
}
if (node.Arguments.Count != 2 && (memberRefExpr == null || node.Arguments.Count != 1))
yield break;
yield return new CodeAction(
useEquality ? context.TranslateString("Use '=='") : context.TranslateString("Use '!='"),
script => {
script.Replace(
expr,
new BinaryOperatorExpression(
node.Arguments.Count == 1 ? memberRefExpr.Target.Clone() : node.Arguments.First().Clone(),
useEquality ? BinaryOperatorType.Equality : BinaryOperatorType.InEquality,
node.Arguments.Last().Clone()
)
);
},
node.Target
);
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertExplicitToImplicitImplementationAction.cs

56
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertForToWhileAction.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
//
// ConvertForToWhileAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert 'for' loop to 'while'", Description = "Works on 'for' loops.")]
public class ConvertForToWhileAction : SpecializedCodeAction<ForStatement>
{
protected override CodeAction GetAction(RefactoringContext context, ForStatement node)
{
if (!node.ForToken.Contains(context.Location))
return null;
return new CodeAction(
context.TranslateString("Convert to 'while'"),
script => {
var body = node.EmbeddedStatement.Clone();
var blockStatement = body as BlockStatement ?? new BlockStatement { Statements = { body } };
blockStatement.Statements.AddRange(node.Iterators.Select(i => i.Clone ()));
var whileStatement = new WhileStatement(node.Condition.IsNull ? new PrimitiveExpression(true) : node.Condition.Clone(), blockStatement);
foreach (var init in node.Initializers) {
var stmt = init.Clone();
stmt.Role = BlockStatement.StatementRole;
script.InsertBefore(node, stmt);
}
script.Replace(node, whileStatement);
},
node
);
}
}
}

218
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertForeachToForAction.cs

@ -0,0 +1,218 @@ @@ -0,0 +1,218 @@
//
// ConvertForeachToFor.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Converts a foreach loop to for.
/// </summary>
[ContextAction("Convert 'foreach' loop to 'for'", Description = "Works on 'foreach' loops that allow direct access to its elements.")]
public class ConvertForeachToForAction : CodeActionProvider
{
static readonly string[] VariableNames = { "i", "j", "k", "l", "n", "m", "x", "y", "z"};
static readonly string[] CollectionNames = { "list" };
static string GetName(ICSharpCode.NRefactory.CSharp.Resolver.CSharpResolver state, string[] variableNames)
{
for (int i = 0; i < 1000; i++) {
foreach (var vn in variableNames) {
string id = i > 0 ? vn + i : vn;
var rr = state.LookupSimpleNameOrTypeName(id, new IType[0], NameLookupMode.Expression);
if (rr.IsError)
return id;
}
}
return null;
}
string GetBoundName(Expression inExpression)
{
var ie = inExpression as IdentifierExpression;
if (ie != null)
return ie.Identifier;
var mre = inExpression as MemberReferenceExpression;
if (mre != null)
return GetBoundName(mre.Target) + mre.MemberName;
return "max";
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
bool hasIndexAccess;
var foreachStatement = GetForeachStatement(context, out hasIndexAccess);
if (foreachStatement == null || foreachStatement.EmbeddedStatement == null)
yield break;
var state = context.GetResolverStateBefore (foreachStatement.EmbeddedStatement);
string name = GetName(state, VariableNames);
if (name == null) // very unlikely, but just in case ...
yield break;
yield return new CodeAction(context.TranslateString("Convert 'foreach' loop to 'for'"), script => {
var result = context.Resolve(foreachStatement.InExpression);
var countProperty = GetCountProperty(result.Type);
var inExpression = foreachStatement.InExpression;
var initializer = hasIndexAccess ? new VariableDeclarationStatement(new PrimitiveType("int"), name, new PrimitiveExpression(0)) :
new VariableDeclarationStatement(new SimpleType("var"), name, new InvocationExpression(new MemberReferenceExpression (inExpression.Clone (), "GetEnumerator")));
var id1 = new IdentifierExpression(name);
var id2 = id1.Clone();
var id3 = id1.Clone();
Statement declarationStatement = null;
if (inExpression is ObjectCreateExpression || inExpression is ArrayCreateExpression) {
string listName = GetName(state, CollectionNames) ?? "col";
declarationStatement = new VariableDeclarationStatement (
new PrimitiveType ("var"),
listName,
inExpression.Clone ()
);
inExpression = new IdentifierExpression (listName);
}
var variableDeclarationStatement = new VariableDeclarationStatement(
foreachStatement.VariableType.Clone(),
foreachStatement.VariableName,
hasIndexAccess ? (Expression)new IndexerExpression(inExpression.Clone(), id3) : new MemberReferenceExpression(id1, "Current")
);
var forStatement = new ForStatement {
Initializers = { initializer },
Condition = hasIndexAccess ? (Expression)new BinaryOperatorExpression (id1, BinaryOperatorType.LessThan, new MemberReferenceExpression (inExpression.Clone (), countProperty)) :
new InvocationExpression(new MemberReferenceExpression (id2, "MoveNext")),
EmbeddedStatement = new BlockStatement {
variableDeclarationStatement
}
};
if (hasIndexAccess)
forStatement.Iterators.Add(new UnaryOperatorExpression (UnaryOperatorType.PostIncrement, id2));
if (foreachStatement.EmbeddedStatement is BlockStatement) {
variableDeclarationStatement.Remove();
var oldBlock = (BlockStatement)foreachStatement.EmbeddedStatement.Clone();
if (oldBlock.Statements.Any()) {
oldBlock.Statements.InsertBefore(oldBlock.Statements.First(), variableDeclarationStatement);
} else {
oldBlock.Statements.Add(variableDeclarationStatement);
}
forStatement.EmbeddedStatement = oldBlock;
} else {
forStatement.EmbeddedStatement.AddChild (foreachStatement.EmbeddedStatement.Clone (), BlockStatement.StatementRole);
}
if (declarationStatement != null)
script.InsertBefore (foreachStatement, declarationStatement);
script.Replace (foreachStatement, forStatement);
if (hasIndexAccess) {
script.Link (initializer.Variables.First ().NameToken, id1, id2, id3);
} else {
script.Link (initializer.Variables.First ().NameToken, id1, id2);
}
}, foreachStatement);
if (!hasIndexAccess)
yield break;
yield return new CodeAction(context.TranslateString("Convert 'foreach' loop to optimized 'for'"), script => {
var result = context.Resolve(foreachStatement.InExpression);
var countProperty = GetCountProperty(result.Type);
var initializer = new VariableDeclarationStatement(new PrimitiveType("int"), name, new PrimitiveExpression(0));
var id1 = new IdentifierExpression(name);
var id2 = id1.Clone();
var id3 = id1.Clone();
var inExpression = foreachStatement.InExpression;
Statement declarationStatement = null;
if (inExpression is ObjectCreateExpression || inExpression is ArrayCreateExpression) {
string listName = GetName(state, CollectionNames) ?? "col";
declarationStatement = new VariableDeclarationStatement (
new PrimitiveType ("var"),
listName,
inExpression.Clone ()
);
inExpression = new IdentifierExpression (listName);
}
var variableDeclarationStatement = new VariableDeclarationStatement(
foreachStatement.VariableType.Clone(),
foreachStatement.VariableName,
new IndexerExpression(inExpression.Clone(), id3)
);
string optimizedUpperBound = GetBoundName(inExpression) + countProperty;
initializer.Variables.Add(new VariableInitializer(optimizedUpperBound, new MemberReferenceExpression (inExpression.Clone (), countProperty)));
var forStatement = new ForStatement {
Initializers = { initializer },
Condition = new BinaryOperatorExpression (id1, BinaryOperatorType.LessThan, new IdentifierExpression(optimizedUpperBound)),
Iterators = { new UnaryOperatorExpression (UnaryOperatorType.PostIncrement, id2) },
EmbeddedStatement = new BlockStatement {
variableDeclarationStatement
}
};
if (foreachStatement.EmbeddedStatement is BlockStatement) {
variableDeclarationStatement.Remove();
var oldBlock = (BlockStatement)foreachStatement.EmbeddedStatement.Clone();
if (oldBlock.Statements.Any()) {
oldBlock.Statements.InsertBefore(oldBlock.Statements.First(), variableDeclarationStatement);
} else {
oldBlock.Statements.Add(variableDeclarationStatement);
}
forStatement.EmbeddedStatement = oldBlock;
} else {
forStatement.EmbeddedStatement.AddChild (foreachStatement.EmbeddedStatement.Clone (), BlockStatement.StatementRole);
}
if (declarationStatement != null)
script.InsertBefore (foreachStatement, declarationStatement);
script.Replace (foreachStatement, forStatement);
script.Link (initializer.Variables.First ().NameToken, id1, id2, id3);
}, foreachStatement);
}
static string GetCountProperty(IType type)
{
return type.Kind == TypeKind.Array ? "Length" : "Count";
}
static ForeachStatement GetForeachStatement (RefactoringContext context, out bool hasIndexAccess)
{
var astNode = context.GetNode ();
if (astNode == null) {
hasIndexAccess = false;
return null;
}
var result = (astNode as ForeachStatement) ?? astNode.Parent as ForeachStatement;
if (result == null) {
hasIndexAccess = false;
return null;
}
var collection = context.Resolve (result.InExpression);
hasIndexAccess = collection.Type.Kind == TypeKind.Array || collection.Type.GetProperties(p => p.IsIndexer).Any();
return result;
}
}
}

78
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertHasFlagsToBitwiseFlagComparisonAction.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
//
// ConvertHasFlagsToBitwiseFlagComparisonAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Replace 'Enum.HasFlag' call with bitwise flag comparison", Description = "Replace 'Enum.HasFlag' call with bitwise flag comparison")]
public class ConvertHasFlagsToBitwiseFlagComparisonAction : SpecializedCodeAction<InvocationExpression>
{
protected override CodeAction GetAction(RefactoringContext context, InvocationExpression node)
{
var mRef = node.Target as MemberReferenceExpression;
if (mRef == null)
return null;
var rr = context.Resolve(node) as CSharpInvocationResolveResult;
if (rr == null || rr.IsError)
return null;
if (rr.Member.Name != "HasFlag" || rr.Member.DeclaringType.GetDefinition().KnownTypeCode != ICSharpCode.NRefactory.TypeSystem.KnownTypeCode.Enum)
return null;
var arg = node.Arguments.First ().Clone ();
if (!arg.DescendantsAndSelf.All(x => !(x is BinaryOperatorExpression) || ((BinaryOperatorExpression)x).Operator == BinaryOperatorType.BitwiseOr))
return null;
arg = ConvertBitwiseFlagComparisonToHasFlagsAction.MakeFlatExpression(arg, BinaryOperatorType.BitwiseAnd);
if (arg is BinaryOperatorExpression)
arg = new ParenthesizedExpression(arg);
return new CodeAction(
context.TranslateString("Replace with bitwise flag comparison"),
script => {
var uOp = node.Parent as UnaryOperatorExpression;
if (uOp != null && uOp.Operator == UnaryOperatorType.Not) {
script.Replace(uOp,
new BinaryOperatorExpression(
new ParenthesizedExpression(new BinaryOperatorExpression(mRef.Target.Clone(), BinaryOperatorType.BitwiseAnd, arg)),
BinaryOperatorType.Equality,
new PrimitiveExpression(0)
)
);
} else {
script.Replace(node,
new BinaryOperatorExpression(
new ParenthesizedExpression(new BinaryOperatorExpression(mRef.Target.Clone(), BinaryOperatorType.BitwiseAnd, arg)),
BinaryOperatorType.InEquality,
new PrimitiveExpression(0)
)
);
}
},
node
);
}
}
}

53
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertHexToDecAction.cs

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
//
// ConvertHexToDec.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Convert a hex numer to dec. For example: 0x10 -> 16
/// </summary>
[ContextAction("Convert hex to dec.", Description = "Convert hex to dec.")]
public class ConvertHexToDecAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var pexpr = context.GetNode<PrimitiveExpression>();
if (pexpr == null || !pexpr.LiteralValue.StartsWith("0X", System.StringComparison.OrdinalIgnoreCase)) {
yield break;
}
if (!((pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) ||
(pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte))) {
yield break;
}
yield return new CodeAction(context.TranslateString("Convert to dec"), script => {
script.Replace(pexpr, new PrimitiveExpression (pexpr.Value));
}, pexpr);
}
}
}

89
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToConditionalTernaryExpressionAction.cs

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
//
// ConvertIfStatementToConditionalTernaryExpressionAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert 'if' to '?:'",
Description = "Convert 'if' to '?:'")]
public class ConvertIfStatementToConditionalTernaryExpressionAction : SpecializedCodeAction <IfElseStatement>
{
static readonly AstNode Pattern =
new IfElseStatement(
new AnyNode("condition"),
PatternHelper.EmbeddedStatement (new ExpressionStatement(new NamedNode ("assign1", new AssignmentExpression(new AnyNode("target"), AssignmentOperatorType.Any, new AnyNode("expr1"))))),
PatternHelper.EmbeddedStatement (new ExpressionStatement(new NamedNode ("assign2", new AssignmentExpression(new Backreference("target"), AssignmentOperatorType.Any, new AnyNode("expr2")))))
);
public static bool GetMatch(IfElseStatement ifElseStatement, out Match match)
{
match = ConvertIfStatementToConditionalTernaryExpressionAction.Pattern.Match(ifElseStatement);
if (!match.Success || ifElseStatement.Parent is IfElseStatement)
return false;
var firstAssign = match.Get<AssignmentExpression>("assign1").Single();
var secondAssign = match.Get<AssignmentExpression>("assign2").Single();
return firstAssign.Operator == secondAssign.Operator;
}
static CodeAction CreateAction (BaseRefactoringContext ctx, IfElseStatement ifElseStatement, Match match)
{
var target = match.Get<Expression>("target").Single();
var condition = match.Get<Expression>("condition").Single();
var trueExpr = match.Get<Expression>("expr1").Single();
var falseExpr = match.Get<Expression>("expr2").Single();
var firstAssign = match.Get<AssignmentExpression>("assign1").Single();
return new CodeAction(
ctx.TranslateString("Replace with '?:' expression"),
script => {
script.Replace(
ifElseStatement,
new ExpressionStatement(
new AssignmentExpression(
target.Clone(),
firstAssign.Operator,
new ConditionalExpression(condition.Clone(), trueExpr.Clone(), falseExpr.Clone())
)
)
);
},
ifElseStatement
);
}
protected override CodeAction GetAction(RefactoringContext context, IfElseStatement node)
{
if (!node.IfToken.Contains(context.Location))
return null;
Match match;
if (!GetMatch(node, out match))
return null;
return CreateAction(context, node, match);
}
}
}

165
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToNullCoalescingExpressionAction.cs

@ -0,0 +1,165 @@ @@ -0,0 +1,165 @@
//
// ConvertIfToNullCoalescingAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Convert 'if' to '??' expression",
Category = IssueCategories.Opportunities,
Description = "Convert 'if' statement to '??' expression.")]
public class ConvertIfStatementToNullCoalescingExpressionAction : SpecializedCodeAction <IfElseStatement>
{
const string expressionGroupName = "expression";
const string comparedNodeGroupName = "comparedNode";
const string valueOnNullGroupName = "valueOnNull";
static readonly Expression ActionPattern =
PatternHelper.OptionalParentheses(
new NamedNode(
expressionGroupName,
new Choice {
PatternHelper.CommutativeOperatorWithOptionalParentheses(new AnyNode(comparedNodeGroupName), BinaryOperatorType.Equality, new NullReferenceExpression()),
PatternHelper.CommutativeOperatorWithOptionalParentheses(new AnyNode(comparedNodeGroupName), BinaryOperatorType.InEquality, new NullReferenceExpression())
}
)
);
internal static Expression CheckNode(IfElseStatement node, out Expression rightSide)
{
rightSide = null;
var match = ActionPattern.Match(node.Condition);
if (!match.Success)
return null;
var conditionExpression = match.Get<BinaryOperatorExpression>(expressionGroupName).Single();
bool isEqualityComparison = conditionExpression.Operator == BinaryOperatorType.Equality;
Expression comparedNode = match.Get<Expression>(comparedNodeGroupName).Single();
Statement contentStatement;
if (isEqualityComparison) {
contentStatement = node.TrueStatement;
if (!IsEmpty(node.FalseStatement))
return null;
}
else {
contentStatement = node.FalseStatement;
if (!IsEmpty(node.TrueStatement))
return null;
}
contentStatement = GetSimpleStatement(contentStatement);
if (contentStatement == null)
return null;
var leftExpressionPattern = PatternHelper.OptionalParentheses(comparedNode);
var expressionPattern = new AssignmentExpression(leftExpressionPattern, AssignmentOperatorType.Assign, new AnyNode(valueOnNullGroupName));
var statementPattern = new ExpressionStatement(PatternHelper.OptionalParentheses(expressionPattern));
var statementMatch = statementPattern.Match(contentStatement);
if (!statementMatch.Success)
return null;
rightSide = statementMatch.Get<Expression>(valueOnNullGroupName).Single();
return comparedNode;
}
protected override CodeAction GetAction (RefactoringContext context, IfElseStatement node)
{
if (!node.IfToken.Contains(context.Location))
return null;
Expression rightSide;
var comparedNode = CheckNode(node, out rightSide);
if (comparedNode == null)
return null;
return new CodeAction(context.TranslateString("Replace with '??'"),
script => {
var previousNode = node.GetPrevSibling(sibling => sibling is Statement);
var previousDeclaration = previousNode as VariableDeclarationStatement;
if (previousDeclaration != null && previousDeclaration.Variables.Count() == 1) {
var variable = previousDeclaration.Variables.First();
var comparedNodeIdentifierExpression = comparedNode as IdentifierExpression;
if (comparedNodeIdentifierExpression != null &&
comparedNodeIdentifierExpression.Identifier == variable.Name) {
script.Replace(variable.Initializer, new BinaryOperatorExpression(variable.Initializer.Clone(),
BinaryOperatorType.NullCoalescing,
rightSide.Clone()));
script.Remove(node);
return;
}
}
var previousExpressionStatement = previousNode as ExpressionStatement;
if (previousExpressionStatement != null)
{
var previousAssignment = previousExpressionStatement.Expression as AssignmentExpression;
if (previousAssignment != null &&
comparedNode.IsMatch(previousAssignment.Left)) {
var newExpression = new BinaryOperatorExpression(previousAssignment.Right.Clone(),
BinaryOperatorType.NullCoalescing,
rightSide.Clone());
script.Replace(previousAssignment.Right, newExpression);
script.Remove(node);
return;
}
}
var coalescedExpression = new BinaryOperatorExpression(comparedNode.Clone(),
BinaryOperatorType.NullCoalescing,
rightSide.Clone());
var newAssignment = new ExpressionStatement(new AssignmentExpression(comparedNode.Clone(), coalescedExpression));
script.Replace(node, newAssignment);
}, node);
}
static Statement GetSimpleStatement (Statement statement)
{
BlockStatement blockStatement;
while ((blockStatement = statement as BlockStatement) != null) {
var statements = blockStatement.Descendants.OfType<Statement>()
.Where(descendant => !IsEmpty(descendant)).ToList();
if (statements.Count() != 1) {
return null;
}
statement = statements.First();
}
return statement;
}
static bool IsEmpty (Statement statement)
{
return statement.IsNull ||
!statement.DescendantsAndSelf.OfType<Statement>().Any(descendant => !(descendant is EmptyStatement || descendant is BlockStatement));
}
}
}

115
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToReturnStatementAction.cs

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
//
// ConvertIfStatementToReturnStatementAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert 'if' to 'return'",
Description = "Convert 'if' to 'return'")]
public class ConvertIfStatementToReturnStatementAction : SpecializedCodeAction <IfElseStatement>
{
static readonly AstNode ifElsePattern =
new IfElseStatement(
new AnyNode("condition"),
PatternHelper.EmbeddedStatement (new ReturnStatement(new AnyNode("expr1"))),
PatternHelper.EmbeddedStatement (new ReturnStatement(new AnyNode("expr2")))
);
static readonly AstNode ifPattern =
new IfElseStatement(
new AnyNode("condition"),
PatternHelper.EmbeddedStatement (new ReturnStatement(new AnyNode("expr1")))
);
static readonly AstNode returnPattern =
new ReturnStatement(new AnyNode("expr2"));
public static bool GetMatch(IfElseStatement ifElseStatement, out Expression condition, out Expression expr1, out Expression expr2, out AstNode returnStatement)
{
var match = ifElsePattern.Match(ifElseStatement);
returnStatement = null;
if (match.Success) {
condition = match.Get<Expression>("condition").Single();
expr1 = match.Get<Expression>("expr1").Single();
expr2 = match.Get<Expression>("expr2").Single();
return true;
}
match = ifPattern.Match(ifElseStatement);
if (match.Success) {
returnStatement = ifElseStatement.GetNextSibling(s => s.Role == BlockStatement.StatementRole);
var match2 = returnPattern.Match(returnStatement);
if (match2.Success) {
condition = match.Get<Expression>("condition").Single();
expr1 = match.Get<Expression>("expr1").Single();
expr2 = match2.Get<Expression>("expr2").Single();
return true;
}
}
condition = expr1 = expr2 = null;
return false;
}
static readonly AstNode truePattern = PatternHelper.OptionalParentheses(new PrimitiveExpression (true));
static readonly AstNode falsePattern = PatternHelper.OptionalParentheses(new PrimitiveExpression (false));
static Expression CreateCondition(Expression c, Expression e1, Expression e2)
{
if (truePattern.IsMatch(e1) && falsePattern.IsMatch(e2))
return c.Clone();
return new ConditionalExpression(c.Clone(), e1.Clone(), e2.Clone());
}
protected override CodeAction GetAction(RefactoringContext context, IfElseStatement ifElseStatement)
{
if (!ifElseStatement.IfToken.Contains(context.Location))
return null;
Expression c, e1, e2;
AstNode rs;
if (!ConvertIfStatementToReturnStatementAction.GetMatch(ifElseStatement, out c, out e1, out e2, out rs))
return null;
return new CodeAction (
context.TranslateString("Replace with 'return'"),
script => {
script.Replace(ifElseStatement, new ReturnStatement(
CreateCondition(c, e1, e2)
));
if (rs != null)
script.Remove(rs);
},
ifElseStatement
);
}
}
}

196
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertIfStatementToSwitchStatementAction.cs

@ -0,0 +1,196 @@ @@ -0,0 +1,196 @@
//
// ConvertIfToSwitchAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction (
"Convert 'if' to 'switch'",
Description = "Convert 'if' statement to 'switch' statement")]
public class ConvertIfStatementToSwitchStatementAction : SpecializedCodeAction<IfElseStatement>
{
protected override CodeAction GetAction (RefactoringContext context, IfElseStatement node)
{
if (!node.IfToken.Contains (context.Location))
return null;
var switchExpr = GetSwitchExpression (context, node.Condition);
if (switchExpr == null)
return null;
var switchSections = new List<SwitchSection> ();
if (!CollectSwitchSections (switchSections, context, node, switchExpr))
return null;
return new CodeAction (context.TranslateString ("Convert to 'switch'"),
script =>
{
var switchStatement = new SwitchStatement { Expression = switchExpr.Clone () };
switchStatement.SwitchSections.AddRange (switchSections);
script.Replace (node, switchStatement);
},
node
);
}
internal static Expression GetSwitchExpression (BaseRefactoringContext context, Expression expr)
{
var binaryOp = expr as BinaryOperatorExpression;
if (binaryOp == null)
return null;
if (binaryOp.Operator == BinaryOperatorType.ConditionalOr)
return GetSwitchExpression (context, binaryOp.Left);
if (binaryOp.Operator == BinaryOperatorType.Equality) {
Expression switchExpr = null;
if (IsConstantExpression (context, binaryOp.Right))
switchExpr = binaryOp.Left;
if (IsConstantExpression (context, binaryOp.Left))
switchExpr = binaryOp.Right;
if (switchExpr != null && IsValidSwitchType (context.Resolve (switchExpr).Type))
return switchExpr;
}
return null;
}
static bool IsConstantExpression (BaseRefactoringContext context, Expression expr)
{
if (expr is PrimitiveExpression || expr is NullReferenceExpression)
return true;
return context.Resolve (expr).IsCompileTimeConstant;
}
static readonly KnownTypeCode [] validTypes =
{
KnownTypeCode.String, KnownTypeCode.Boolean, KnownTypeCode.Char,
KnownTypeCode.Byte, KnownTypeCode.SByte,
KnownTypeCode.Int16, KnownTypeCode.Int32, KnownTypeCode.Int64,
KnownTypeCode.UInt16, KnownTypeCode.UInt32, KnownTypeCode.UInt64
};
static bool IsValidSwitchType (IType type)
{
if (type.Kind == TypeKind.Enum)
return true;
var typeDefinition = type.GetDefinition ();
if (typeDefinition == null)
return false;
if (typeDefinition.KnownTypeCode == KnownTypeCode.NullableOfT) {
var nullableType = (ParameterizedType)type;
typeDefinition = nullableType.TypeArguments [0].GetDefinition ();
if (typeDefinition == null)
return false;
}
return Array.IndexOf (validTypes, typeDefinition.KnownTypeCode) != -1;
}
internal static bool CollectSwitchSections (ICollection<SwitchSection> result, BaseRefactoringContext context,
IfElseStatement ifStatement, Expression switchExpr)
{
// if
var section = new SwitchSection ();
if (!CollectCaseLabels (section.CaseLabels, context, ifStatement.Condition, switchExpr))
return false;
CollectSwitchSectionStatements (section.Statements, context, ifStatement.TrueStatement);
result.Add (section);
if (ifStatement.TrueStatement.Descendants.Any(n => n is BreakStatement))
return false;
if (ifStatement.FalseStatement.IsNull)
return true;
// else if
var falseStatement = ifStatement.FalseStatement as IfElseStatement;
if (falseStatement != null)
return CollectSwitchSections (result, context, falseStatement, switchExpr);
if (ifStatement.FalseStatement.Descendants.Any(n => n is BreakStatement))
return false;
// else (default label)
var defaultSection = new SwitchSection ();
defaultSection.CaseLabels.Add (new CaseLabel ());
CollectSwitchSectionStatements (defaultSection.Statements, context, ifStatement.FalseStatement);
result.Add (defaultSection);
return true;
}
static bool CollectCaseLabels (AstNodeCollection<CaseLabel> result, BaseRefactoringContext context,
Expression condition, Expression switchExpr)
{
if (condition is ParenthesizedExpression)
return CollectCaseLabels (result, context, ((ParenthesizedExpression)condition).Expression, switchExpr);
var binaryOp = condition as BinaryOperatorExpression;
if (binaryOp == null)
return false;
if (binaryOp.Operator == BinaryOperatorType.ConditionalOr)
return CollectCaseLabels (result, context, binaryOp.Left, switchExpr) &&
CollectCaseLabels (result, context, binaryOp.Right, switchExpr);
if (binaryOp.Operator == BinaryOperatorType.Equality) {
if (switchExpr.Match (binaryOp.Left).Success) {
if (IsConstantExpression (context, binaryOp.Right)) {
result.Add (new CaseLabel (binaryOp.Right.Clone ()));
return true;
}
} else if (switchExpr.Match (binaryOp.Right).Success) {
if (IsConstantExpression (context, binaryOp.Left)) {
result.Add (new CaseLabel (binaryOp.Left.Clone ()));
return true;
}
}
}
return false;
}
static void CollectSwitchSectionStatements (AstNodeCollection<Statement> result, BaseRefactoringContext context,
Statement statement)
{
BlockStatement blockStatement = statement as BlockStatement;
if (blockStatement != null)
result.AddRange(blockStatement.Statements.Select(s => s.Clone()));
else
result.Add(statement.Clone());
// add 'break;' at end if necessary
var reachabilityAnalysis = context.CreateReachabilityAnalysis (statement);
if (reachabilityAnalysis.IsEndpointReachable(statement))
result.Add(new BreakStatement());
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertImplicitToExplicitImplementationAction.cs

63
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaBodyExpressionToStatementAction.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
//
// ConvertLambdaBodyExpressionToStatementAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Converts expression of lambda body to statement",
Description = "Converts expression of lambda body to statement")]
public class ConvertLambdaBodyExpressionToStatementAction : SpecializedCodeAction<LambdaExpression>
{
protected override CodeAction GetAction (RefactoringContext context, LambdaExpression node)
{
if (!node.ArrowToken.Contains (context.Location))
return null;
var bodyExpr = node.Body as Expression;
if (bodyExpr == null)
return null;
return new CodeAction (context.TranslateString ("Convert to lambda statement"),
script =>
{
var body = new BlockStatement ();
if (RequireReturnStatement (context, node)) {
body.Add (new ReturnStatement (bodyExpr.Clone ()));
} else {
body.Add (bodyExpr.Clone ());
}
script.Replace (bodyExpr, body);
},
node
);
}
static bool RequireReturnStatement (RefactoringContext context, LambdaExpression lambda)
{
var type = LambdaHelper.GetLambdaReturnType (context, lambda);
return type != null && type.ReflectionName != "System.Void";
}
}
}

74
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaBodyStatementToExpressionAction.cs

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
//
// ConvertLambdaBodyStatementToExpressionAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Converts statement of lambda body to expression",
Description = "Converts statement of lambda body to expression")]
public class ConvertLambdaBodyStatementToExpressionAction : SpecializedCodeAction<LambdaExpression>
{
internal static bool TryGetConvertableExpression(AstNode body, out BlockStatement blockStatement, out Expression expr)
{
expr = null;
blockStatement = body as BlockStatement;
if (blockStatement == null || blockStatement.Statements.Count > 1)
return false;
var returnStatement = blockStatement.Statements.FirstOrNullObject() as ReturnStatement;
if (returnStatement != null) {
expr = returnStatement.Expression;
} else {
var exprStatement = blockStatement.Statements.FirstOrNullObject() as ExpressionStatement;
if (exprStatement == null)
return false;
expr = exprStatement.Expression;
}
return true;
}
internal static CodeAction CreateAction (BaseRefactoringContext context, AstNode node, BlockStatement blockStatement, Expression expr)
{
return new CodeAction (
context.TranslateString ("Convert to lambda expression"),
script => script.Replace (blockStatement, expr.Clone ()),
node
);
}
protected override CodeAction GetAction (RefactoringContext context, LambdaExpression node)
{
if (!node.ArrowToken.Contains (context.Location))
return null;
BlockStatement blockStatement;
Expression expr;
if (!TryGetConvertableExpression(node.Body, out blockStatement, out expr))
return null;
return CreateAction (context, node.ArrowToken, blockStatement, expr);
}
}
}

99
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertLambdaToAnonymousDelegateAction.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
//
// ConvertLambdaToDelegateAction.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert lambda to anonymous delegate",
Description = "Converts a lambda to an anonymous delegate.")]
public class ConvertLambdaToAnonymousDelegateAction : SpecializedCodeAction<LambdaExpression>
{
#region implemented abstract members of SpecializedCodeAction
protected override CodeAction GetAction(RefactoringContext context, LambdaExpression node)
{
if (context.Location < node.StartLocation || context.Location >= node.Body.StartLocation)
return null;
var lambdaResolveResult = context.Resolve(node) as LambdaResolveResult;
if (lambdaResolveResult == null)
return null;
return new CodeAction(context.TranslateString("Convert to anonymous delegate"), script => {
BlockStatement newBody;
if (node.Body is BlockStatement) {
newBody = (BlockStatement)node.Body.Clone();
} else {
var expression = (Expression)node.Body.Clone();
Statement statement;
if (RequireReturnStatement(context, node)) {
statement = new ReturnStatement(expression);
}
else {
statement = expression;
}
newBody = new BlockStatement {
Statements = {
statement
}
};
}
var method = new AnonymousMethodExpression (newBody, GetParameters(lambdaResolveResult.Parameters, context));
script.Replace(node, method);
}, node);
}
#endregion
IEnumerable<ParameterDeclaration> GetParameters(IList<IParameter> parameters, RefactoringContext context)
{
if (parameters == null || parameters.Count == 0)
return null;
var result = new List<ParameterDeclaration> ();
foreach (var parameter in parameters) {
var type = context.CreateShortType(parameter.Type);
var name = parameter.Name;
ParameterModifier modifier = ParameterModifier.None;
if (parameter.IsRef)
modifier |= ParameterModifier.Ref;
if (parameter.IsOut)
modifier |= ParameterModifier.Out;
result.Add (new ParameterDeclaration(type, name, modifier));
}
return result;
}
static bool RequireReturnStatement (RefactoringContext context, LambdaExpression lambda)
{
var type = LambdaHelper.GetLambdaReturnType (context, lambda);
return type != null && type.ReflectionName != "System.Void";
}
}
}

78
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMethodGroupToAnonymousMethodAction.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
//
// ConvertMethodGroupToAnonymousMethodAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert method group to anoymous method",
Description = "Convert method group to anoymous method")]
public class ConvertMethodGroupToAnonymousMethodAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
Expression node = context.GetNode<IdentifierExpression>();
if (node == null) {
var mr = context.GetNode<MemberReferenceExpression>();
if (mr == null || !mr.MemberNameToken.IsInside(context.Location))
yield break;
node = mr;
}
if (node == null)
yield break;
var rr = context.Resolve(node) as MethodGroupResolveResult;
if (rr == null || rr.IsError)
yield break;
var type = TypeGuessing.GetValidTypes(context.Resolver, node).FirstOrDefault(t => t.Kind == TypeKind.Delegate);
if (type == null)
yield break;
var invocationMethod = type.GetDelegateInvokeMethod();
if (invocationMethod == null)
yield break;
yield return new CodeAction(
context.TranslateString("Convert to anonymous method"),
script => {
var expr = new InvocationExpression(node.Clone(), invocationMethod.Parameters.Select(p => new IdentifierExpression(context.GetNameProposal(p.Name))));
var stmt = invocationMethod.ReturnType.IsKnownType(KnownTypeCode.Void) ? (Statement)expr : new ReturnStatement(expr);
var anonymousMethod = new AnonymousMethodExpression {
Body = new BlockStatement { stmt }
};
foreach (var p in invocationMethod.Parameters) {
var decl = new ParameterDeclaration(context.CreateShortType(p.Type), context.GetNameProposal(p.Name));
anonymousMethod.Parameters.Add(decl);
}
script.Replace(node, anonymousMethod);
},
node
);
}
}
}

77
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMethodGroupToLambdaAction.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
//
// ConvertMethodGroupToLambdaAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert method group to lambda expression",
Description = "Convert method group to lambda expression")]
public class ConvertMethodGroupToLambdaAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
Expression node = context.GetNode<IdentifierExpression>();
if (node == null) {
var mr = context.GetNode<MemberReferenceExpression>();
if (mr == null || !mr.MemberNameToken.IsInside(context.Location))
yield break;
node = mr;
}
if (node == null)
yield break;
var rr = context.Resolve(node) as MethodGroupResolveResult;
if (rr == null || rr.IsError)
yield break;
var type = TypeGuessing.GetValidTypes(context.Resolver, node).FirstOrDefault(t => t.Kind == TypeKind.Delegate);
if (type == null)
yield break;
var invocationMethod = type.GetDelegateInvokeMethod();
if (invocationMethod == null)
yield break;
yield return new CodeAction(
context.TranslateString("Convert to lambda expression"),
script => {
var invocation = new InvocationExpression(node.Clone(), invocationMethod.Parameters.Select(p => new IdentifierExpression(context.GetNameProposal(p.Name))));
var lambda = new LambdaExpression {
Body = invocation
};
lambda.Parameters.AddRange(
invocation.Arguments
.Cast<IdentifierExpression>()
.Select(p => new ParameterDeclaration { Name = p.Identifier })
);
script.Replace(node, lambda);
},
node
);
}
}
}

67
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertMultiplyToShiftAction.cs

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
//
// ConvertMultiplyToShiftAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert '*'/'/' to '<<'/'>>'",
Description = "Convert '*'/'/' to '<<'/'>>'")]
public class ConvertMultiplyToShiftAction : SpecializedCodeAction<BinaryOperatorExpression>
{
protected override CodeAction GetAction(RefactoringContext context, BinaryOperatorExpression node)
{
if (!node.OperatorToken.Contains(context.Location))
return null;
if (node.Operator != BinaryOperatorType.Multiply && node.Operator != BinaryOperatorType.Divide || !(node.Right is PrimitiveExpression))
return null;
var valueObj = context.Resolve(node.Right).ConstantValue;
if (!(valueObj is int))
return null;
var value = (int)valueObj;
var log2 = (int)Math.Log(value, 2);
if (value != 1 << log2)
return null;
return new CodeAction (
node.Operator == BinaryOperatorType.Multiply ? context.TranslateString("Replace with '<<'") : context.TranslateString("Replace with '>>'"),
script => script.Replace(
node,
new BinaryOperatorExpression(
node.Left.Clone(),
node.Operator == BinaryOperatorType.Multiply ? BinaryOperatorType.ShiftLeft : BinaryOperatorType.ShiftRight,
new PrimitiveExpression(log2)
)
),
node.OperatorToken
);
}
}
}

54
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertNullCoalescingToConditionalExpressionAction.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
//
// ConvertNullCoalescingToConditionalExpressionAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert '??' to '?:'",
Description = "Convert '??' to '?:'")]
public class ConvertNullCoalescingToConditionalExpressionAction : SpecializedCodeAction<BinaryOperatorExpression>
{
protected override CodeAction GetAction(RefactoringContext ctx, BinaryOperatorExpression node)
{
if (node.Operator != BinaryOperatorType.NullCoalescing || !node.OperatorToken.Contains(ctx.Location))
return null;
return new CodeAction(
ctx.TranslateString("Replace with '?:' expression"),
script => {
Expression expr = new ConditionalExpression (
new BinaryOperatorExpression(node.Left.Clone(), BinaryOperatorType.InEquality, new NullReferenceExpression ()),
node.Left.Clone(),
node.Right.Clone()
);
script.Replace(node, expr);
},
node
);
}
}
}

78
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertReturnStatementToIfAction.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
//
// ConvertReturnStatementToIfAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert 'return' to 'if'",
Description = "Convert 'return' to 'if'")]
public class ConvertReturnStatementToIfAction : SpecializedCodeAction <ReturnStatement>
{
protected override CodeAction GetAction(RefactoringContext context, ReturnStatement node)
{
if (!node.ReturnToken.Contains(context.Location))
return null;
if (node.Expression is ConditionalExpression)
return CreateForConditionalExpression(context, node, (ConditionalExpression)node.Expression);
var bOp = node.Expression as BinaryOperatorExpression;
if (bOp != null && bOp.Operator == BinaryOperatorType.NullCoalescing)
return CreateForNullCoalesingExpression(context, node, bOp);
return null;
}
CodeAction CreateForConditionalExpression(RefactoringContext ctx, ReturnStatement node, ConditionalExpression conditionalExpression)
{
return new CodeAction (
ctx.TranslateString("Replace with 'if' statement"),
script => {
var ifStatement = new IfElseStatement(conditionalExpression.Condition.Clone(), new ReturnStatement(conditionalExpression.TrueExpression.Clone()));
script.Replace(node, ifStatement);
script.InsertAfter(ifStatement, new ReturnStatement(conditionalExpression.FalseExpression.Clone()));
},
node
);
}
CodeAction CreateForNullCoalesingExpression(RefactoringContext ctx, ReturnStatement node, BinaryOperatorExpression bOp)
{
return new CodeAction (
ctx.TranslateString("Replace with 'if' statement"),
script => {
var ifStatement = new IfElseStatement(new BinaryOperatorExpression(bOp.Left.Clone(), BinaryOperatorType.InEquality, new NullReferenceExpression()), new ReturnStatement(bOp.Left.Clone()));
script.Replace(node, ifStatement);
script.InsertAfter(ifStatement, new ReturnStatement(bOp.Right.Clone()));
},
node
);
}
}
}

61
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertShiftToMultiplyAction.cs

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
//
// ConvertShiftToMultiplyAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert '<<'/'>>' to '*'/'/'",
Description = "Convert '<<'/'>>' to '*'/'/'")]
public class ConvertShiftToMultiplyAction : SpecializedCodeAction <BinaryOperatorExpression>
{
protected override CodeAction GetAction(RefactoringContext context, BinaryOperatorExpression node)
{
if (!node.OperatorToken.Contains(context.Location))
return null;
if (node.Operator != BinaryOperatorType.ShiftLeft && node.Operator != BinaryOperatorType.ShiftRight || !(node.Right is PrimitiveExpression))
return null;
var value = context.Resolve(node.Right).ConstantValue;
if (!(value is int))
return null;
return new CodeAction (
node.Operator == BinaryOperatorType.ShiftLeft ? context.TranslateString("Replace with '*'") : context.TranslateString("Replace with '/'"),
script => script.Replace(
node,
new BinaryOperatorExpression(
node.Left.Clone(),
node.Operator == BinaryOperatorType.ShiftLeft ? BinaryOperatorType.Multiply : BinaryOperatorType.Divide,
new PrimitiveExpression(1 << (int)value)
)
),
node.OperatorToken
);
}
}
}

147
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertSwitchToIfAction.cs

@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
//
// ConvertSwitchToIfAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Convert 'switch' to 'if'", Description = "Convert 'switch' statement to 'if' statement")]
public class ConvertSwitchToIfAction : SpecializedCodeAction<SwitchStatement>
{
static readonly InsertParenthesesVisitor insertParenthesesVisitor = new InsertParenthesesVisitor ();
protected override CodeAction GetAction (RefactoringContext context, SwitchStatement node)
{
if (!node.SwitchToken.Contains (context.Location))
return null;
// empty switch
if (node.SwitchSections.Count == 0)
return null;
// switch with default only
if (node.SwitchSections.First ().CaseLabels.Any (label => label.Expression.IsNull))
return null;
// check non-trailing breaks
foreach (var switchSection in node.SwitchSections) {
var lastStatement = switchSection.Statements.LastOrDefault ();
var finder = new NonTrailingBreakFinder (lastStatement as BreakStatement);
if (switchSection.AcceptVisitor (finder))
return null;
}
return new CodeAction (context.TranslateString ("Convert to 'if'"),
script =>
{
IfElseStatement ifStatement = null;
IfElseStatement currentStatement = null;
foreach (var switchSection in node.SwitchSections) {
var condition = CollectCondition (node.Expression, switchSection.CaseLabels);
var bodyStatement = new BlockStatement ();
var lastStatement = switchSection.Statements.LastOrDefault ();
foreach (var statement in switchSection.Statements) {
// skip trailing break
if (statement == lastStatement && statement is BreakStatement)
continue;
bodyStatement.Add (statement.Clone ());
}
// default -> else
if (condition == null) {
currentStatement.FalseStatement = bodyStatement;
break;
}
var elseIfStatement = new IfElseStatement (condition, bodyStatement);
if (ifStatement == null)
ifStatement = elseIfStatement;
else
currentStatement.FalseStatement = elseIfStatement;
currentStatement = elseIfStatement;
}
script.Replace (node, ifStatement);
script.FormatText (ifStatement);
}, node);
}
static Expression CollectCondition(Expression switchExpr, AstNodeCollection<CaseLabel> caseLabels)
{
// default
if (caseLabels.Count == 0 || caseLabels.Any (label => label.Expression.IsNull))
return null;
var conditionList = caseLabels.Select (
label => new BinaryOperatorExpression (switchExpr.Clone (), BinaryOperatorType.Equality, label.Expression.Clone ()))
.ToArray ();
// insert necessary parentheses
foreach (var expr in conditionList)
expr.AcceptVisitor (insertParenthesesVisitor);
if (conditionList.Length == 1)
return conditionList [0];
// combine case labels into an conditional or expression
BinaryOperatorExpression condition = null;
BinaryOperatorExpression currentCondition = null;
for (int i = 0; i < conditionList.Length - 1; i++) {
var newCondition = new BinaryOperatorExpression
{
Operator = BinaryOperatorType.ConditionalOr,
Left = conditionList[i]
};
if (currentCondition == null)
condition = newCondition;
else
currentCondition.Right = newCondition;
currentCondition = newCondition;
}
currentCondition.Right = conditionList [conditionList.Length - 1];
return condition;
}
class NonTrailingBreakFinder : DepthFirstAstVisitor<bool>
{
BreakStatement trailingBreakStatement;
public NonTrailingBreakFinder (BreakStatement trailingBreak)
{
trailingBreakStatement = trailingBreak;
}
protected override bool VisitChildren (AstNode node)
{
return node.Children.Any (child => child.AcceptVisitor (this));
}
public override bool VisitBreakStatement (BreakStatement breakStatement)
{
return breakStatement != trailingBreakStatement;
}
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/AccessPath.cs

207
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/ConvertInitializerToExplicitInitializationsAction.cs

@ -0,0 +1,207 @@ @@ -0,0 +1,207 @@
//
// ConvertInitializerToExplicitInitializationsAction.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert to explicit initializers",
Description = "Converts an object or collection initializer to explicit initializations.")]
public class ConvertInitializerToExplicitInitializationsAction : CodeActionProvider
{
#region ICodeActionProvider implementation
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var codeAction = GetActionForVariableInitializer(context);
if (codeAction != null) {
yield return codeAction;
yield break;
}
codeAction = GetActionForAssignmentExpression(context);
if (codeAction != null) {
yield return codeAction;
yield break;
}
}
public CodeAction GetActionForVariableInitializer(RefactoringContext context)
{
var variableInitializer = context.GetNode<VariableInitializer>();
if (variableInitializer == null)
return null;
var declaration = variableInitializer.Parent as VariableDeclarationStatement;
if (declaration == null)
return null;
if (variableInitializer.Initializer.IsNull)
return null;
var objectCreateExpression = variableInitializer.Initializer as ObjectCreateExpression;
if (objectCreateExpression == null)
return null;
var converter = new InitializerConversionVisitor(context);
Expression finalExpression;
var statements = converter.ConvertInitializer(objectCreateExpression, out finalExpression);
if (statements.Count > 0) {
return new CodeAction(context.TranslateString("Convert to explicit initializers"), script => {
foreach (var statement in statements) {
script.InsertBefore(declaration, statement);
}
script.Replace(variableInitializer.Initializer, finalExpression);
}, variableInitializer);
}
return null;
}
public CodeAction GetActionForAssignmentExpression(RefactoringContext context)
{
var assignmentExpression = context.GetNode<AssignmentExpression>();
if (assignmentExpression == null)
return null;
var expressionStatement = assignmentExpression.Parent as ExpressionStatement;
if (expressionStatement == null)
return null;
var objectCreateExpression = assignmentExpression.Right as ObjectCreateExpression;
if (objectCreateExpression == null)
return null;
var converter = new InitializerConversionVisitor(context);
Expression finalExpression;
var statements = converter.ConvertInitializer(objectCreateExpression, out finalExpression);
if (statements.Count > 0) {
return new CodeAction(context.TranslateString("Convert to explicit initializers"), script => {
foreach (var statement in statements) {
script.InsertBefore(expressionStatement, statement);
}
script.Replace(assignmentExpression.Right, finalExpression);
}, assignmentExpression);
}
return null;
}
#endregion
class InitializerConversionVisitor : DepthFirstAstVisitor<Expression, Expression>
{
RefactoringContext context;
IList<Statement> statements;
NamingHelper namingHelper;
public InitializerConversionVisitor(RefactoringContext context)
{
this.context = context;
namingHelper = new NamingHelper(context);
}
AstType GetDeclarationType(AstType type)
{
AstType declarationType;
if (context.UseExplicitTypes) {
declarationType = type.Clone();
} else {
declarationType = new SimpleType("var");
}
return declarationType;
}
public IList<Statement> ConvertInitializer(ObjectCreateExpression initializer, out Expression finalExpression)
{
statements = new List<Statement>();
finalExpression = initializer.AcceptVisitor(this, null);
return statements;
}
public override Expression VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, Expression data)
{
var creationType = objectCreateExpression.Type.Clone();
var parameters = objectCreateExpression.Arguments.Select(arg => arg.Clone());
var newCreation = new ObjectCreateExpression(creationType, parameters);
if (objectCreateExpression.Initializer.IsNull) {
return newCreation;
} else {
AstType declarationType = GetDeclarationType(objectCreateExpression.Type);
var name = namingHelper.GenerateVariableName(objectCreateExpression.Type);
var variableInitializer = new VariableDeclarationStatement(declarationType, name, newCreation);
statements.Add(variableInitializer);
var identifier = new IdentifierExpression(name);
base.VisitObjectCreateExpression(objectCreateExpression, identifier);
return identifier;
}
}
public override Expression VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, Expression data)
{
if (!(arrayInitializerExpression.Parent is ArrayInitializerExpression)) {
return base.VisitArrayInitializerExpression(arrayInitializerExpression, data);
}
// this a tuple in a collection initializer
var arguments = arrayInitializerExpression.Elements.Select(element => element.AcceptVisitor(this, null).Clone());
var method = new MemberReferenceExpression {
Target = data.Clone(),
MemberName = "Add"
};
statements.Add(new InvocationExpression(method, arguments));
return null;
}
public override Expression VisitNamedExpression(NamedExpression namedExpression, Expression data)
{
var member = new MemberReferenceExpression {
Target = data.Clone(),
MemberName = namedExpression.Name
};
var expression = namedExpression.Expression.AcceptVisitor(this, member);
if (expression != null) {
var statement = new ExpressionStatement {
Expression = new AssignmentExpression {
Left = member,
Right = expression.Clone()
}
};
statements.Add(statement);
}
return null;
}
protected override Expression VisitChildren(AstNode node, Expression data)
{
// Most expressions should just be used as-is, and
// a) need not be visited
// b) only return themselves
if (node is Expression && !(node is ObjectCreateExpression || node is ArrayInitializerExpression || node is NamedExpression)){
return (Expression)node;
}
return base.VisitChildren(node, data);
}
}
}
}

109
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/ConvertToInitializerAction.cs

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
//
// ConvertToInitializerAction.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Convert to initializer",
Description = "Converts a set of assignments and .Add() calls to an initializer.")]
public class ConvertToInitializerAction : CodeActionProvider
{
#region ICodeActionProvider implementation
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var initializer = context.GetNode<VariableInitializer>();
if (initializer != null) {
var action = HandleInitializer(context, initializer);
if (action != null)
yield return action;
}
var expressionStatement = context.GetNode<ExpressionStatement>();
if (expressionStatement != null) {
var action = HandleExpressionStatement(context, expressionStatement);
if (action != null)
yield return action;
}
}
CodeAction HandleInitializer(RefactoringContext context, VariableInitializer initializer)
{
var objectCreateExpression = initializer.Initializer as ObjectCreateExpression;
if (objectCreateExpression == null)
return null;
var initializerRR = context.Resolve(initializer) as LocalResolveResult;
if (initializerRR == null)
return null;
IList<AstNode> statements = GetNodes(context.GetNode<Statement>());
var converter = new StatementsToInitializerConverter(context);
var newInitializer = converter.ConvertToInitializer(initializer, ref statements);
if (newInitializer == null || statements.Count == 0)
return null;
return MakeAction(context, initializer, newInitializer, statements);
}
CodeAction HandleExpressionStatement(RefactoringContext context, ExpressionStatement expressionStatement)
{
var expression = expressionStatement.Expression as AssignmentExpression;
if (expression == null || expression.Operator != AssignmentOperatorType.Assign)
return null;
if (!(expression.Right is ObjectCreateExpression))
return null;
var expressionResolveResult = context.Resolve(expression.Left);
if (!(expressionResolveResult is LocalResolveResult) && !(expressionResolveResult is MemberResolveResult))
return null;
IList<AstNode> statements = GetNodes(context.GetNode<Statement>());
var converter = new StatementsToInitializerConverter(context);
var newExpression = converter.ConvertToInitializer(expression, ref statements);
if (newExpression == null || statements.Count == 0)
return null;
return MakeAction(context, expression, newExpression, statements);
}
List<AstNode> GetNodes(Statement startStatement)
{
var statements = new List<AstNode>();
AstNode currentNode = startStatement.NextSibling;
while (currentNode != null) {
if (currentNode is Statement || currentNode is Comment)
statements.Add(currentNode);
currentNode = currentNode.NextSibling;
}
return statements;
}
CodeAction MakeAction(RefactoringContext context, AstNode oldNode, AstNode replacementNode, IEnumerable<AstNode> toRemove)
{
return new CodeAction(context.TranslateString("Convert to initializer"), script => {
foreach (var statement in toRemove)
script.Remove(statement);
script.Replace(oldNode, replacementNode);
}, oldNode);
}
#endregion
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertToInitializer/StatementsToInitializerConverter.cs

60
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ConvertWhileToDoWhileLoopAction.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
//
// ConvertWhileToDoWhileLoopAction.cs
//
// Author:
// Luís Reis <luiscubal@gmail.com>
//
// Copyright (c) 2013 Luís Reis
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Converts a while loop to a do...while loop.
/// For instance: while (foo) {} becomes do { } while (foo);
/// </summary>
[ContextAction("Convert while loop to do...while", Description = "Convert while loop to do...while (changing semantics)")]
public class ConvertWhileToDoWhileLoopAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var whileLoop = context.GetNode<WhileStatement>();
if (whileLoop == null || !whileLoop.WhileToken.Contains(context.Location)) {
yield break;
}
yield return new CodeAction(context.TranslateString("Convert to do...while loop"),
script => ApplyAction(script, whileLoop),
whileLoop.WhileToken);
}
void ApplyAction(Script script, WhileStatement statement) {
var doWhile = new DoWhileStatement {
Condition = statement.Condition.Clone(),
EmbeddedStatement = statement.EmbeddedStatement.Clone()
};
script.Replace(statement, doWhile);
}
}
}

69
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CopyCommentsFromBase.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
//
// CopyCommentsFromBase.cs
//
// Author:
// Ji Kun <jikun.nus0@gmail.com>
//
// Copyright (c) 2013 Ji Kun <jikun.nus@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Copies documented comments from base to overriding methods.
/// </summary>
using System;
using System.Collections.Generic;
[ContextAction("Copy comments from base", Description = "Copies documented comments from base to overriding methods.")]
public class CopyCommentsFromBase: SpecializedCodeAction <MethodDeclaration>
{
protected override CodeAction GetAction(RefactoringContext context, MethodDeclaration node)
{
if (node == null || !node.HasModifier(Modifiers.Override))
return null;
if (!node.NameToken.Contains(context.Location))
return null;
IMethod resolvedMember = (IMethod)(context.Resolve(node) as MemberResolveResult).Member;
if (resolvedMember == null)
return null;
IMethod originalMember = (IMethod)InheritanceHelper.GetBaseMember(resolvedMember);
if (originalMember == null || originalMember.Documentation == null)
return null;
string comments = originalMember.Documentation.ToString();
if (string.IsNullOrEmpty(comments))
return null;
string[] lines = comments.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
return new CodeAction(context.TranslateString("Copy comments from base"), script => {
foreach (string co in lines) {
script.InsertBefore(node, new Comment(co, CommentType.Documentation));
}
}, node.NameToken);
}
}
}

82
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CopyCommentsFromInterface.cs

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
//
// CopyCommentsFromInterface.cs
//
// Author:
// Ji Kun <jikun.nus@gmail.com>
//
// Copyright (c) 2013 Ji Kun <jikun.nus@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
/// <summary>
/// Copies documented comments from interface to overriding methods.
/// </summary>
using System;
using System.Collections.Generic;
using System.Linq;
[ContextAction("Copy comments from interface", Description = "Copies documented comments from interface to implementing methods.")]
public class CopyCommentsFromInterface: SpecializedCodeAction <MethodDeclaration>
{
protected override CodeAction GetAction(RefactoringContext context, MethodDeclaration node)
{
if (!(node.PrivateImplementationType.IsNull))
return null;
if (!node.NameToken.Contains(context.Location))
return null;
var method = (IMethod)((MemberResolveResult)context.Resolve(node)).Member;
if (method.Documentation != null)
return null;
IList<IMember> interfaceMethods = method.ImplementedInterfaceMembers;
if (interfaceMethods.Count != 1 || method.DeclaringType.Kind == TypeKind.Interface)
return null;
var interfaceMethod = interfaceMethods.SingleOrDefault();
if (interfaceMethod == null)
return null;
if (interfaceMethod.Documentation == null)
return null;
string comments = interfaceMethod.Documentation.ToString();
if (comments == "")
return null;
string[] lines = comments.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
return new CodeAction(context.TranslateString("Copy comments from interface"), script =>
{
foreach (string co in lines) {
script.InsertBefore(node, new Comment(co, CommentType.Documentation));
}
}, node);
}
}
}

80
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateBackingStoreAction.cs

@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
//
// CreateBackingStore.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create backing store for auto property", Description = "Creates a backing field for an auto property.")]
public class CreateBackingStoreAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var property = context.GetNode<PropertyDeclaration>();
if (property == null || !property.NameToken.Contains(context.Location))
yield break;
if (!(!property.Getter.IsNull && !property.Setter.IsNull && // automatic properties always need getter & setter
property.Getter.Body.IsNull &&
property.Setter.Body.IsNull)) {
yield break;
}
yield return new CodeAction(context.TranslateString("Create backing store"), script => {
string backingStoreName = context.GetNameProposal (property.Name);
// create field
var backingStore = new FieldDeclaration ();
if (property.Modifiers.HasFlag (Modifiers.Static))
backingStore.Modifiers |= Modifiers.Static;
backingStore.ReturnType = property.ReturnType.Clone ();
var initializer = new VariableInitializer (backingStoreName);
backingStore.Variables.Add (initializer);
// create new property & implement the get/set bodies
var newProperty = (PropertyDeclaration)property.Clone ();
Expression id1;
if (backingStoreName == "value")
id1 = new ThisReferenceExpression().Member("value");
else
id1 = new IdentifierExpression (backingStoreName);
Expression id2 = id1.Clone();
newProperty.Getter.Body = new BlockStatement () {
new ReturnStatement (id1)
};
newProperty.Setter.Body = new BlockStatement () {
new AssignmentExpression (id2, AssignmentOperatorType.Assign, new IdentifierExpression ("value"))
};
script.Replace (property, newProperty);
script.InsertBefore (property, backingStore);
script.Link (initializer, id1, id2);
}, property.NameToken);
}
}
}

86
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateChangedEventAction.cs

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
//
// CreateChangedEvent.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create changed event for property", Description = "Creates a changed event for an property.")]
public class CreateChangedEventAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var property = context.GetNode<PropertyDeclaration>();
if (property == null || !property.NameToken.Contains(context.Location))
yield break;
var field = RemoveBackingStoreAction.GetBackingField(context, property);
if (field == null)
yield break;
var resolvedType = ReflectionHelper.ParseReflectionName ("System.EventHandler").Resolve (context.Compilation);
if (resolvedType == null)
yield break;
var type = (TypeDeclaration)property.Parent;
yield return new CodeAction(context.TranslateString("Create changed event"), script => {
var eventDeclaration = CreateChangedEventDeclaration (context, property);
var methodDeclaration = CreateEventInvocatorAction.CreateEventInvocator (context, type, eventDeclaration, eventDeclaration.Variables.First (), resolvedType.GetDelegateInvokeMethod (), false);
var stmt = new ExpressionStatement (new InvocationExpression (
new IdentifierExpression (methodDeclaration.Name),
new MemberReferenceExpression (context.CreateShortType("System", "EventArgs"), "Empty")
));
script.InsertWithCursor(
context.TranslateString("Create event invocator"),
Script.InsertPosition.After,
new AstNode[] { eventDeclaration, methodDeclaration }
).ContinueScript(delegate {
script.InsertBefore (property.Setter.Body.RBraceToken, stmt);
script.FormatText (stmt);
});
}, property.NameToken);
}
EventDeclaration CreateChangedEventDeclaration (RefactoringContext context, PropertyDeclaration propertyDeclaration)
{
return new EventDeclaration {
Modifiers = propertyDeclaration.HasModifier (Modifiers.Static) ? Modifiers.Public | Modifiers.Static : Modifiers.Public,
ReturnType = context.CreateShortType("System", "EventHandler"),
Variables = {
new VariableInitializer {
Name = propertyDeclaration.Name + "Changed"
}
}
};
}
}
}

330
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateClassDeclarationAction.cs

@ -0,0 +1,330 @@ @@ -0,0 +1,330 @@
//
// CreateClassDeclarationAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create class", Description = "Creates a class declaration out of an object creation.")]
public class CreateClassDeclarationAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var simpleType = context.GetNode<SimpleType>();
if (simpleType != null && !(simpleType.Parent is EventDeclaration || simpleType.Parent is CustomEventDeclaration))
return GetActions(context, simpleType);
var createExpression = context.GetNode<ObjectCreateExpression>();
if (createExpression != null)
return GetActions(context, createExpression);
var identifier = context.GetNode<IdentifierExpression>();
if (identifier != null && (identifier.Parent is MemberReferenceExpression))
return GetActions(context, identifier);
return Enumerable.Empty<CodeAction>();
}
static IEnumerable<CodeAction> GetActions(RefactoringContext context, AstNode node)
{
var resolveResult = context.Resolve(node) as UnknownIdentifierResolveResult;
if (resolveResult == null)
yield break;
var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
if (service != null && !service.IsValidName(resolveResult.Identifier, AffectedEntity.Class)) {
yield break;
}
ClassType classType = GuessClassTypeByName(service, node);
ModifyClassTypeBasedOnTypeGuessing(context, node, ref classType);
string message;
switch (classType) {
case ClassType.Struct:
message = context.TranslateString("Create struct");
break;
case ClassType.Interface:
message = context.TranslateString("Create interface");
break;
default:
message = context.TranslateString("Create class");
break;
}
yield return new CodeAction(message, script => {
script.CreateNewType(CreateType(context, service, node, classType));
}, node);
if (node.Parent is TypeDeclaration || classType != ClassType.Class)
yield break;
yield return new CodeAction(context.TranslateString("Create nested class"), script => {
script.InsertWithCursor(
context.TranslateString("Create nested class"),
Script.InsertPosition.Before,
CreateType(context, service, node, classType)
);
}, node);
}
static void ModifyClassTypeBasedOnTypeGuessing(RefactoringContext context, AstNode node, ref ClassType classType)
{
var guessedType = TypeGuessing.GuessType(context, node);
if (guessedType.Kind == TypeKind.TypeParameter) {
var tp = (ITypeParameter)guessedType;
if (tp.HasValueTypeConstraint)
classType = ClassType.Struct;
if (tp.HasReferenceTypeConstraint)
classType = ClassType.Class;
}
}
static ClassType GuessClassTypeByName(NamingConventionService service, string identifier)
{
if (service == null)
return ClassType.Class;
if (service.IsValidName (identifier, AffectedEntity.Interface, Modifiers.Public))
return ClassType.Interface;
if (!service.IsValidName (identifier, AffectedEntity.Class, Modifiers.Public) &&
service.IsValidName (identifier, AffectedEntity.Struct, Modifiers.Public))
return ClassType.Struct;
return ClassType.Class;
}
static ClassType GuessClassTypeByName(NamingConventionService service, AstNode node)
{
if (node is SimpleType)
return GuessClassTypeByName (service, ((SimpleType)node).Identifier);
if (node is IdentifierExpression)
return GuessClassTypeByName (service, ((IdentifierExpression)node).Identifier);
return ClassType.Class;
}
static TypeDeclaration CreateType(RefactoringContext context, NamingConventionService service, AstNode node, ClassType classType)
{
TypeDeclaration result;
if (node is SimpleType) {
result = CreateClassFromType(context, classType, (SimpleType)node);
} else if (node is ObjectCreateExpression) {
result = CreateClassFromObjectCreation(context, (ObjectCreateExpression)node);
} else {
result = CreateClassFromIdentifier(context, classType, (IdentifierExpression)node);
}
return AddBaseTypesAccordingToNamingRules(context, service, result);
}
static TypeDeclaration CreateClassFromIdentifier(RefactoringContext context, ClassType classType, IdentifierExpression identifierExpression)
{
var result = new TypeDeclaration { Name = identifierExpression.Identifier, ClassType = classType };
var entity = identifierExpression.GetParent<EntityDeclaration>();
if (entity != null)
result.Modifiers |= entity.Modifiers & Modifiers.Public;
return result;
}
static TypeDeclaration CreateClassFromType(RefactoringContext context, ClassType classType, SimpleType simpleType)
{
TypeDeclaration result;
string className = simpleType.Identifier;
if (simpleType.Parent is Attribute && classType == ClassType.Class) {
if (!className.EndsWith("Attribute", System.StringComparison.Ordinal))
className += "Attribute";
}
result = new TypeDeclaration { Name = className, ClassType = classType };
var entity = simpleType.GetParent<EntityDeclaration>();
if (entity != null)
result.Modifiers |= entity.Modifiers & Modifiers.Public;
var guessedType = TypeGuessing.GuessType (context, simpleType);
if (guessedType.Kind == TypeKind.TypeParameter)
ImplementConstraints (context, result, (ITypeParameter)guessedType);
return result;
}
static void ImplementConstraints(RefactoringContext context, TypeDeclaration result, ITypeParameter tp)
{
if (tp.HasValueTypeConstraint)
result.ClassType = ClassType.Struct;
if (tp.HasReferenceTypeConstraint)
result.ClassType = ClassType.Class;
if (tp.HasDefaultConstructorConstraint)
result.AddChild (new ConstructorDeclaration { Modifiers = Modifiers.Public, Body = new BlockStatement () }, Roles.TypeMemberRole);
foreach (var baseType in tp.DirectBaseTypes) {
if (baseType.Namespace == "System") {
if (baseType.Name == "Object" || baseType.Name == "ValueType")
continue;
}
result.BaseTypes.Add (context.CreateShortType (baseType));
}
}
static TypeDeclaration CreateClassFromObjectCreation(RefactoringContext context, ObjectCreateExpression createExpression)
{
TypeDeclaration result;
string className = createExpression.Type.ToString();
if (!createExpression.Arguments.Any()) {
result = new TypeDeclaration { Name = className };
} else {
var decl = new ConstructorDeclaration {
Name = className,
Modifiers = Modifiers.Public,
Body = new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
result = new TypeDeclaration {
Name = className,
Members = {
decl
}
};
decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, createExpression.Arguments));
}
var guessedType = TypeGuessing.GuessType(context, createExpression);
if (guessedType.Kind == TypeKind.Interface || guessedType.Kind == TypeKind.Class && guessedType.GetDefinition ().IsAbstract) {
result.BaseTypes.Add(context.CreateShortType(guessedType));
AddImplementation(context, result, guessedType);
}
return result;
}
static Modifiers GetModifiers(IEntity property)
{
if (property.DeclaringType.Kind == TypeKind.Interface)
return Modifiers.Public;
switch (property.Accessibility) {
case Accessibility.Public:
return Modifiers.Public | Modifiers.Override;
case Accessibility.Protected:
return Modifiers.Protected | Modifiers.Override;
case Accessibility.Internal:
return Modifiers.Internal | Modifiers.Override;
case Accessibility.ProtectedOrInternal:
// TODO: oops
return Modifiers.Internal | Modifiers.Protected | Modifiers.Override;
case Accessibility.ProtectedAndInternal:
// TODO: oops
return Modifiers.Internal | Modifiers.Protected | Modifiers.Override;
}
return Modifiers.Override;
}
static void AddImplementation(RefactoringContext context, TypeDeclaration result, IType guessedType)
{
foreach (var property in guessedType.GetProperties ()) {
if (!property.IsAbstract)
continue;
if (property.IsIndexer) {
var indexerDecl = new IndexerDeclaration {
ReturnType = context.CreateShortType(property.ReturnType),
Modifiers = GetModifiers(property),
Name = property.Name
};
indexerDecl.Parameters.AddRange(ConvertParameters(context, property.Parameters));
if (property.CanGet)
indexerDecl.Getter = new Accessor();
if (property.CanSet)
indexerDecl.Setter = new Accessor();
result.AddChild(indexerDecl, Roles.TypeMemberRole);
continue;
}
var propDecl = new PropertyDeclaration {
ReturnType = context.CreateShortType(property.ReturnType),
Modifiers = GetModifiers (property),
Name = property.Name
};
if (property.CanGet)
propDecl.Getter = new Accessor();
if (property.CanSet)
propDecl.Setter = new Accessor();
result.AddChild(propDecl, Roles.TypeMemberRole);
}
foreach (var method in guessedType.GetMethods ()) {
if (!method.IsAbstract)
continue;
var decl = new MethodDeclaration {
ReturnType = context.CreateShortType(method.ReturnType),
Modifiers = GetModifiers (method),
Name = method.Name,
Body = new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
};
decl.Parameters.AddRange(ConvertParameters(context, method.Parameters));
result.AddChild(decl, Roles.TypeMemberRole);
}
foreach (var evt in guessedType.GetEvents ()) {
if (!evt.IsAbstract)
continue;
var decl = new EventDeclaration {
ReturnType = context.CreateShortType(evt.ReturnType),
Modifiers = GetModifiers (evt),
Variables = {
new VariableInitializer {
Name = evt.Name
}
}
};
decl.Variables.Add(new VariableInitializer(evt.Name));
result.AddChild(decl, Roles.TypeMemberRole);
}
}
static IEnumerable<ParameterDeclaration> ConvertParameters(RefactoringContext context, IList<IParameter> parameters)
{
foreach (var param in parameters) {
ParameterModifier mod = ParameterModifier.None;
if (param.IsOut) {
mod = ParameterModifier.Out;
} else if (param.IsRef) {
mod = ParameterModifier.Ref;
} else if (param.IsParams) {
mod = ParameterModifier.Params;
}
yield return new ParameterDeclaration(context.CreateShortType(param.Type), param.Name, mod);
}
}
static TypeDeclaration AddBaseTypesAccordingToNamingRules(RefactoringContext context, NamingConventionService service, TypeDeclaration result)
{
if (service.HasValidRule(result.Name, AffectedEntity.CustomAttributes, Modifiers.Public)) {
result.BaseTypes.Add(context.CreateShortType("System", "Attribute"));
} else if (service.HasValidRule(result.Name, AffectedEntity.CustomEventArgs, Modifiers.Public)) {
result.BaseTypes.Add(context.CreateShortType("System", "EventArgs"));
} else if (service.HasValidRule(result.Name, AffectedEntity.CustomExceptions, Modifiers.Public)) {
result.BaseTypes.Add(context.CreateShortType("System", "Exception"));
}
return result;
}
}
}

64
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateConstructorDeclarationAction.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
//
// CreateClassDeclarationAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create constructor", Description = "Creates a constructor declaration out of an object creation.")]
public class CreateConstructorDeclarationAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var createExpression = context.GetNode<Expression>() as ObjectCreateExpression;
if (createExpression == null)
yield break;
var resolveResult = context.Resolve(createExpression) as CSharpInvocationResolveResult;
if (resolveResult == null || !resolveResult.IsError || resolveResult.Member.DeclaringTypeDefinition == null || resolveResult.Member.DeclaringTypeDefinition.IsSealed || resolveResult.Member.DeclaringTypeDefinition.Region.IsEmpty)
yield break;
yield return new CodeAction(context.TranslateString("Create constructor"), script =>
script.InsertWithCursor(
context.TranslateString("Create constructor"),
resolveResult.Member.DeclaringTypeDefinition,
(s, c) => {
var decl = new ConstructorDeclaration {
Name = resolveResult.Member.DeclaringTypeDefinition.Name,
Modifiers = Modifiers.Public,
Body = new BlockStatement {
new ThrowStatement(new ObjectCreateExpression(c.CreateShortType("System", "NotImplementedException")))
}
};
decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, createExpression.Arguments));
return decl;
}
)
, createExpression) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateCustomEventImplementationAction.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateCustomEventImplementationAction.cs

71
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateDelegateAction.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
//
// CreateDelegateAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create delegate", Description = "Creates a delegate declaration out of an event declaration.")]
public class CreateDelegateAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var simpleType = context.GetNode<SimpleType>();
if (simpleType != null && (simpleType.Parent is EventDeclaration || simpleType.Parent is CustomEventDeclaration))
return GetActions(context, simpleType);
return Enumerable.Empty<CodeAction>();
}
static IEnumerable<CodeAction> GetActions(RefactoringContext context, SimpleType node)
{
var resolveResult = context.Resolve(node) as UnknownIdentifierResolveResult;
if (resolveResult == null)
yield break;
yield return new CodeAction(context.TranslateString("Create delegate"), script => {
script.CreateNewType(CreateType(context, node));
}, node);
}
static DelegateDeclaration CreateType(RefactoringContext context, SimpleType simpleType)
{
var result = new DelegateDeclaration() {
Name = simpleType.Identifier,
Modifiers = ((EntityDeclaration)simpleType.Parent).Modifiers,
ReturnType = new PrimitiveType("void"),
Parameters = {
new ParameterDeclaration(new PrimitiveType("object"), "sender"),
new ParameterDeclaration(context.CreateShortType("System", "EventArgs"), "e")
}
};
return result;
}
}
}

85
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateEnumValue.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
//
// CreateEnumValue.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create enum value", Description = "Creates an enum value for a undefined enum value.")]
public class CreateEnumValue : CodeActionProvider
{
internal static bool IsInvocationTarget(AstNode node)
{
var invoke = node.Parent as InvocationExpression;
return invoke != null && invoke.Target == node;
}
internal static Expression GetCreatePropertyOrFieldNode(RefactoringContext context)
{
return context.GetNode(n => n is IdentifierExpression || n is MemberReferenceExpression || n is NamedExpression) as Expression;
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var expr = GetCreatePropertyOrFieldNode(context);
if (expr == null)
yield break;
if (!(expr is MemberReferenceExpression))
yield break;
var propertyName = CreatePropertyAction.GetPropertyName(expr);
if (propertyName == null)
yield break;
if (IsInvocationTarget(expr))
yield break;
var statement = expr.GetParent<Statement>();
if (statement == null)
yield break;
if (!(context.Resolve(expr).IsError))
yield break;
var guessedType = TypeGuessing.GuessType(context, expr);
if (guessedType == null || guessedType.Kind != TypeKind.Enum)
yield break;
var state = context.GetResolverStateBefore(expr);
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
yield return new CodeAction(context.TranslateString("Create enum value"), script => {
var decl = new EnumMemberDeclaration {
Name = propertyName
};
script.InsertWithCursor(context.TranslateString("Create enum value"), guessedType.GetDefinition (), (s, c) => decl);
}, expr) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
}
}

144
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateEventInvocatorAction.cs

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
//
// CreateEventInvocator.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Linq;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create event invocator", Description = "Creates a standard OnXXX event method.")]
public class CreateEventInvocatorAction : CodeActionProvider
{
/// <summary>
/// If <c>true</c> an explicit type will be used for the handler variable; otherwise, 'var' will be used as type.
/// Default value is <c>false</c>
/// </summary>
public bool UseExplictType {
get;
set;
}
public static MethodDeclaration CreateEventInvocator (RefactoringContext context, TypeDeclaration declaringType, EventDeclaration eventDeclaration, VariableInitializer initializer, IMethod invokeMethod, bool useExplictType)
{
bool hasSenderParam = false;
IEnumerable<IParameter> pars = invokeMethod.Parameters;
if (invokeMethod.Parameters.Any()) {
var first = invokeMethod.Parameters [0];
if (first.Name == "sender" /*&& first.Type == "System.Object"*/) {
hasSenderParam = true;
pars = invokeMethod.Parameters.Skip(1);
}
}
const string handlerName = "handler";
var arguments = new List<Expression>();
if (hasSenderParam)
arguments.Add(eventDeclaration.HasModifier (Modifiers.Static) ? (Expression)new PrimitiveExpression (null) : new ThisReferenceExpression());
bool useThisMemberReference = false;
foreach (var par in pars) {
arguments.Add(new IdentifierExpression(par.Name));
useThisMemberReference |= par.Name == initializer.Name;
}
var proposedHandlerName = GetNameProposal(initializer);
var modifiers = eventDeclaration.HasModifier(Modifiers.Static) ? Modifiers.Static : Modifiers.Protected | Modifiers.Virtual;
if (declaringType.HasModifier (Modifiers.Sealed)) {
modifiers = Modifiers.None;
}
var methodDeclaration = new MethodDeclaration {
Name = proposedHandlerName,
ReturnType = new PrimitiveType ("void"),
Modifiers = modifiers,
Body = new BlockStatement {
new VariableDeclarationStatement (
useExplictType ? eventDeclaration.ReturnType.Clone () : new PrimitiveType ("var"), handlerName,
useThisMemberReference ?
(Expression)new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)
: new IdentifierExpression (initializer.Name)
),
new IfElseStatement {
Condition = new BinaryOperatorExpression (new IdentifierExpression (handlerName), BinaryOperatorType.InEquality, new PrimitiveExpression (null)),
TrueStatement = new InvocationExpression (new IdentifierExpression (handlerName), arguments)
}
}
};
foreach (var par in pars) {
var typeName = context.CreateShortType(par.Type);
var decl = new ParameterDeclaration(typeName, par.Name);
methodDeclaration.Parameters.Add(decl);
}
return methodDeclaration;
}
static string GetNameProposal(VariableInitializer initializer)
{
return "On" + char.ToUpper(initializer.Name[0]) + initializer.Name.Substring(1);
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
VariableInitializer initializer;
var eventDeclaration = GetEventDeclaration(context, out initializer);
if (eventDeclaration == null) {
yield break;
}
var type = (TypeDeclaration)eventDeclaration.Parent;
var proposedHandlerName = GetNameProposal(initializer);
if (type.Members.Any(m => m is MethodDeclaration && m.Name == proposedHandlerName)) {
yield break;
}
var resolvedType = context.Resolve(eventDeclaration.ReturnType).Type;
if (resolvedType.Kind == TypeKind.Unknown) {
yield break;
}
var invokeMethod = resolvedType.GetDelegateInvokeMethod();
if (invokeMethod == null) {
yield break;
}
yield return new CodeAction(context.TranslateString("Create event invocator"), script => {
var methodDeclaration = CreateEventInvocator (context, type, eventDeclaration, initializer, invokeMethod, UseExplictType);
script.InsertWithCursor(
context.TranslateString("Create event invocator"),
Script.InsertPosition.After,
methodDeclaration
);
}, initializer);
}
static EventDeclaration GetEventDeclaration (RefactoringContext context, out VariableInitializer initializer)
{
var result = context.GetNode<EventDeclaration> ();
if (result == null) {
initializer = null;
return null;
}
initializer = result.Variables.FirstOrDefault (v => v.NameToken.Contains (context.Location));
return initializer != null ? result : null;
}
}
}

98
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateFieldAction.cs

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
//
// CreateField.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading;
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create field", Description = "Creates a field for a undefined variable.")]
public class CreateFieldAction : CodeActionProvider
{
internal static bool IsInvocationTarget(AstNode node)
{
var invoke = node.Parent as InvocationExpression;
return invoke != null && invoke.Target == node;
}
internal static Expression GetCreatePropertyOrFieldNode(RefactoringContext context)
{
return context.GetNode(n => n is IdentifierExpression || n is MemberReferenceExpression || n is NamedExpression) as Expression;
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var expr = GetCreatePropertyOrFieldNode(context);
if (expr == null)
yield break;
if (expr is MemberReferenceExpression && !(((MemberReferenceExpression)expr).Target is ThisReferenceExpression))
yield break;
var propertyName = CreatePropertyAction.GetPropertyName(expr);
if (propertyName == null)
yield break;
if (IsInvocationTarget(expr))
yield break;
var statement = expr.GetParent<Statement>();
if (statement == null)
yield break;
if (!(context.Resolve(expr).IsError))
yield break;
var guessedType = TypeGuessing.GuessAstType(context, expr);
if (guessedType == null)
yield break;
var state = context.GetResolverStateBefore(expr);
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
bool isStatic = !(expr is NamedExpression) && (state.CurrentMember.IsStatic | state.CurrentTypeDefinition.IsStatic);
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
// if (service != null && !service.IsValidName(identifier.Identifier, AffectedEntity.Field, Modifiers.Private, isStatic)) {
// yield break;
// }
yield return new CodeAction(context.TranslateString("Create field"), script => {
var decl = new FieldDeclaration {
ReturnType = guessedType,
Variables = { new VariableInitializer(propertyName) }
};
if (isStatic)
decl.Modifiers |= Modifiers.Static;
script.InsertWithCursor(context.TranslateString("Create field"), Script.InsertPosition.Before, decl);
}, expr.GetNodeAt(context.Location) ?? expr) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
}
}

102
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateIndexerAction.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
//
// CreateIndexerAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Text;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create indexer", Description = "Creates an indexer declaration out of an indexer expression.")]
public class CreateIndexerAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var indexer = context.GetNode<IndexerExpression>();
if (indexer == null)
yield break;
if (!(context.Resolve(indexer).IsError))
yield break;
var state = context.GetResolverStateBefore(indexer);
if (state.CurrentTypeDefinition == null)
yield break;
var guessedType = TypeGuessing.GuessAstType(context, indexer);
bool createInOtherType = false;
ResolveResult targetResolveResult = null;
targetResolveResult = context.Resolve(indexer.Target);
createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
bool isStatic;
if (createInOtherType) {
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
isStatic = targetResolveResult is TypeResolveResult;
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
yield break;
} else {
isStatic = indexer.Target is IdentifierExpression && state.CurrentMember.IsStatic;
}
yield return new CodeAction(context.TranslateString("Create indexer"), script => {
var decl = new IndexerDeclaration() {
ReturnType = guessedType,
Getter = new Accessor() {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
},
Setter = new Accessor() {
Body = new BlockStatement() {
new ThrowStatement(new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException")))
}
},
};
decl.Parameters.AddRange(CreateMethodDeclarationAction.GenerateParameters(context, indexer.Arguments));
if (isStatic)
decl.Modifiers |= Modifiers.Static;
if (createInOtherType) {
if (targetResolveResult.Type.Kind == TypeKind.Interface) {
decl.Getter.Body = null;
decl.Setter.Body = null;
decl.Modifiers = Modifiers.None;
} else {
decl.Modifiers |= Modifiers.Public;
}
script.InsertWithCursor(context.TranslateString("Create indexer"), targetResolveResult.Type.GetDefinition(), (s, c) => decl);
return;
}
script.InsertWithCursor(context.TranslateString("Create indexer"), Script.InsertPosition.Before, decl);
}, indexer) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
}
}

73
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateLocalVariableAction.cs

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
//
// CreateLocalVariable.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create local variable", Description = "Creates a local variable for a undefined variable.")]
public class CreateLocalVariableAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var identifier = context.GetNode<IdentifierExpression>();
if (identifier == null) {
yield break;
}
if (CreateFieldAction.IsInvocationTarget(identifier)) {
yield break;
}
var statement = context.GetNode<Statement>();
if (statement == null) {
yield break;
}
if (!(context.Resolve(identifier).IsError)) {
yield break;
}
var guessedType = TypeGuessing.GuessAstType(context, identifier);
if (guessedType == null) {
yield break;
}
yield return new CodeAction(context.TranslateString("Create local variable"), script => {
var initializer = new VariableInitializer(identifier.Identifier);
var decl = new VariableDeclarationStatement() {
Type = guessedType,
Variables = { initializer }
};
if (identifier.Parent is AssignmentExpression && ((AssignmentExpression)identifier.Parent).Left == identifier) {
initializer.Initializer = ((AssignmentExpression)identifier.Parent).Right.Clone();
if (!context.UseExplicitTypes)
decl.Type = new SimpleType("var");
script.Replace(statement, decl);
} else {
script.InsertBefore(statement, decl);
}
}, identifier) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
}
}

379
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateMethodDeclarationAction.cs

@ -0,0 +1,379 @@ @@ -0,0 +1,379 @@
//
// CreateMethodDeclarationAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin <http://xamarin.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Text;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create method", Description = "Creates a method declaration out of an invocation.")]
public class CreateMethodDeclarationAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var identifier = context.GetNode<IdentifierExpression>();
if (identifier != null && !(identifier.Parent is InvocationExpression && ((InvocationExpression)identifier.Parent).Target == identifier))
return GetActionsFromIdentifier(context, identifier);
var memberReference = context.GetNode<MemberReferenceExpression>();
if (memberReference != null && !(memberReference.Parent is InvocationExpression && ((InvocationExpression)memberReference.Parent).Target == memberReference))
return GetActionsFromMemberReferenceExpression(context, memberReference);
var invocation = context.GetNode<InvocationExpression>();
if (invocation != null)
return GetActionsFromInvocation(context, invocation);
return Enumerable.Empty<CodeAction>();
}
IEnumerable<CodeAction> GetActionsFromMemberReferenceExpression(RefactoringContext context, MemberReferenceExpression invocation)
{
if (!(context.Resolve(invocation).IsError))
yield break;
var methodName = invocation.MemberName;
var guessedType = TypeGuessing.GuessType(context, invocation);
if (guessedType.Kind != TypeKind.Delegate)
yield break;
var invocationMethod = guessedType.GetDelegateInvokeMethod();
var state = context.GetResolverStateBefore(invocation);
if (state.CurrentTypeDefinition == null)
yield break;
ResolveResult targetResolveResult = context.Resolve(invocation.Target);
bool createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
bool isStatic;
if (createInOtherType) {
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
isStatic = targetResolveResult is TypeResolveResult;
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
yield break;
} else {
if (state.CurrentMember == null)
yield break;
isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
}
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
// if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic)) {
// yield break;
// }
yield return CreateAction(
context,
invocation,
methodName,
context.CreateShortType(invocationMethod.ReturnType),
invocationMethod.Parameters.Select(parameter => new ParameterDeclaration(context.CreateShortType(parameter.Type), parameter.Name) {
ParameterModifier = GetModifiers(parameter)
}),
createInOtherType,
isStatic,
targetResolveResult);
}
IEnumerable<CodeAction> GetActionsFromIdentifier(RefactoringContext context, IdentifierExpression identifier)
{
if (!(context.Resolve(identifier).IsError))
yield break;
var methodName = identifier.Identifier;
var guessedType = TypeGuessing.GuessType(context, identifier);
if (guessedType.Kind != TypeKind.Delegate)
yield break;
var invocationMethod = guessedType.GetDelegateInvokeMethod();
if (invocationMethod == null)
yield break;
var state = context.GetResolverStateBefore(identifier);
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
bool isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic))
yield break;
yield return CreateAction(
context,
identifier,
methodName,
context.CreateShortType(invocationMethod.ReturnType),
invocationMethod.Parameters.Select(parameter => new ParameterDeclaration(context.CreateShortType(parameter.Type), parameter.Name) {
ParameterModifier = GetModifiers(parameter)
}),
false,
isStatic,
null);
}
IEnumerable<CodeAction> GetActionsFromInvocation(RefactoringContext context, InvocationExpression invocation)
{
if (!(context.Resolve(invocation.Target).IsError))
yield break;
var methodName = GetMethodName(invocation);
if (methodName == null)
yield break;
var state = context.GetResolverStateBefore(invocation);
if (state.CurrentMember == null || state.CurrentTypeDefinition == null)
yield break;
var guessedType = invocation.Parent is ExpressionStatement ? new PrimitiveType("void") : TypeGuessing.GuessAstType(context, invocation);
bool createInOtherType = false;
ResolveResult targetResolveResult = null;
if (invocation.Target is MemberReferenceExpression) {
targetResolveResult = context.Resolve(((MemberReferenceExpression)invocation.Target).Target);
createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
}
bool isStatic;
if (createInOtherType) {
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
isStatic = targetResolveResult is TypeResolveResult;
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
yield break;
} else {
isStatic = state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic;
}
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
// if (service != null && !service.IsValidName(methodName, AffectedEntity.Method, Modifiers.Private, isStatic)) {
// yield break;
// }
yield return CreateAction(
context,
invocation,
methodName,
guessedType,
GenerateParameters(context, invocation.Arguments),
createInOtherType,
isStatic,
targetResolveResult);
}
static ParameterModifier GetModifiers(IParameter parameter)
{
if (parameter.IsOut)
return ParameterModifier.Out;
if (parameter.IsRef)
return ParameterModifier.Ref;
if (parameter.IsParams)
return ParameterModifier.Params;
return ParameterModifier.None;
}
static CodeAction CreateAction(RefactoringContext context, AstNode createFromNode, string methodName, AstType returnType, IEnumerable<ParameterDeclaration> parameters, bool createInOtherType, bool isStatic, ResolveResult targetResolveResult)
{
return new CodeAction(context.TranslateString("Create method"), script => {
var throwStatement = new ThrowStatement();
var decl = new MethodDeclaration {
ReturnType = returnType,
Name = methodName,
Body = new BlockStatement {
throwStatement
}
};
decl.Parameters.AddRange(parameters);
if (isStatic)
decl.Modifiers |= Modifiers.Static;
if (createInOtherType) {
if (targetResolveResult.Type.Kind == TypeKind.Interface) {
decl.Body = null;
decl.Modifiers = Modifiers.None;
} else {
decl.Modifiers |= Modifiers.Public;
}
script
.InsertWithCursor(context.TranslateString("Create method"), targetResolveResult.Type.GetDefinition(), (s, c) => {
throwStatement.Expression = new ObjectCreateExpression(c.CreateShortType("System", "NotImplementedException"));
return decl;
})
.ContinueScript(s => s.Select(throwStatement));
return;
} else {
throwStatement.Expression = new ObjectCreateExpression(context.CreateShortType("System", "NotImplementedException"));
}
script
.InsertWithCursor(context.TranslateString("Create method"), Script.InsertPosition.Before, decl)
.ContinueScript(() => script.Select(throwStatement));
}, createFromNode.GetNodeAt(context.Location) ?? createFromNode) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
public static IEnumerable<ParameterDeclaration> GenerateParameters(RefactoringContext context, IEnumerable<Expression> arguments)
{
var nameCounter = new Dictionary<string, int>();
foreach (var argument in arguments) {
var direction = ParameterModifier.None;
AstNode node;
if (argument is DirectionExpression) {
var de = (DirectionExpression)argument;
direction = de.FieldDirection == FieldDirection.Out ? ParameterModifier.Out : ParameterModifier.Ref;
node = de.Expression;
} else {
node = argument;
}
var resolveResult = context.Resolve(node);
string name = CreateBaseName(argument, resolveResult.Type);
if (!nameCounter.ContainsKey(name)) {
nameCounter [name] = 1;
} else {
nameCounter [name]++;
name += nameCounter [name].ToString();
}
var type = resolveResult.Type.Kind == TypeKind.Unknown || resolveResult.Type.Kind == TypeKind.Null ? new PrimitiveType("object") : context.CreateShortType(resolveResult.Type);
yield return new ParameterDeclaration(type, name) { ParameterModifier = direction};
}
}
static string CreateBaseNameFromString(string str)
{
if (string.IsNullOrEmpty(str)) {
return "empty";
}
var sb = new StringBuilder();
bool firstLetter = true, wordStart = false;
foreach (char ch in str) {
if (char.IsWhiteSpace(ch)) {
wordStart = true;
continue;
}
if (!char.IsLetter(ch))
continue;
if (firstLetter) {
sb.Append(char.ToLower(ch));
firstLetter = false;
continue;
}
if (wordStart) {
sb.Append(char.ToUpper(ch));
wordStart = false;
continue;
}
sb.Append(ch);
}
return sb.Length == 0 ? "str" : sb.ToString();
}
public static string CreateBaseName(AstNode node, IType type)
{
string name = null;
if (node is NullReferenceExpression)
return "o";
if (node is DirectionExpression)
node = ((DirectionExpression)node).Expression;
if (node is IdentifierExpression) {
name = ((IdentifierExpression)node).Identifier;
} else if (node is MemberReferenceExpression) {
name = ((MemberReferenceExpression)node).MemberName;
} else if (node is PrimitiveExpression) {
var pe = (PrimitiveExpression)node;
if (pe.Value is string) {
name = CreateBaseNameFromString(pe.Value.ToString());
} else {
return char.ToLower(type.Name [0]).ToString();
}
} else if (node is ArrayCreateExpression) {
name = "arr";
} else {
if (type.Kind == TypeKind.Unknown)
return "par";
name = GuessNameFromType(type);
}
var sb = new StringBuilder ();
sb.Append (char.ToLower(name [0]));
for (int i = 1; i < name.Length; i++) {
var ch = name[i];
if (char.IsLetterOrDigit (ch) || ch == '_')
sb.Append (ch);
}
return sb.ToString ();
}
internal static string GuessNameFromType(IType returnType)
{
switch (returnType.ReflectionName) {
case "System.Byte":
case "System.SByte":
return "b";
case "System.Int16":
case "System.UInt16":
case "System.Int32":
case "System.UInt32":
case "System.Int64":
case "System.UInt64":
return "i";
case "System.Boolean":
return "b";
case "System.DateTime":
return "date";
case "System.Char":
return "ch";
case "System.Double":
case "System.Decimal":
return "d";
case "System.Single":
return "f";
case "System.String":
return "str";
case "System.Exception":
return "e";
case "System.Object":
return "obj";
case "System.Func":
return "func";
case "System.Action":
return "action";
}
return returnType.Name;
}
string GetMethodName(InvocationExpression invocation)
{
if (invocation.Target is IdentifierExpression)
return ((IdentifierExpression)invocation.Target).Identifier;
if (invocation.Target is MemberReferenceExpression)
return ((MemberReferenceExpression)invocation.Target).MemberName;
return null;
}
}
}

154
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs

@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
//
// CreateOverloadWithoutParameterAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading.Tasks;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Create overload without parameter", Description = "Create overload without the selected parameter.")]
public class CreateOverloadWithoutParameterAction : SpecializedCodeAction<ParameterDeclaration>
{
protected override CodeAction GetAction (RefactoringContext context, ParameterDeclaration node)
{
if (!node.DefaultExpression.IsNull)
return null;
if (node.ParameterModifier == ParameterModifier.This || node.ParameterModifier == ParameterModifier.Params)
return null;
if (!node.NameToken.Contains(context.Location))
return null;
var methodDecl = node.Parent as MethodDeclaration;
if (methodDecl == null)
return null;
// explicit implementation
if (!methodDecl.PrivateImplementationType.IsNull)
return null;
// find existing method
var method = (IMethod)((MemberResolveResult)context.Resolve (methodDecl)).Member;
var parameters = new List<IParameter> (method.Parameters.Where (param => param.Name != node.Name));
if (method.DeclaringType.GetMethods (
m => m.Name == method.Name && m.TypeParameters.Count == method.TypeParameters.Count)
.Any (m => ParameterListComparer.Instance.Equals (m.Parameters, parameters)))
return null;
return new CodeAction (context.TranslateString ("Create overload without parameter"),
script =>
{
var defaultExpr = GetDefaultValueExpression (context, node.Type);
var body = new BlockStatement ();
Expression argExpr;
if (node.ParameterModifier == ParameterModifier.Ref) {
body.Add (new VariableDeclarationStatement (node.Type.Clone (), node.Name, defaultExpr));
argExpr = GetArgumentExpression (node);
} else if (node.ParameterModifier == ParameterModifier.Out) {
body.Add (new VariableDeclarationStatement (node.Type.Clone (), node.Name));
argExpr = GetArgumentExpression (node);
} else {
argExpr = defaultExpr;
}
body.Add (new InvocationExpression (new IdentifierExpression (methodDecl.Name),
methodDecl.Parameters.Select (param => param == node ? argExpr : GetArgumentExpression(param))));
var decl = (MethodDeclaration)methodDecl.Clone ();
decl.Parameters.Remove (decl.Parameters.First (param => param.Name == node.Name));
decl.Body = body;
script
.InsertWithCursor ("Create overload without parameter", Script.InsertPosition.Before, decl)
.ContinueScript (() => script.Select(argExpr));
}, node.NameToken);
}
static Expression GetArgumentExpression(ParameterDeclaration parameter)
{
var identifierExpr = new IdentifierExpression(parameter.Name);
switch (parameter.ParameterModifier) {
case ParameterModifier.Out:
return new DirectionExpression (FieldDirection.Out, identifierExpr);
case ParameterModifier.Ref:
return new DirectionExpression (FieldDirection.Ref, identifierExpr);
}
return identifierExpr;
}
static Expression GetDefaultValueExpression (RefactoringContext context, AstType astType)
{
var type = context.ResolveType (astType);
// array
if (type.Kind == TypeKind.Array)
return new ObjectCreateExpression (astType.Clone ());
// enum
if (type.Kind == TypeKind.Enum) {
var members = type.GetMembers ().ToArray();
if (members.Length == 0)
return new DefaultValueExpression (astType.Clone ());
return astType.Member(members[0].Name).Clone ();
}
if ((type.IsReferenceType ?? false) || type.Kind == TypeKind.Dynamic)
return new NullReferenceExpression ();
var typeDefinition = type.GetDefinition ();
if (typeDefinition != null) {
switch (typeDefinition.KnownTypeCode) {
case KnownTypeCode.Boolean:
return new PrimitiveExpression (false);
case KnownTypeCode.Char:
return new PrimitiveExpression ('\0');
case KnownTypeCode.SByte:
case KnownTypeCode.Byte:
case KnownTypeCode.Int16:
case KnownTypeCode.UInt16:
case KnownTypeCode.Int32:
case KnownTypeCode.UInt32:
case KnownTypeCode.Int64:
case KnownTypeCode.UInt64:
case KnownTypeCode.Single:
case KnownTypeCode.Double:
case KnownTypeCode.Decimal:
return new PrimitiveExpression (0);
case KnownTypeCode.NullableOfT:
return new NullReferenceExpression ();
}
if (type.Kind == TypeKind.Struct)
return new ObjectCreateExpression (astType.Clone ());
}
return new DefaultValueExpression (astType.Clone ());
}
}
}

131
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreatePropertyAction.cs

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
//
// CreateProperty.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Create property", Description = "Creates a property for a undefined variable.")]
public class CreatePropertyAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var identifier = CreateFieldAction.GetCreatePropertyOrFieldNode (context);
if (identifier == null)
yield break;
if (CreateFieldAction.IsInvocationTarget(identifier))
yield break;
var propertyName = GetPropertyName(identifier);
if (propertyName == null)
yield break;
var statement = context.GetNode<Statement>();
if (statement == null)
yield break;
if (!(context.Resolve(identifier).IsError))
yield break;
var guessedType = TypeGuessing.GuessAstType(context, identifier);
if (guessedType == null)
yield break;
var state = context.GetResolverStateBefore(identifier);
if (state.CurrentTypeDefinition == null)
yield break;
bool createInOtherType = false;
ResolveResult targetResolveResult = null;
if (identifier is MemberReferenceExpression) {
targetResolveResult = context.Resolve(((MemberReferenceExpression)identifier).Target);
if (targetResolveResult.Type.GetDefinition() == null || targetResolveResult.Type.GetDefinition().Region.IsEmpty)
yield break;
createInOtherType = !state.CurrentTypeDefinition.Equals(targetResolveResult.Type.GetDefinition());
}
bool isStatic = targetResolveResult is TypeResolveResult;
if (createInOtherType) {
if (isStatic && targetResolveResult.Type.Kind == TypeKind.Interface || targetResolveResult.Type.Kind == TypeKind.Enum)
yield break;
} else {
if (state.CurrentMember == null)
yield break;
isStatic |= state.CurrentTypeDefinition.IsStatic;
if (targetResolveResult == null)
isStatic |= state.CurrentMember.IsStatic;
}
isStatic &= !(identifier is NamedExpression);
// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService));
// if (service != null && !service.IsValidName(propertyName, AffectedEntity.Property, Modifiers.Private, isStatic)) {
// yield break;
// }
yield return new CodeAction(context.TranslateString("Create property"), script => {
var decl = new PropertyDeclaration() {
ReturnType = guessedType,
Name = propertyName,
Getter = new Accessor(),
Setter = new Accessor()
};
if (isStatic)
decl.Modifiers |= Modifiers.Static;
if (createInOtherType) {
if (targetResolveResult.Type.Kind == TypeKind.Interface) {
decl.Modifiers = Modifiers.None;
} else {
decl.Modifiers |= Modifiers.Public;
}
script.InsertWithCursor(
context.TranslateString("Create property"),
targetResolveResult.Type.GetDefinition(),
(s, c) => decl);
return;
}
script.InsertWithCursor(context.TranslateString("Create property"), Script.InsertPosition.Before, decl);
}, identifier.GetNodeAt(context.Location) ?? identifier) { Severity = ICSharpCode.NRefactory.Refactoring.Severity.Error };
}
internal static string GetPropertyName(Expression expr)
{
if (expr is IdentifierExpression)
return ((IdentifierExpression)expr).Identifier;
if (expr is MemberReferenceExpression)
return ((MemberReferenceExpression)expr).MemberName;
if (expr is NamedExpression)
return ((NamedExpression)expr).Name;
return null;
}
}
}

188
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/DeclareLocalVariableAction.cs

@ -0,0 +1,188 @@ @@ -0,0 +1,188 @@
//
// DeclareLocalVariableAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.PatternMatching;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Declare local variable", Description = "Declare a local variable out of a selected expression.")]
public class DeclareLocalVariableAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
if (!context.IsSomethingSelected) {
yield break;
}
var selected = new List<AstNode>(context.GetSelectedNodes());
if (selected.Count != 1 || !(selected [0] is Expression)) {
yield break;
}
var expr = selected [0] as Expression;
if (expr is ArrayInitializerExpression) {
var arr = (ArrayInitializerExpression)expr;
if (arr.IsSingleElement) {
expr = arr.Elements.First();
} else {
yield break;
}
}
var visitor = new SearchNodeVisitior(expr);
var node = context.GetNode <BlockStatement>();
if (node != null) {
node.AcceptVisitor(visitor);
}
yield return new CodeAction(context.TranslateString("Declare local variable"), script => {
var resolveResult = context.Resolve(expr);
var guessedType = resolveResult.Type;
if (resolveResult is MethodGroupResolveResult) {
guessedType = GetDelegateType(context, ((MethodGroupResolveResult)resolveResult).Methods.First(), expr);
}
var name = CreateMethodDeclarationAction.CreateBaseName(expr, guessedType);
var type = context.UseExplicitTypes ? context.CreateShortType(guessedType) : new SimpleType("var");
var varDecl = new VariableDeclarationStatement(type, name, expr.Clone());
var replaceNode = visitor.Matches.First () as Expression;
if (replaceNode.Parent is ExpressionStatement) {
script.Replace(replaceNode.Parent, varDecl);
script.Select(varDecl.Variables.First().NameToken);
} else {
var containing = replaceNode.Parent;
while (!(containing.Parent is BlockStatement)) {
containing = containing.Parent;
}
script.InsertBefore(containing, varDecl);
var identifierExpression = new IdentifierExpression(name);
script.Replace(replaceNode, identifierExpression);
script.Link(varDecl.Variables.First().NameToken, identifierExpression);
}
}, expr);
if (visitor.Matches.Count > 1) {
yield return new CodeAction(string.Format(context.TranslateString("Declare local variable (replace '{0}' occurrences)"), visitor.Matches.Count), script => {
var resolveResult = context.Resolve(expr);
var guessedType = resolveResult.Type;
if (resolveResult is MethodGroupResolveResult) {
guessedType = GetDelegateType(context, ((MethodGroupResolveResult)resolveResult).Methods.First(), expr);
}
var linkedNodes = new List<AstNode>();
var name = CreateMethodDeclarationAction.CreateBaseName(expr, guessedType);
var type = context.UseExplicitTypes ? context.CreateShortType(guessedType) : new SimpleType("var");
var varDecl = new VariableDeclarationStatement(type, name, expr.Clone());
linkedNodes.Add(varDecl.Variables.First().NameToken);
var first = visitor.Matches [0];
if (first.Parent is ExpressionStatement) {
script.Replace(first.Parent, varDecl);
} else {
var containing = first.Parent;
while (!(containing.Parent is BlockStatement)) {
containing = containing.Parent;
}
script.InsertBefore(containing, varDecl);
var identifierExpression = new IdentifierExpression(name);
linkedNodes.Add(identifierExpression);
script.Replace(first, identifierExpression);
}
for (int i = 1; i < visitor.Matches.Count; i++) {
var identifierExpression = new IdentifierExpression(name);
linkedNodes.Add(identifierExpression);
script.Replace(visitor.Matches [i], identifierExpression);
}
script.Link(linkedNodes.ToArray ());
}, expr);
}
}
// Gets Action/Func delegate types for a given method.
IType GetDelegateType(RefactoringContext context, IMethod method, Expression expr)
{
var parameters = new List<IType>();
var invoke = expr.Parent as InvocationExpression;
if (invoke == null) {
return null;
}
foreach (var arg in invoke.Arguments) {
parameters.Add(context.Resolve(arg).Type);
}
ITypeDefinition genericType;
if (method.ReturnType.FullName == "System.Void") {
genericType = context.Compilation.GetAllTypeDefinitions().FirstOrDefault(t => t.FullName == "System.Action" && t.TypeParameterCount == parameters.Count);
} else {
parameters.Add(method.ReturnType);
genericType = context.Compilation.GetAllTypeDefinitions().FirstOrDefault(t => t.FullName == "System.Func" && t.TypeParameterCount == parameters.Count);
}
if (genericType == null) {
return null;
}
return new ParameterizedType(genericType, parameters);
}
internal class SearchNodeVisitior : DepthFirstAstVisitor
{
readonly AstNode searchForNode;
public readonly List<AstNode> Matches = new List<AstNode> ();
public SearchNodeVisitior (AstNode searchForNode)
{
this.searchForNode = searchForNode;
AddNode (searchForNode);
}
void AddNode(AstNode node)
{
if (node.Parent is ParenthesizedExpression) {
Matches.Add(node.Parent);
} else {
Matches.Add(node);
}
}
protected override void VisitChildren(AstNode node)
{
if (node.StartLocation > searchForNode.StartLocation && node.IsMatch(searchForNode)) {
AddNode(node);
return;
}
base.VisitChildren (node);
}
}
}
}

69
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtensionMethodInvocationToStaticMethodInvocationAction.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
//
// ExtensionMethodInvocationToStaticMethodInvocationAction.cs
//
// Author:
// Simon Lindgren <simon.n.lindgren@gmail.com>
//
// Copyright (c) 2012 Simon Lindgren
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp.Resolver;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Invoke using static method syntax",
Description = "Converts the call into static method call syntax.")]
public class ExtensionMethodInvocationToStaticMethodInvocationAction : CodeActionProvider
{
#region ICodeActionProvider implementation
public override IEnumerable<CodeAction> GetActions (RefactoringContext context)
{
var invocation = context.GetNode<InvocationExpression>();
if (invocation == null)
yield break;
var memberReference = invocation.Target as MemberReferenceExpression;
if (memberReference == null)
yield break;
var invocationRR = context.Resolve(invocation) as CSharpInvocationResolveResult;
if (invocationRR == null)
yield break;
if (invocationRR.IsExtensionMethodInvocation)
yield return new CodeAction(context.TranslateString("Convert to static method call"), script => {
script.Replace(invocation, ToStaticMethodInvocation(invocation, memberReference, invocationRR));
}, invocation);
}
#endregion
AstNode ToStaticMethodInvocation(InvocationExpression invocation, MemberReferenceExpression memberReference,
CSharpInvocationResolveResult invocationRR)
{
var newArgumentList = invocation.Arguments.Select(arg => arg.Clone()).ToList();
newArgumentList.Insert(0, memberReference.Target.Clone());
var newTarget = memberReference.Clone() as MemberReferenceExpression;
newTarget.Target = new IdentifierExpression(invocationRR.Member.DeclaringType.Name);
return new InvocationExpression(newTarget, newArgumentList);
}
}
}

120
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractAnonymousMethodAction.cs

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
//
// ExtractAnonymousMethodAction.cs
//
// Author:
// Mansheng Yang <lightyang0@gmail.com>
//
// Copyright (c) 2012 Mansheng Yang <lightyang0@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction ("Extract anonymous method",
Description = "Extract anonymous method to method of the containing type")]
public class ExtractAnonymousMethodAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions (RefactoringContext context)
{
// lambda
var lambda = context.GetNode<LambdaExpression> ();
if (lambda != null && lambda.ArrowToken.Contains(context.Location)) {
if (ContainsLocalReferences (context, lambda, lambda.Body))
yield break;
bool noReturn = false;
BlockStatement body;
if (lambda.Body is BlockStatement) {
body = (BlockStatement)lambda.Body.Clone ();
} else {
if (!(lambda.Body is Expression))
yield break;
body = new BlockStatement ();
var type = LambdaHelper.GetLambdaReturnType (context, lambda);
if (type == null || type.ReflectionName == "System.Void") {
noReturn = true;
body.Add ((Expression)lambda.Body.Clone ());
} else {
body.Add (new ReturnStatement ((Expression)lambda.Body.Clone ()));
}
}
var method = GetMethod (context, (LambdaResolveResult)context.Resolve (lambda), body, noReturn);
yield return GetAction (context, lambda, method);
}
// anonymous method
var anonymousMethod = context.GetNode<AnonymousMethodExpression> ();
if (anonymousMethod != null && anonymousMethod.DelegateToken.Contains(context.Location)) {
if (ContainsLocalReferences (context, anonymousMethod, anonymousMethod.Body))
yield break;
var method = GetMethod (context, (LambdaResolveResult)context.Resolve (anonymousMethod),
(BlockStatement)anonymousMethod.Body.Clone ());
yield return GetAction (context, anonymousMethod, method);
}
}
CodeAction GetAction (RefactoringContext context, AstNode node, MethodDeclaration method)
{
return new CodeAction (context.TranslateString ("Extract anonymous method"),
script =>
{
var identifier = new IdentifierExpression ("Method");
script.Replace (node, identifier);
script.InsertBefore (node.GetParent<EntityDeclaration> (), method);
script.Link (method.NameToken, identifier);
}, method.NameToken);
}
static MethodDeclaration GetMethod (RefactoringContext context, LambdaResolveResult lambda, BlockStatement body,
bool noReturnValue = false)
{
var method = new MethodDeclaration { Name = "Method" };
if (noReturnValue) {
method.ReturnType = new PrimitiveType ("void");
} else {
var type = lambda.ReturnType;
method.ReturnType = type.Kind == TypeKind.Unknown ? new PrimitiveType ("void") : context.CreateShortType (type);
}
foreach (var param in lambda.Parameters)
method.Parameters.Add (new ParameterDeclaration (context.CreateShortType (param.Type), param.Name));
method.Body = body;
if (lambda.IsAsync)
method.Modifiers |= Modifiers.Async;
return method;
}
static bool ContainsLocalReferences (RefactoringContext context, AstNode expr, AstNode body)
{
var visitor = new ExtractMethod.VariableLookupVisitor (context);
body.AcceptVisitor (visitor);
return visitor.UsedVariables.Any (variable => !expr.Contains (variable.Region.Begin));
}
}
}

125
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractFieldAction.cs

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
//
// ExtractFieldAction.cs
//
// Author:
// Nieve <>
//
// Copyright (c) 2012 Nieve
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using Mono.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Extract field", Description = "Extracts a field from a local variable declaration.")]
public class ExtractFieldAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
//TODO: implement variable assignment & ctor param
var varInit = context.GetNode<VariableInitializer>();
if (varInit != null) {
var selectedNode = varInit.GetNodeAt(context.Location);
if (selectedNode != varInit.NameToken)
yield break;
AstType type = varInit.GetPrevNode() as AstType;
if (type == null) yield break;
if (varInit.Parent is FieldDeclaration) yield break;
if (CannotExtractField(context, varInit)) yield break;
yield return new CodeAction(context.TranslateString("Assign to new field"), s=>{
var name = varInit.Name;
AstType extractedType;
if (type.IsVar()) {
IType resolvedType = context.Resolve(varInit.Initializer).Type;
extractedType = context.CreateShortType(resolvedType);
}
else {
extractedType = (AstType) type.Clone();
}
AstNode entityDeclarationNode = varInit.Parent;
while (!(entityDeclarationNode is EntityDeclaration) || (entityDeclarationNode is Accessor)) {
entityDeclarationNode = entityDeclarationNode.Parent;
}
var entity = (EntityDeclaration) entityDeclarationNode;
bool isStatic = entity.HasModifier(Modifiers.Static);
FieldDeclaration field = new FieldDeclaration(){
Modifiers = isStatic ? Modifiers.Static : Modifiers.None,
ReturnType = extractedType,
Variables = { new VariableInitializer(name) }
};
AstNode nodeToRemove = RemoveDeclaration(varInit) ? varInit.Parent : type;
s.Remove(nodeToRemove, true);
s.InsertWithCursor(context.TranslateString("Insert new field"),Script.InsertPosition.Before,field);
s.FormatText(varInit.Parent);
}, selectedNode);
}
var idntf = context.GetNode<Identifier>();
if (idntf == null) yield break;
var paramDec = idntf.Parent as ParameterDeclaration;
if (paramDec != null) {
var ctor = paramDec.Parent as ConstructorDeclaration;
if (ctor == null) yield break;
MemberReferenceExpression thisField = new MemberReferenceExpression(new ThisReferenceExpression(), idntf.Name, new AstType[]{});
var assign = new AssignmentExpression(thisField, AssignmentOperatorType.Assign, new IdentifierExpression(idntf.Name));
var statement = new ExpressionStatement(assign);
var type = (idntf.GetPrevNode() as AstType).Clone();
FieldDeclaration field = new FieldDeclaration(){
ReturnType = type.Clone(),
Variables = { new VariableInitializer(idntf.Name) }
};
yield return new CodeAction(context.TranslateString("Assign to new field"), s=>{
s.InsertWithCursor(context.TranslateString("Insert new field"),Script.InsertPosition.Before,field);
s.AddTo(ctor.Body, statement);
}, paramDec.NameToken);
}
}
static bool RemoveDeclaration (VariableInitializer varInit){
var result = varInit.Parent as VariableDeclarationStatement;
return result.Variables.First ().Initializer.IsNull;
}
static bool CannotExtractField (RefactoringContext context, VariableInitializer varInit)
{
var result = varInit.Parent as VariableDeclarationStatement;
return result == null || result.Variables.Count != 1 || ContainsAnonymousType(context.Resolve(varInit.Initializer).Type);
}
static bool ContainsAnonymousType (IType type)
{
if (type.Kind == TypeKind.Anonymous)
return true;
var arrayType = type as ArrayType;
return arrayType != null && ContainsAnonymousType (arrayType.ElementType);
}
}
}

243
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/ExtractMethodAction.cs

@ -0,0 +1,243 @@ @@ -0,0 +1,243 @@
//
// ExtractMethodAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Analysis;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
using System.Threading.Tasks;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
[ContextAction("Extract method", Description = "Creates a new method out of selected text.")]
public class ExtractMethodAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
if (!context.IsSomethingSelected)
yield break;
var selected = new List<AstNode>(context.GetSelectedNodes());
if (selected.Count == 0)
yield break;
if (selected.Count == 1 && selected [0] is Expression) {
var codeAction = CreateFromExpression(context, (Expression)selected [0]);
if (codeAction == null)
yield break;
yield return codeAction;
}
foreach (var node in selected) {
if (!(node is Statement) && !(node is Comment) && !(node is NewLineNode) && !(node is PreProcessorDirective))
yield break;
}
var action = CreateFromStatements (context, new List<AstNode> (selected));
if (action != null)
yield return action;
}
CodeAction CreateFromExpression(RefactoringContext context, Expression expression)
{
var resolveResult = context.Resolve(expression);
if (resolveResult.IsError)
return null;
return new CodeAction(context.TranslateString("Extract method"), script => {
string methodName = "NewMethod";
var method = new MethodDeclaration {
ReturnType = context.CreateShortType(resolveResult.Type),
Name = methodName,
Body = new BlockStatement {
new ReturnStatement(expression.Clone())
}
};
if (!StaticVisitor.UsesNotStaticMember(context, expression))
method.Modifiers |= Modifiers.Static;
var usedVariables = VariableLookupVisitor.Analyze(context, expression);
var inExtractedRegion = new VariableUsageAnalyzation (context, usedVariables);
usedVariables.Sort ((l, r) => l.Region.Begin.CompareTo (r.Region.Begin));
var target = new IdentifierExpression(methodName);
var invocation = new InvocationExpression(target);
foreach (var variable in usedVariables) {
Expression argumentExpression = new IdentifierExpression(variable.Name);
var mod = ParameterModifier.None;
if (inExtractedRegion.GetStatus (variable) == VariableState.Changed) {
mod = ParameterModifier.Ref;
argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
}
method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(variable.Type), variable.Name, mod));
invocation.Arguments.Add(argumentExpression);
}
script
.InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method)
.ContinueScript (delegate {
script.Replace(expression, invocation);
script.Link(target, method.NameToken);
});
}, expression);
}
CodeAction CreateFromStatements(RefactoringContext context, List<AstNode> statements)
{
if (!(statements [0].Parent is Statement))
return null;
return new CodeAction(context.TranslateString("Extract method"), script => {
string methodName = "NewMethod";
var method = new MethodDeclaration() {
ReturnType = new PrimitiveType("void"),
Name = methodName,
Body = new BlockStatement()
};
bool usesNonStaticMember = false;
foreach (var node in statements) {
usesNonStaticMember |= StaticVisitor.UsesNotStaticMember(context, node);
if (node is Statement) {
method.Body.Add((Statement)node.Clone());
} else {
method.Body.AddChildUnsafe (node.Clone (), node.Role);
}
}
if (!usesNonStaticMember)
method.Modifiers |= Modifiers.Static;
var target = new IdentifierExpression(methodName);
var invocation = new InvocationExpression(target);
var usedVariables = VariableLookupVisitor.Analyze(context, statements);
var inExtractedRegion = new VariableUsageAnalyzation (context, usedVariables);
var lastStatement = statements [statements.Count - 1];
var stmt = statements [0].GetParent<BlockStatement>();
while (stmt.GetParent<BlockStatement> () != null) {
stmt = stmt.GetParent<BlockStatement>();
}
inExtractedRegion.SetAnalyzedRange(statements [0], lastStatement);
stmt.AcceptVisitor (inExtractedRegion);
var beforeExtractedRegion = new VariableUsageAnalyzation (context, usedVariables);
beforeExtractedRegion.SetAnalyzedRange(statements [0].Parent, statements [0], true, false);
stmt.AcceptVisitor (beforeExtractedRegion);
var afterExtractedRegion = new VariableUsageAnalyzation (context, usedVariables);
afterExtractedRegion.SetAnalyzedRange(lastStatement, stmt.Statements.Last(), false, true);
stmt.AcceptVisitor (afterExtractedRegion);
usedVariables.Sort ((l, r) => l.Region.Begin.CompareTo (r.Region.Begin));
IVariable generatedReturnVariable = null;
foreach (var variable in usedVariables) {
if ((variable is IParameter) || beforeExtractedRegion.Has (variable) || !afterExtractedRegion.Has (variable))
continue;
generatedReturnVariable = variable;
method.ReturnType = context.CreateShortType (variable.Type);
method.Body.Add (new ReturnStatement (new IdentifierExpression (variable.Name)));
break;
}
int parameterOutCount = 0;
foreach (var variable in usedVariables) {
if (!(variable is IParameter) && !beforeExtractedRegion.Has (variable) && !afterExtractedRegion.Has (variable))
continue;
if (variable == generatedReturnVariable)
continue;
Expression argumentExpression = new IdentifierExpression(variable.Name);
ParameterModifier mod = ParameterModifier.None;
if (inExtractedRegion.GetStatus (variable) == VariableState.Changed) {
if (beforeExtractedRegion.GetStatus (variable) == VariableState.None) {
mod = ParameterModifier.Out;
argumentExpression = new DirectionExpression(FieldDirection.Out, argumentExpression);
parameterOutCount++;
} else {
mod = ParameterModifier.Ref;
argumentExpression = new DirectionExpression(FieldDirection.Ref, argumentExpression);
}
}
method.Parameters.Add(new ParameterDeclaration(context.CreateShortType(variable.Type), variable.Name, mod));
invocation.Arguments.Add(argumentExpression);
}
ParameterDeclaration parameterToTransform = null;
bool transformParameterToReturn = method.ReturnType is PrimitiveType &&
((PrimitiveType)method.ReturnType).Keyword == "void" &&
parameterOutCount == 1;
if(transformParameterToReturn) {
parameterToTransform = method.Parameters.First(p => p.ParameterModifier == ParameterModifier.Out);
parameterToTransform.Remove();
var argumentExpression = invocation.Arguments.OfType<DirectionExpression>().First(a => a.FieldDirection == FieldDirection.Out);
argumentExpression.Remove();
method.ReturnType = parameterToTransform.Type.Clone();
var argumentDecl = new VariableDeclarationStatement(parameterToTransform.Type.Clone(),parameterToTransform.Name);
method.Body.InsertChildBefore(method.Body.First(),argumentDecl,BlockStatement.StatementRole);
method.Body.Add(new ReturnStatement (new IdentifierExpression (parameterToTransform.Name)));
}
script
.InsertWithCursor(context.TranslateString("Extract method"), Script.InsertPosition.Before, method)
.ContinueScript(delegate {
foreach (var node in statements.Skip (1)) {
if (node is NewLineNode)
continue;
script.Remove(node);
}
foreach (var variable in usedVariables) {
if ((variable is IParameter) || beforeExtractedRegion.Has (variable) || !afterExtractedRegion.Has (variable))
continue;
if (variable == generatedReturnVariable)
continue;
script.InsertBefore (statements [0], new VariableDeclarationStatement (context.CreateShortType(variable.Type), variable.Name));
}
Statement invocationStatement;
if (generatedReturnVariable != null) {
invocationStatement = new VariableDeclarationStatement (new SimpleType ("var"), generatedReturnVariable.Name, invocation);
} else if(transformParameterToReturn) {
invocationStatement = new AssignmentExpression(new IdentifierExpression(parameterToTransform.Name), invocation);
} else {
invocationStatement = invocation;
}
script.Replace(statements [0], invocationStatement);
script.Link(target, method.NameToken);
});
}, statements.First ().StartLocation, statements.Last ().EndLocation);
}
}
}

85
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/StaticVisitor.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
//
// StaticVisitor.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.Semantics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
class StaticVisitor : DepthFirstAstVisitor
{
readonly BaseRefactoringContext context;
public bool UsesNonStaticMember = false;
StaticVisitor(BaseRefactoringContext context)
{
this.context = context;
}
public static bool UsesNotStaticMember(BaseRefactoringContext context, AstNode node)
{
var visitor = new StaticVisitor(context);
node.AcceptVisitor(visitor);
return visitor.UsesNonStaticMember;
}
protected override void VisitChildren(AstNode node)
{
if (UsesNonStaticMember)
return;
base.VisitChildren(node);
}
public override void VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression)
{
UsesNonStaticMember = true;
base.VisitThisReferenceExpression(thisReferenceExpression);
}
public override void VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression)
{
UsesNonStaticMember = true;
base.VisitBaseReferenceExpression(baseReferenceExpression);
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
var resolveResult = context.Resolve(identifierExpression);
if (resolveResult is MemberResolveResult) {
var memberResult = (MemberResolveResult)resolveResult;
if (!memberResult.Member.IsStatic)
UsesNonStaticMember = true;
} else if (resolveResult is MethodGroupResolveResult) {
var methodGroupResolveResult = (MethodGroupResolveResult)resolveResult;
if (methodGroupResolveResult.Methods.Any(m => !m.IsStatic))
UsesNonStaticMember = true;
}
}
}
}

135
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/VariableLookupVisitor.cs

@ -0,0 +1,135 @@ @@ -0,0 +1,135 @@
//
// VariableLookupVisitor.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring.ExtractMethod
{
class VariableLookupVisitor : DepthFirstAstVisitor
{
readonly RefactoringContext context;
public List<IVariable> UsedVariables = new List<IVariable> ();
TextLocation startLocation = TextLocation.Empty;
TextLocation endLocation = TextLocation.Empty;
public VariableLookupVisitor (RefactoringContext context)
{
this.context = context;
}
public bool Has (IVariable item1)
{
return UsedVariables.Contains (item1);
}
public void SetAnalyzedRange(AstNode start, AstNode end, bool startInclusive = true, bool endInclusive = true)
{
if (start == null)
throw new ArgumentNullException("start");
if (end == null)
throw new ArgumentNullException("end");
startLocation = startInclusive ? start.StartLocation : start.EndLocation;
endLocation = endInclusive ? end.EndLocation : end.StartLocation;
}
public override void VisitIdentifierExpression(IdentifierExpression identifierExpression)
{
if (startLocation.IsEmpty || startLocation <= identifierExpression.StartLocation && identifierExpression.EndLocation <= endLocation) {
var result = context.Resolve(identifierExpression);
var local = result as LocalResolveResult;
if (local != null && !UsedVariables.Contains(local.Variable)&& !anonymousParameters.Contains(local.Variable)) {
UsedVariables.Add(local.Variable);
}
}
}
HashSet<IVariable> anonymousParameters = new HashSet<IVariable> ();
public override void VisitLambdaExpression(LambdaExpression lambdaExpression)
{
foreach (var param in lambdaExpression.Parameters) {
var result = context.Resolve(param);
var local = result as LocalResolveResult;
anonymousParameters.Add(local.Variable);
}
base.VisitLambdaExpression(lambdaExpression);
foreach (var param in lambdaExpression.Parameters) {
var result = context.Resolve(param);
var local = result as LocalResolveResult;
anonymousParameters.Remove(local.Variable);
}
}
public override void VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression)
{
foreach (var param in anonymousMethodExpression.Parameters) {
var result = context.Resolve(param);
var local = result as LocalResolveResult;
anonymousParameters.Add(local.Variable);
}
base.VisitAnonymousMethodExpression(anonymousMethodExpression);
foreach (var param in anonymousMethodExpression.Parameters) {
var result = context.Resolve(param);
var local = result as LocalResolveResult;
anonymousParameters.Remove(local.Variable);
}
}
public override void VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement)
{
base.VisitVariableDeclarationStatement(variableDeclarationStatement);
foreach (var varDecl in variableDeclarationStatement.Variables) {
if (startLocation.IsEmpty || startLocation <= varDecl.StartLocation && varDecl.EndLocation <= endLocation) {
var result = context.Resolve(varDecl);
var local = result as LocalResolveResult;
if (local != null && !UsedVariables.Contains(local.Variable) && !anonymousParameters.Contains(local.Variable))
UsedVariables.Add(local.Variable);
}
}
}
public static List<IVariable> Analyze(RefactoringContext context, Expression expression)
{
var visitor = new VariableLookupVisitor(context);
expression.AcceptVisitor(visitor);
return visitor.UsedVariables;
}
public static List<IVariable> Analyze(RefactoringContext context, List<AstNode> statements)
{
var visitor = new VariableLookupVisitor(context);
statements.ForEach(stmt => stmt.AcceptVisitor(visitor));
return visitor.UsedVariables;
}
}
}

0
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/ExtractMethod/VariableUsageAnalyzation.cs → src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractMethod/VariableUsageAnalyzation.cs

68
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/ExtractWhileConditionToInternalIfStatementAction.cs

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
//
// ExtractWhileConditionToInternalIfStatementAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.PatternMatching;
using Mono.CSharp;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Extract field", Description = "Extracts a field from a local variable declaration.")]
public class ExtractWhileConditionToInternalIfStatementAction : SpecializedCodeAction<WhileStatement>
{
protected override CodeAction GetAction(RefactoringContext context, WhileStatement node)
{
if (!node.WhileToken.Contains(context.Location))
return null;
return new CodeAction(
context.TranslateString("Extract condition to internal 'if' statement"),
script => {
script.Replace(node.Condition, new PrimitiveExpression(true));
var ifStmt = new IfElseStatement(
CSharpUtil.InvertCondition(node.Condition),
new BreakStatement()
);
var block = node.EmbeddedStatement as BlockStatement;
if (block != null) {
script.InsertAfter(block.LBraceToken, ifStmt);
} else {
var blockStatement = new BlockStatement {
ifStmt
};
if (!(node.EmbeddedStatement is EmptyStatement))
blockStatement.Statements.Add(node.EmbeddedStatement.Clone());
script.Replace(node.EmbeddedStatement, blockStatement);
}
},
node
);
}
}
}

96
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/FlipEqualsTargetAndArgumentAction.cs

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
//
// FlipEqualsQualifierAndArgumentAction.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using System.Linq;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Swap 'Equals' target and argument", Description = "Swap 'Equals' target and argument")]
public class FlipEqualsTargetAndArgumentAction : CodeActionProvider
{
Expression GetInnerMostExpression(Expression target)
{
while (target is ParenthesizedExpression)
target = ((ParenthesizedExpression)target).Expression;
return target;
}
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var invocation = context.GetNode<InvocationExpression>();
if (invocation == null)
yield break;
if (invocation.Arguments.Count != 1 || invocation.Arguments.First() is NullReferenceExpression)
yield break;
var target = invocation.Target as MemberReferenceExpression;
if (target == null || target.MemberNameToken.StartLocation > context.Location || invocation.LParToken.StartLocation < context.Location)
yield break;
var rr = context.Resolve(invocation) as InvocationResolveResult;
if (rr == null || rr.Member.Name != "Equals" || rr.Member.IsStatic || !rr.Member.ReturnType.IsKnownType(KnownTypeCode.Boolean))
yield break;
yield return new CodeAction(
context.TranslateString("Flip 'Equals' target and argument"),
script => {
script.Replace(
invocation,
new InvocationExpression(
new MemberReferenceExpression(
AddParensIfRequired(invocation.Arguments.First ().Clone()),
"Equals"
),
GetInnerMostExpression (target.Target).Clone()
)
);
},
invocation
);
}
Expression AddParensIfRequired(Expression expression)
{
if ((expression is BinaryOperatorExpression) ||
(expression is UnaryOperatorExpression) ||
(expression is CastExpression) ||
(expression is AssignmentExpression) ||
(expression is AsExpression) ||
(expression is IsExpression) ||
(expression is LambdaExpression) ||
(expression is ConditionalExpression)) {
return new ParenthesizedExpression(expression);
}
return expression;
}
}
}

61
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/FlipOperatorArgumentsAction.cs

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
//
// FlipOperatorArguments.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Mike Krüger <mkrueger@novell.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Swaps left and right arguments.", Description = "Swaps left and right arguments.")]
public class FlipOperatorArgumentsAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var binop = GetBinaryOperatorExpression(context);
if (binop == null) {
yield break;
}
yield return new CodeAction(string.Format(context.TranslateString("Flip '{0}' operator arguments"), binop.OperatorToken.ToString()), script => {
script.Replace(binop.Left, binop.Right.Clone());
script.Replace(binop.Right, binop.Left.Clone());
}, binop.OperatorToken);
}
public static BinaryOperatorExpression GetBinaryOperatorExpression (RefactoringContext context)
{
var node = context.GetNode<BinaryOperatorExpression> ();
if (node == null || !node.OperatorToken.Contains (context.Location))
return null;
var result = node as BinaryOperatorExpression;
if (result == null || (result.Operator != BinaryOperatorType.Equality && result.Operator != BinaryOperatorType.InEquality))
return null;
return result;
}
}
}

101
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/GenerateGetterAction.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
//
// GenerateGetter.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2011 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using System.Threading;
using System.Collections.Generic;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Generate getter", Description = "Generates a getter for a field.")]
public class GenerateGetterAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var initializer = GetVariableInitializer(context);
if (initializer == null || !initializer.NameToken.Contains(context.Location)) {
yield break;
}
var type = initializer.Parent.Parent as TypeDeclaration;
if (type == null) {
yield break;
}
foreach (var member in type.Members) {
if (member is PropertyDeclaration && ContainsGetter((PropertyDeclaration)member, initializer)) {
yield break;
}
}
var field = initializer.Parent as FieldDeclaration;
if (field == null) {
yield break;
}
yield return new CodeAction(context.TranslateString("Create getter"), script => {
script.InsertWithCursor(
context.TranslateString("Create getter"),
Script.InsertPosition.After,
GeneratePropertyDeclaration(context, field, initializer));
}, initializer);
}
static PropertyDeclaration GeneratePropertyDeclaration (RefactoringContext context, FieldDeclaration field, VariableInitializer initializer)
{
var mod = ICSharpCode.NRefactory.CSharp.Modifiers.Public;
if (field.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Static))
mod |= ICSharpCode.NRefactory.CSharp.Modifiers.Static;
return new PropertyDeclaration () {
Modifiers = mod,
Name = context.GetNameProposal (initializer.Name, false),
ReturnType = field.ReturnType.Clone (),
Getter = new Accessor () {
Body = new BlockStatement () {
new ReturnStatement (new IdentifierExpression (initializer.Name))
}
}
};
}
bool ContainsGetter (PropertyDeclaration property, VariableInitializer initializer)
{
if (property.Getter.IsNull || property.Getter.Body.Statements.Count () != 1)
return false;
var ret = property.Getter.Body.Statements.Single () as ReturnStatement;
if (ret == null)
return false;
return ret.Expression.IsMatch (new IdentifierExpression (initializer.Name)) ||
ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name));
}
VariableInitializer GetVariableInitializer (RefactoringContext context)
{
return context.GetNode<VariableInitializer> ();
}
}
}

108
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/GeneratePropertyAction.cs

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
//
// GenerateProperty.cs
//
// Author:
// Mike Krüger <mkrueger@xamarin.com>
//
// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.PatternMatching;
using System.Linq;
using System.Threading;
using System.Collections.Generic;
using ICSharpCode.NRefactory.Semantics;
namespace ICSharpCode.NRefactory.CSharp.Refactoring
{
[ContextAction("Generate property", Description = "Generates a getter and setter for a field.")]
public class GeneratePropertyAction : CodeActionProvider
{
public override IEnumerable<CodeAction> GetActions(RefactoringContext context)
{
var initializer = context.GetNode<VariableInitializer>();
if (initializer == null || !initializer.NameToken.Contains(context.Location.Line, context.Location.Column)) {
yield break;
}
var type = initializer.Parent.Parent as TypeDeclaration;
if (type == null) {
yield break;
}
foreach (var member in type.Members) {
if (member is PropertyDeclaration && ContainsGetter((PropertyDeclaration)member, initializer)) {
yield break;
}
}
var field = initializer.Parent as FieldDeclaration;
if (field == null || field.HasModifier(Modifiers.Readonly) || field.HasModifier(Modifiers.Const)) {
yield break;
}
var resolveResult = context.Resolve(initializer) as MemberResolveResult;
if (resolveResult == null)
yield break;
yield return new CodeAction(context.TranslateString("Create property"), script => {
var fieldName = context.GetNameProposal(initializer.Name, true);
if (initializer.Name == context.GetNameProposal(initializer.Name, false)) {
script.Rename(resolveResult.Member, fieldName);
}
script.InsertWithCursor(
context.TranslateString("Create property"),
Script.InsertPosition.After, GeneratePropertyDeclaration(context, field, fieldName));
}, initializer);
}
static PropertyDeclaration GeneratePropertyDeclaration (RefactoringContext context, FieldDeclaration field, string fieldName)
{
var mod = ICSharpCode.NRefactory.CSharp.Modifiers.Public;
if (field.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Static))
mod |= ICSharpCode.NRefactory.CSharp.Modifiers.Static;
return new PropertyDeclaration () {
Modifiers = mod,
Name = context.GetNameProposal (fieldName, false),
ReturnType = field.ReturnType.Clone (),
Getter = new Accessor {
Body = new BlockStatement {
new ReturnStatement (new IdentifierExpression (fieldName))
}
},
Setter = new Accessor {
Body = new BlockStatement {
new AssignmentExpression (new IdentifierExpression (fieldName), new IdentifierExpression ("value"))
}
}
};
}
bool ContainsGetter (PropertyDeclaration property, VariableInitializer initializer)
{
if (property.Getter.IsNull || property.Getter.Body.Statements.Count () != 1)
return false;
var ret = property.Getter.Body.Statements.Single () as ReturnStatement;
if (ret == null)
return false;
return ret.Expression.IsMatch (new IdentifierExpression (initializer.Name)) ||
ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name));
}
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save