diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
index 3a9759177f..b4ac3ed070 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
@@ -73,9 +73,10 @@
-
+
+
@@ -96,6 +97,9 @@
+
+
+
OverrideEqualsGetHashCodeMethodsDialog.xaml
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
index b981593f37..cabc8fa3ef 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
@@ -95,10 +95,11 @@ namespace CSharpBinding.Completion
ICompletionData ICompletionDataFactory.CreateNewOverrideCompletionData(int declarationBegin, IUnresolvedTypeDefinition type, IMember m)
{
- if ((m.EntityType == EntityType.Method) && (m.Name == "ToString"))
- return new OverrideToStringCompletionData(declarationBegin, m, contextAtCaret);
- else if ((m.EntityType == EntityType.Method) && (m.Name == "GetHashCode"))
+ if ((m.SymbolKind == SymbolKind.Method) && (m.Name == "ToString"))
return new OverrideToStringCompletionData(declarationBegin, m, contextAtCaret);
+ else if ((m.SymbolKind == SymbolKind.Method) && ((m.Name == "GetHashCode")
+ || ((m.Name == "Equals") && ((((IMethod) m)).Parameters.Count == 1) && (((IMethod) m).Parameters.First().Type.FullName == "System.Object"))))
+ return new OverrideEqualsGetHashCodeCompletionData(declarationBegin, m, contextAtCaret);
else
return new OverrideCompletionData(declarationBegin, m, contextAtCaret);
}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideGetHashCodeCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs
similarity index 54%
rename from src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideGetHashCodeCompletionData.cs
rename to src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs
index 2b2c8a5a6b..1f88e9e82f 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideGetHashCodeCompletionData.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs
@@ -26,11 +26,11 @@ using CSharpBinding.Refactoring;
namespace CSharpBinding.Completion
{
///
- /// Item for 'override' completion of "GetHashCode()" methods.
+ /// Item for 'override' completion of "Equals()" and "GetHashCode()" methods.
///
- class OverrideGetHashCodeCompletionData : OverrideCompletionData
+ class OverrideEqualsGetHashCodeCompletionData : OverrideCompletionData
{
- public OverrideGetHashCodeCompletionData(int declarationBegin, IMember m, CSharpTypeResolveContext contextAtCaret)
+ public OverrideEqualsGetHashCodeCompletionData(int declarationBegin, IMember m, CSharpTypeResolveContext contextAtCaret)
: base(declarationBegin, m, contextAtCaret)
{
}
@@ -55,7 +55,7 @@ namespace CSharpBinding.Completion
if (!this.Entity.IsAbstract) {
// modify body to call the base method
- if (this.Entity.EntityType == EntityType.Method) {
+ if (this.Entity.SymbolKind == SymbolKind.Method) {
var baseCall = new BaseReferenceExpression().Invoke(this.Entity.Name, new Expression[] { });
if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void))
baseCallStatement = new ExpressionStatement(baseCall);
@@ -88,60 +88,26 @@ namespace CSharpBinding.Completion
return;
}
var resolvedCurrent = typeResolveContext.CurrentTypeDefinition;
- var entities = FindFieldsAndProperties(resolvedCurrent).ToList();
- if (entities.Any()) {
- IEditorUIService uiService = context.Editor.GetService(typeof(IEditorUIService)) as IEditorUIService;
-
- ITextAnchor endAnchor = context.Editor.Document.CreateAnchor(context.Editor.Caret.Offset);
- endAnchor.MovementType = AnchorMovementType.AfterInsertion;
-
- ITextAnchor startAnchor = context.Editor.Document.CreateAnchor(context.Editor.Caret.Offset);
- startAnchor.MovementType = AnchorMovementType.BeforeInsertion;
-
- ITextAnchor insertionPos = context.Editor.Document.CreateAnchor(endAnchor.Offset);
- insertionPos.MovementType = AnchorMovementType.BeforeInsertion;
+ IEditorUIService uiService = context.Editor.GetService(typeof(IEditorUIService)) as IEditorUIService;
+
+ ITextAnchor endAnchor = context.Editor.Document.CreateAnchor(context.Editor.Caret.Offset);
+ endAnchor.MovementType = AnchorMovementType.AfterInsertion;
+
+ ITextAnchor startAnchor = context.Editor.Document.CreateAnchor(context.Editor.Caret.Offset);
+ startAnchor.MovementType = AnchorMovementType.BeforeInsertion;
+
+ ITextAnchor insertionPos = context.Editor.Document.CreateAnchor(endAnchor.Offset);
+ insertionPos.MovementType = AnchorMovementType.BeforeInsertion;
- InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, startAnchor.Offset);
-
-// AbstractInlineRefactorDialog dialog = new OverrideToStringMethodDialog(insertionContext, context.Editor, startAnchor, insertionPos, entities, baseCallStatement);
-// dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog);
-
- insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog);
- insertionContext.RaiseInsertionCompleted(EventArgs.Empty);
- }
- else {
- if (baseCallStatement != null) {
- // Add default base call
- MethodDeclaration insertedOverrideMethod = refactoringContext.GetNode().PrevSibling as MethodDeclaration;
- if (insertedOverrideMethod == null)
- {
- // We are not inside of a method declaration
- return;
- }
- using (Script script = refactoringContext.StartScript()) {
- script.AddTo(insertedOverrideMethod.Body, baseCallStatement);
- }
- }
- }
- }
- }
-
- IEnumerable FindFieldsAndProperties(IType sourceType)
- {
- int i = 0;
-
- foreach (var f in sourceType.GetFields().Where(field => !field.IsConst
- && field.IsStatic == sourceType.GetDefinition().IsStatic
- && field.ReturnType != null)) {
- yield return new PropertyOrFieldWrapper(f) { Index = i };
- i++;
- }
-
- foreach (var p in sourceType.GetProperties().Where(prop => prop.CanGet && !prop.IsIndexer
- && prop.IsStatic == sourceType.GetDefinition().IsStatic
- && prop.ReturnType != null)) {
- yield return new PropertyOrFieldWrapper(p) { Index = i };
- i++;
+ InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, startAnchor.Offset);
+
+ var current = typeResolveContext.CurrentTypeDefinition;
+ AbstractInlineRefactorDialog dialog = new OverrideEqualsGetHashCodeMethodsDialog(insertionContext, context.Editor, startAnchor, endAnchor, insertionPos, current, Entity as IMethod, baseCallStatement);
+
+ dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog);
+
+ insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog);
+ insertionContext.RaiseInsertionCompleted(EventArgs.Empty);
}
}
}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs
index dcdc3a5491..04f6709134 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs
@@ -55,7 +55,7 @@ namespace CSharpBinding.Completion
if (!this.Entity.IsAbstract) {
// modify body to call the base method
- if (this.Entity.EntityType == EntityType.Method) {
+ if (this.Entity.SymbolKind == SymbolKind.Method) {
var baseCall = new BaseReferenceExpression().Invoke(this.Entity.Name, new Expression[] { });
if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void))
baseCallStatement = new ExpressionStatement(baseCall);
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs
index 480a48ef9b..228b28f8d5 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs
@@ -12,6 +12,7 @@ using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Snippets;
using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Parser;
@@ -93,6 +94,16 @@ namespace CSharpBinding.Refactoring
optionBindings.Add(binding);
}
+ protected AstType ConvertType(KnownTypeCode knownTypeCode)
+ {
+ IType type = refactoringContext.Compilation.FindType(knownTypeCode);
+ if (type != null)
+ return ConvertType(type);
+
+ // Backup solution
+ return new SimpleType(KnownTypeReference.GetCSharpNameByTypeCode(knownTypeCode));
+ }
+
protected AstType ConvertType(IType type)
{
return refactoringContext.CreateShortType(type);
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/Options.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/Options.cs
new file mode 100644
index 0000000000..51dbfc4c10
--- /dev/null
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/Options.cs
@@ -0,0 +1,50 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Diagnostics;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+
+namespace CSharpBinding.Refactoring
+{
+ ///
+ /// Description of Options.
+ ///
+ public static class Options
+ {
+ static Properties properties;
+
+ public static Properties Properties {
+ get {
+ Debug.Assert(properties != null);
+ return properties;
+ }
+ }
+
+ static Options()
+ {
+ properties = SD.PropertyService.Get("SharpRefactoringOptions", new Properties());
+ }
+
+ public static bool AddIEquatableInterface {
+ get { return properties.Get("AddIEquatableInterface", false); }
+ set { properties.Set("AddIEquatableInterface", value); }
+ }
+
+ public static bool AddOtherMethod {
+ get { return properties.Get("AddOtherMethod", true); }
+ set { properties.Set("AddOtherMethod", value); }
+ }
+
+ public static bool SurroundWithRegion {
+ get { return properties.Get("SurroundWithRegion", true); }
+ set { properties.Set("SurroundWithRegion", value); }
+ }
+
+ public static bool AddOperatorOverloads {
+ get { return properties.Get("AddOperatorOverloads", true); }
+ set { properties.Set("AddOperatorOverloads", value); }
+ }
+ }
+}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs
index d16d4623f5..5bc5d5d18e 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -9,11 +10,9 @@ using System.Text;
using ICSharpCode.AvalonEdit.Snippets;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.SharpDevelop.Dom;
-using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Editor;
using Dom = ICSharpCode.SharpDevelop.Dom;
@@ -24,13 +23,13 @@ namespace CSharpBinding.Refactoring
///
public partial class OverrideEqualsGetHashCodeMethodsDialog : AbstractInlineRefactorDialog
{
- IType selectedClass;
+ ITypeDefinition selectedClass;
ITextAnchor startAnchor;
IMethod selectedMethod;
AstNode baseCallNode;
public OverrideEqualsGetHashCodeMethodsDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor endAnchor,
- ITextAnchor insertionPosition, IType selectedClass, IMethod selectedMethod, AstNode baseCallNode)
+ ITextAnchor insertionPosition, ITypeDefinition selectedClass, IMethod selectedMethod, AstNode baseCallNode)
: base(context, editor, insertionPosition)
{
if (selectedClass == null)
@@ -51,15 +50,19 @@ namespace CSharpBinding.Refactoring
addOtherMethod.Content = StringParser.Parse("${res:AddIns.SharpRefactoring.OverrideEqualsGetHashCodeMethods.AddOtherMethod}", new StringTagPair("otherMethod", otherMethod));
- addIEquatable.IsEnabled = !selectedClass.BaseTypes.Any(
+ addIEquatable.IsEnabled = !selectedClass.GetAllBaseTypes().Any(
type => {
- if (!type.IsGenericReturnType)
+ if (!type.IsParameterized || (type.TypeParameterCount != 1))
return false;
- var genericType = type.CastToGenericReturnType();
- var boundTo = genericType.TypeParameter.BoundTo;
- if (boundTo == null)
+ if (type.FullName != "System.IEquatable")
return false;
- return boundTo.Name == selectedClass.Name;
+ return type.TypeArguments.First().FullName == selectedClass.FullName;
+
+// var genericType = type.CastToGenericReturnType();
+// var boundTo = genericType.TypeParameter.BoundTo;
+// if (boundTo == null)
+// return false;
+// return boundTo.Name == selectedClass.Name;
}
);
}
@@ -82,11 +85,11 @@ namespace CSharpBinding.Refactoring
return type != null
&& type.FullName != "System.Single"
&& type.FullName != "System.Double"
- && (!type.IsReferenceType
+ && (!IsReferenceType(type)
|| type.FullName == "System.String");
}
- static Expression TestEquality(string other, IField field)
+ Expression TestEquality(string other, IField field)
{
if (CanCompareEqualityWithOperator(field.ReturnType)) {
return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name),
@@ -94,7 +97,7 @@ namespace CSharpBinding.Refactoring
new MemberReferenceExpression(new IdentifierExpression(other), field.Name));
} else {
InvocationExpression ie = new InvocationExpression(
- new MemberReferenceExpression(new TypeReferenceExpression(new TypeReference("System.Object", true)), "Equals")
+ new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(KnownTypeCode.Object)), "Equals")
);
ie.Arguments.Add(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name));
ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), field.Name));
@@ -102,7 +105,7 @@ namespace CSharpBinding.Refactoring
}
}
- static Expression TestEquality(string other, IProperty property)
+ Expression TestEquality(string other, IProperty property)
{
if (CanCompareEqualityWithOperator(property.ReturnType)) {
return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), property.Name),
@@ -110,7 +113,7 @@ namespace CSharpBinding.Refactoring
new MemberReferenceExpression(new IdentifierExpression(other), property.Name));
} else {
InvocationExpression ie = new InvocationExpression(
- new MemberReferenceExpression(new TypeReferenceExpression(new SimpleType("System.Object")), "Equals")
+ new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(KnownTypeCode.Object)), "Equals")
);
ie.Arguments.Add(new MemberReferenceExpression(new ThisReferenceExpression(), property.Name));
ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), property.Name));
@@ -118,6 +121,15 @@ namespace CSharpBinding.Refactoring
}
}
+ static bool IsReferenceType(IType type)
+ {
+ if (type.IsReferenceType.HasValue) {
+ return type.IsReferenceType.Value;
+ }
+
+ return false;
+ }
+
protected override string GenerateCode(ITypeDefinition currentClass)
{
StringBuilder code = new StringBuilder();
@@ -126,8 +138,18 @@ namespace CSharpBinding.Refactoring
string indent = DocumentUtilitites.GetWhitespaceAfter(editor.Document, line.Offset);
- CodeGenerator generator = language.CodeGenerator;
+// CodeGenerator generator = language.CodeGenerator;
+
+ MethodDeclaration insertedOverrideMethod = refactoringContext.GetNode().PrevSibling as MethodDeclaration;
+ if (insertedOverrideMethod == null)
+ {
+ // We are not inside of a method declaration
+ return null;
+ }
+ using (Script script = refactoringContext.StartScript()) {
+ NewLineNode nextNewLineNode = insertedOverrideMethod.NextSibling as NewLineNode;
+
// if (Options.AddIEquatableInterface) {
// TODO : add IEquatable to class
// IAmbience ambience = currentClass.CompilationUnit.Language.GetAmbience();
@@ -152,120 +174,132 @@ namespace CSharpBinding.Refactoring
//
// editor.Document.Replace(startOffset, endOffset - startOffset, a);
// }
-
- if (Options.SurroundWithRegion) {
- editor.Document.InsertNormalized(startAnchor.Offset, "#region Equals and GetHashCode implementation\n" + indent);
- }
-
- string codeForMethodBody;
-
- if ("Equals".Equals(selectedMethod.Name, StringComparison.Ordinal)) {
- IList equalsOverrides = CreateEqualsOverrides(currentClass);
- MethodDeclaration defaultOverride = equalsOverrides.First();
- equalsOverrides = equalsOverrides.Skip(1).ToList();
- StringBuilder builder = new StringBuilder();
-
- foreach (AbstractNode element in defaultOverride.Body.Children.OfType()) {
- builder.Append(language.CodeGenerator.GenerateCode(element, indent + "\t"));
+ if (Options.SurroundWithRegion) {
+ script.InsertBefore(insertedOverrideMethod, new PreProcessorDirective(PreProcessorDirectiveType.Region, "Equals and GetHashCode implementation"));
}
- codeForMethodBody = builder.ToString().Trim();
-
- if (addOtherMethod.IsChecked == true) {
- if (equalsOverrides.Any())
- code.Append(indent + "\n" + string.Join("\n", equalsOverrides.Select(item => generator.GenerateCode(item, indent))));
- code.Append(indent + "\n" + generator.GenerateCode(CreateGetHashCodeOverride(currentClass), indent));
- }
- } else {
- StringBuilder builder = new StringBuilder();
-
- foreach (AbstractNode element in CreateGetHashCodeOverride(currentClass).Body.Children.OfType()) {
- builder.Append(language.CodeGenerator.GenerateCode(element, indent + "\t"));
+ if ("Equals".Equals(selectedMethod.Name, StringComparison.Ordinal)) {
+ IList equalsOverrides = CreateEqualsOverrides(currentClass);
+ MethodDeclaration defaultOverride = equalsOverrides.First();
+ equalsOverrides = equalsOverrides.Skip(1).ToList();
+
+ // Insert children of default Equals method into
+ foreach (AstNode element in defaultOverride.Body.Children) {
+ script.AddTo(insertedOverrideMethod.Body, element.Clone());
+ }
+
+ // Add other Equals() overrides after our main inserted method
+ if (addOtherMethod.IsChecked == true) {
+ if (equalsOverrides.Any()) {
+ foreach (var equalsMethod in equalsOverrides) {
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, equalsMethod);
+ }
+ }
+
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, CreateGetHashCodeOverride(currentClass));
+ }
+ } else {
+ StringBuilder builder = new StringBuilder();
+
+ foreach (AstNode element in CreateGetHashCodeOverride(currentClass).Body.Children) {
+ script.AddTo(insertedOverrideMethod.Body, element.Clone());
+ }
+
+ if (addOtherMethod.IsChecked == true) {
+ foreach (var equalsMethod in CreateEqualsOverrides(currentClass)) {
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, equalsMethod);
+ }
+ }
}
- codeForMethodBody = builder.ToString().Trim();
-
- if (addOtherMethod.IsChecked == true)
- code.Append(indent + "\n" + string.Join("\n", CreateEqualsOverrides(currentClass).Select(item => generator.GenerateCode(item, indent))));
- }
-
- if (Options.AddOperatorOverloads) {
- var checkStatements = new[] {
- new IfElseStatement(
- new InvocationExpression(
- new IdentifierExpression("ReferenceEquals"),
- new List() { new IdentifierExpression("lhs"), new IdentifierExpression("rhs") }
- ),
- new ReturnStatement(new PrimitiveExpression(true))
- ),
- new IfElseStatement(
- new BinaryOperatorExpression(
+ if (Options.AddOperatorOverloads) {
+ var checkStatements = new[] {
+ new IfElseStatement(
new InvocationExpression(
new IdentifierExpression("ReferenceEquals"),
- new List() { new IdentifierExpression("lhs"), new PrimitiveExpression(null) }
+ new List() { new IdentifierExpression("lhs"), new IdentifierExpression("rhs") }
),
- BinaryOperatorType.LogicalOr,
- new InvocationExpression(
- new IdentifierExpression("ReferenceEquals"),
- new List() { new IdentifierExpression("rhs"), new PrimitiveExpression(null) }
- )
+ new ReturnStatement(new PrimitiveExpression(true))
),
- new ReturnStatement(new PrimitiveExpression(false))
- )
- };
-
- BlockStatement equalsOpBody = new BlockStatement() {
- Children = {
+ new IfElseStatement(
+ new BinaryOperatorExpression(
+ new InvocationExpression(
+ new IdentifierExpression("ReferenceEquals"),
+ new List() { new IdentifierExpression("lhs"), new PrimitiveExpression(null) }
+ ),
+ BinaryOperatorType.ConditionalOr,
+ new InvocationExpression(
+ new IdentifierExpression("ReferenceEquals"),
+ new List() { new IdentifierExpression("rhs"), new PrimitiveExpression(null) }
+ )
+ ),
+ new ReturnStatement(new PrimitiveExpression(false))
+ )
+ };
+
+ BlockStatement equalsOpBody = new BlockStatement();
+
+ if (currentClass.Kind == TypeKind.Class) {
+ foreach (var statement in checkStatements) {
+ equalsOpBody.Add(statement);
+ }
+ }
+
+ equalsOpBody.Add(
new ReturnStatement(
new InvocationExpression(
new MemberReferenceExpression(new IdentifierExpression("lhs"), "Equals"),
new List() { new IdentifierExpression("rhs") }
)
)
- }
- };
-
- if (currentClass.ClassType == Dom.ClassType.Class) {
- equalsOpBody.Children.InsertRange(0, checkStatements);
- }
+ );
- BlockStatement notEqualsOpBody = new BlockStatement() {
- Children = {
- new ReturnStatement(
- new UnaryOperatorExpression(
- new ParenthesizedExpression(
- new BinaryOperatorExpression(
- new IdentifierExpression("lhs"),
- BinaryOperatorType.Equality,
- new IdentifierExpression("rhs")
- )
- ),
- UnaryOperatorType.Not
+ BlockStatement notEqualsOpBody = new BlockStatement();
+ notEqualsOpBody.Add(new ReturnStatement(
+ new UnaryOperatorExpression(
+ UnaryOperatorType.Not,
+ new ParenthesizedExpression(
+ new BinaryOperatorExpression(
+ new IdentifierExpression("lhs"),
+ BinaryOperatorType.Equality,
+ new IdentifierExpression("rhs")
+ )
)
)
- }
- };
+ )
+ );
+
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, CreateOperatorOverload(OperatorType.Equality, currentClass, equalsOpBody));
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, CreateOperatorOverload(OperatorType.Inequality, currentClass, notEqualsOpBody));
+ }
- code.Append(indent + "\n" + generator.GenerateCode(CreateOperatorOverload(OverloadableOperatorType.Equality, currentClass, equalsOpBody), indent));
- code.Append(indent + "\n" + generator.GenerateCode(CreateOperatorOverload(OverloadableOperatorType.InEquality, currentClass, notEqualsOpBody), indent));
- }
-
- if (Options.SurroundWithRegion) {
- code.AppendLine(indent + "#endregion");
+ if (Options.SurroundWithRegion) {
+ AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
+ script.InsertAfter(insertedOverrideMethod, new PreProcessorDirective(PreProcessorDirectiveType.Endregion));
+ }
}
- editor.Document.InsertNormalized(insertionEndAnchor.Offset, code.ToString());
-
- return codeForMethodBody;
+ return null;
+ }
+
+ void AppendNewLine(Script script, AstNode afterNode, NewLineNode newLineNode)
+ {
+ if (newLineNode != null)
+ script.InsertAfter(afterNode, newLineNode.Clone());
}
List CreateEqualsOverrides(IType currentClass)
{
List methods = new List();
- AstType boolReference = new SimpleType("System.Boolean");
- AstType objectReference = new SimpleType("System.Object", true);
+ AstType boolReference = ConvertType(KnownTypeCode.Boolean);
+ AstType objectReference = ConvertType(KnownTypeCode.Object);
MethodDeclaration method = new MethodDeclaration {
Name = "Equals",
@@ -275,22 +309,24 @@ namespace CSharpBinding.Refactoring
method.Parameters.Add(new ParameterDeclaration(objectReference, "obj"));
method.Body = new BlockStatement();
- AstType currentType = ConvertType(currentClass.DefaultReturnType);
-
+ AstType currentType = ConvertType(currentClass);
Expression expr = null;
- if (currentClass.ClassType == Dom.ClassType.Struct) {
+ if (currentClass.Kind == TypeKind.Struct) {
// return obj is CurrentType && Equals((CurrentType)obj);
- expr = new IsExpression(new IdentifierExpression("obj"), currentType);
+ expr = new IsExpression() {
+ Expression = new IdentifierExpression("obj"),
+ Type = currentType.Clone()
+ };
expr = new ParenthesizedExpression(expr);
expr = new BinaryOperatorExpression(
- expr, BinaryOperatorType.LogicalAnd,
+ expr, BinaryOperatorType.ConditionalAnd,
new InvocationExpression(
new IdentifierExpression("Equals"),
new List {
- new CastExpression(currentType, new IdentifierExpression("obj"), CastType.Cast)
+ new CastExpression(currentType.Clone(), new IdentifierExpression("obj"))
}));
- method.Body.AddChild(new ReturnStatement(expr));
+ method.Body.Add(new ReturnStatement(expr));
methods.Add(method);
@@ -298,141 +334,132 @@ namespace CSharpBinding.Refactoring
method = new MethodDeclaration {
Name = "Equals",
Modifiers = Modifiers.Public,
- ReturnType = boolReference
+ ReturnType = boolReference.Clone()
};
method.Parameters.Add(new ParameterDeclaration(currentType, "other"));
method.Body = new BlockStatement();
} else {
- method.Body.AddChild(new VariableDeclaration(
+ method.Body.Add(new VariableDeclarationStatement(
+ currentType.Clone(),
"other",
- new CastExpression(currentType, new IdentifierExpression("obj")),
- currentType));
- method.Body.AddChild(new IfElseStatement(
+ new CastExpression(currentType.Clone(), new IdentifierExpression("obj"))));
+ method.Body.Add(new IfElseStatement(
new BinaryOperatorExpression(new IdentifierExpression("other"), BinaryOperatorType.Equality, new PrimitiveExpression(null, "null")),
new ReturnStatement(new PrimitiveExpression(false, "false"))));
-
-// expr = new BinaryOperatorExpression(new ThisReferenceExpression(),
-// BinaryOperatorType.ReferenceEquality,
-// new IdentifierExpression("obj"));
-// method.Body.AddChild(new IfElseStatement(expr, new ReturnStatement(new PrimitiveExpression(true, "true"))));
}
-
expr = null;
- foreach (IField field in currentClass.Fields) {
+ foreach (IField field in currentClass.GetFields()) {
if (field.IsStatic) continue;
if (expr == null) {
expr = TestEquality("other", field);
} else {
- expr = new BinaryOperatorExpression(expr, BinaryOperatorType.LogicalAnd,
+ expr = new BinaryOperatorExpression(expr, BinaryOperatorType.ConditionalAnd,
TestEquality("other", field));
}
}
- foreach (IProperty property in currentClass.Properties) {
+ foreach (IProperty property in currentClass.GetProperties()) {
if (property.IsStatic || !property.IsAutoImplemented()) continue;
if (expr == null) {
expr = TestEquality("other", property);
} else {
- expr = new BinaryOperatorExpression(expr, BinaryOperatorType.LogicalAnd,
+ expr = new BinaryOperatorExpression(expr, BinaryOperatorType.ConditionalAnd,
TestEquality("other", property));
}
}
- method.Body.AddChild(new ReturnStatement(expr ?? new PrimitiveExpression(true, "true")));
+ method.Body.Add(new ReturnStatement(expr ?? new PrimitiveExpression(true, "true")));
methods.Add(method);
return methods;
}
- MethodDeclaration CreateGetHashCodeOverride(IClass currentClass)
+ MethodDeclaration CreateGetHashCodeOverride(ITypeDefinition currentClass)
{
- TypeReference intReference = new TypeReference("System.Int32", true);
- VariableDeclaration hashCodeVar = new VariableDeclaration("hashCode", new PrimitiveExpression(0, "0"), intReference);
+ const string hashCodeVarName = "hashCode";
+ AstType intReference = ConvertType(KnownTypeCode.Int32);
+ VariableDeclarationStatement hashCodeVar = new VariableDeclarationStatement(intReference, hashCodeVarName, new PrimitiveExpression(0, "0"));
+ // Create new method declaration (to insert after main inserted method)
MethodDeclaration getHashCodeMethod = new MethodDeclaration {
Name = "GetHashCode",
- Modifier = Modifiers.Public | Modifiers.Override,
- TypeReference = intReference,
+ Modifiers = Modifiers.Public | Modifiers.Override,
+ ReturnType = intReference.Clone(),
Body = new BlockStatement()
};
- getHashCodeMethod.Body.AddChild(new LocalVariableDeclaration(hashCodeVar));
+ getHashCodeMethod.Body.Add(hashCodeVar);
if (currentClass.Fields.Any(f => !f.IsStatic) || currentClass.Properties.Any(p => !p.IsStatic && p.IsAutoImplemented())) {
- bool usePrimeMultiplication = currentClass.ProjectContent.Language == LanguageProperties.CSharp;
- BlockStatement hashCalculationBlock;
-
- if (usePrimeMultiplication) {
- hashCalculationBlock = new BlockStatement();
- getHashCodeMethod.Body.AddChild(new UncheckedStatement(hashCalculationBlock));
- } else {
- hashCalculationBlock = getHashCodeMethod.Body;
- }
+ bool usePrimeMultiplication = true; // Always leave true for C#?
+ BlockStatement hashCalculationBlock = new BlockStatement();
+ getHashCodeMethod.Body.Add(new UncheckedStatement(hashCalculationBlock));
+// hashCalculationBlock = getHashCodeMethod.Body;
int fieldIndex = 0;
foreach (IField field in currentClass.Fields) {
if (field.IsStatic) continue;
- AddToBlock(hashCodeVar, getHashCodeMethod, usePrimeMultiplication, hashCalculationBlock, ref fieldIndex, field);
+ AddToBlock(hashCodeVarName, usePrimeMultiplication, hashCalculationBlock, ref fieldIndex, field);
}
foreach (IProperty property in currentClass.Properties) {
if (property.IsStatic || !property.IsAutoImplemented()) continue;
- AddToBlock(hashCodeVar, getHashCodeMethod, usePrimeMultiplication, hashCalculationBlock, ref fieldIndex, property);
+ AddToBlock(hashCodeVarName, usePrimeMultiplication, hashCalculationBlock, ref fieldIndex, property);
}
}
- getHashCodeMethod.Body.AddChild(new ReturnStatement(new IdentifierExpression(hashCodeVar.Name)));
+ getHashCodeMethod.Body.Add(new ReturnStatement(new IdentifierExpression(hashCodeVarName)));
return getHashCodeMethod;
}
-
- void AddToBlock(VariableDeclaration hashCodeVar, MethodDeclaration getHashCodeMethod, bool usePrimeMultiplication, BlockStatement hashCalculationBlock, ref int fieldIndex, IField field)
+
+ void AddToBlock(string hashCodeVarName, bool usePrimeMultiplication, BlockStatement hashCalculationBlock, ref int fieldIndex, IField field)
{
Expression expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(field.Name), "GetHashCode"));
if (usePrimeMultiplication) {
int prime = largePrimes[fieldIndex++ % largePrimes.Length];
- expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr));
+ expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr));
} else {
- expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.ExclusiveOr, expr);
+ expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.ExclusiveOr, expr);
}
- if (IsValueType(field.ReturnType)) {
- hashCalculationBlock.AddChild(new ExpressionStatement(expr));
+ if (IsReferenceType(field.ReturnType)) {
+ hashCalculationBlock.Add(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(field.Name), BinaryOperatorType.InEquality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
} else {
- hashCalculationBlock.AddChild(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(field.Name), BinaryOperatorType.ReferenceInequality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
+ hashCalculationBlock.Add(new ExpressionStatement(expr));
}
}
- void AddToBlock(VariableDeclaration hashCodeVar, MethodDeclaration getHashCodeMethod, bool usePrimeMultiplication, BlockStatement hashCalculationBlock, ref int fieldIndex, IProperty property)
+ void AddToBlock(string hashCodeVarName, bool usePrimeMultiplication, BlockStatement hashCalculationBlock, ref int fieldIndex, IProperty property)
{
Expression expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(property.Name), "GetHashCode"));
if (usePrimeMultiplication) {
int prime = largePrimes[fieldIndex++ % largePrimes.Length];
- expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr));
+ expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(prime, prime.ToString()), BinaryOperatorType.Multiply, expr));
} else {
- expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.ExclusiveOr, expr);
+ expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.ExclusiveOr, expr);
}
- if (IsValueType(property.ReturnType)) {
- hashCalculationBlock.AddChild(new ExpressionStatement(expr));
+ if (IsReferenceType(property.ReturnType)) {
+ hashCalculationBlock.Add(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(property.Name), BinaryOperatorType.InEquality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
} else {
- hashCalculationBlock.AddChild(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(property.Name), BinaryOperatorType.ReferenceInequality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
+ hashCalculationBlock.Add(new ExpressionStatement(expr));
}
}
- OperatorDeclaration CreateOperatorOverload(OverloadableOperatorType op, IClass currentClass, BlockStatement body)
+ OperatorDeclaration CreateOperatorOverload(OperatorType op, ITypeDefinition currentClass, BlockStatement body)
{
return new OperatorDeclaration() {
- OverloadableOperator = op,
- TypeReference = new TypeReference("System.Boolean", true),
+ OperatorType = op,
+ ReturnType = ConvertType(KnownTypeCode.Boolean),
Parameters = {
- new ParameterDeclarationExpression(ConvertType(currentClass.DefaultReturnType), "lhs"),
- new ParameterDeclarationExpression(ConvertType(currentClass.DefaultReturnType), "rhs")
+ new ParameterDeclaration(ConvertType(currentClass), "lhs"),
+ new ParameterDeclaration(ConvertType(currentClass), "rhs")
},
- Modifier = Modifiers.Public | Modifiers.Static,
+ Modifiers = Modifiers.Public | Modifiers.Static,
Body = body
};
}
@@ -441,15 +468,28 @@ namespace CSharpBinding.Refactoring
{
base.CancelButtonClick(sender, e);
- editor.Document.Insert(anchor.Offset, baseCall);
- editor.Select(anchor.Offset, baseCall.Length);
+// editor.Document.Insert(anchor.Offset, baseCall);
+// editor.Select(anchor.Offset, baseCall.Length);
+
+ if (baseCallNode != null) {
+ // Insert at least the base call
+ MethodDeclaration insertedOverrideMethod = refactoringContext.GetNode().PrevSibling as MethodDeclaration;
+ if (insertedOverrideMethod == null)
+ {
+ // We are not inside of a method declaration
+ return;
+ }
+ using (Script script = refactoringContext.StartScript()) {
+ script.AddTo(insertedOverrideMethod.Body, baseCallNode);
+ }
+ }
}
protected override void OKButtonClick(object sender, System.Windows.RoutedEventArgs e)
{
base.OKButtonClick(sender, e);
- editor.Caret.Offset = insertionEndAnchor.Offset;
+// editor.Caret.Offset = insertionEndAnchor.Offset;
}
}
}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsRefactoring.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsRefactoring.cs
deleted file mode 100644
index 3b77ad2b81..0000000000
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsRefactoring.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
-// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
-
-using System;
-using System.Linq;
-using ICSharpCode.AvalonEdit.Editing;
-using ICSharpCode.AvalonEdit.Snippets;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Dom;
-using ICSharpCode.SharpDevelop.Dom.Refactoring;
-using ICSharpCode.SharpDevelop.Editor;
-using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
-using SharpRefactoring.Gui;
-
-namespace SharpRefactoring
-{
- public class OverrideEqualsGetHashCodeMethodsRefactoring : ICompletionItemHandler
- {
- public void Insert(CompletionContext context, ICompletionItem item)
- {
- if (item == null)
- throw new ArgumentNullException("item");
-
- if (!(item is OverrideCompletionItem))
- throw new ArgumentException("item is not an OverrideCompletionItem");
-
- OverrideCompletionItem completionItem = item as OverrideCompletionItem;
-
- ITextEditor textEditor = context.Editor;
-
- IEditorUIService uiService = textEditor.GetService(typeof(IEditorUIService)) as IEditorUIService;
-
- if (uiService == null)
- return;
-
- ParseInformation parseInfo = ParserService.GetParseInformation(textEditor.FileName);
-
- if (parseInfo == null)
- return;
-
- CodeGenerator generator = parseInfo.CompilationUnit.Language.CodeGenerator;
- IClass current = parseInfo.CompilationUnit.GetInnermostClass(textEditor.Caret.Line, textEditor.Caret.Column);
- ClassFinder finder = new ClassFinder(current, textEditor.Caret.Line, textEditor.Caret.Column);
-
- if (current == null)
- return;
-
- using (textEditor.Document.OpenUndoGroup()) {
- ITextAnchor startAnchor = textEditor.Document.CreateAnchor(textEditor.Caret.Offset);
- startAnchor.MovementType = AnchorMovementType.BeforeInsertion;
-
- ITextAnchor endAnchor = textEditor.Document.CreateAnchor(textEditor.Caret.Offset);
- endAnchor.MovementType = AnchorMovementType.AfterInsertion;
-
- MethodDeclaration member = (MethodDeclaration)generator.GetOverridingMethod(completionItem.Member, finder);
-
- string indent = DocumentUtilitites.GetWhitespaceBefore(textEditor.Document, textEditor.Caret.Offset);
- string codeForBaseCall = generator.GenerateCode(member.Body.Children.OfType().First(), "");
- string code = generator.GenerateCode(member, indent);
- int marker = code.IndexOf(codeForBaseCall);
-
- textEditor.Document.Insert(startAnchor.Offset, code.Substring(0, marker).TrimStart());
-
- ITextAnchor insertionPos = textEditor.Document.CreateAnchor(endAnchor.Offset);
- insertionPos.MovementType = AnchorMovementType.BeforeInsertion;
-
- InsertionContext insertionContext = new InsertionContext(textEditor.GetService(typeof(TextArea)) as TextArea, startAnchor.Offset);
-
- AbstractInlineRefactorDialog dialog = new OverrideEqualsGetHashCodeMethodsDialog(insertionContext, textEditor, startAnchor, endAnchor, insertionPos, current, completionItem.Member as IMethod, codeForBaseCall.Trim());
- dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog);
-
- textEditor.Document.InsertNormalized(endAnchor.Offset, Environment.NewLine + code.Substring(marker + codeForBaseCall.Length));
-
- insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog);
- insertionContext.RaiseInsertionCompleted(EventArgs.Empty);
- }
- }
-
- public bool Handles(ICompletionItem item)
- {
- return item is OverrideCompletionItem && (item.Text == "GetHashCode()" || item.Text == "Equals(object obj)");
- }
- }
-}
diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs
index c4afba82fc..f3967dcbe6 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs
@@ -25,7 +25,6 @@ namespace CSharpBinding.Refactoring
{
AstNode baseCallNode;
string insertedCode;
- ITextEditor editor;
public OverrideToStringMethodDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor anchor, IList fields, AstNode baseCallNode)
: base(context, editor, anchor)
@@ -34,7 +33,6 @@ namespace CSharpBinding.Refactoring
this.baseCallNode = baseCallNode;
this.listBox.ItemsSource = fields;
- this.editor = editor;
listBox.SelectAll();
}
@@ -45,7 +43,7 @@ namespace CSharpBinding.Refactoring
PrimitiveExpression formatString = new PrimitiveExpression(GenerateFormatString(currentClass, editor.Language.CodeGenerator, fields));
List param = new List() { formatString };
ReturnStatement ret = new ReturnStatement(new InvocationExpression(
- new MemberReferenceExpression(new TypeReferenceExpression(new SimpleType("System.String")), "Format"),
+ new MemberReferenceExpression(new TypeReferenceExpression(ConvertType(KnownTypeCode.String)), "Format"),
param.Concat(fields.Select(f => new IdentifierExpression(f))).ToList()
));