Browse Source

Finished migration of OverrideEqualsGetHash code completion, some improvements for OverrideToString completion, too.

pull/45/merge
Andreas Weizel 12 years ago
parent
commit
e6cb26d43e
  1. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  2. 7
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionDataFactory.cs
  3. 80
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs
  4. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs
  5. 11
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs
  6. 50
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/Options.cs
  7. 374
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs
  8. 85
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsRefactoring.cs
  9. 4
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs

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

@ -73,9 +73,10 @@
<Compile Include="Src\Completion\CSharpMethodInsight.cs" /> <Compile Include="Src\Completion\CSharpMethodInsight.cs" />
<Compile Include="Src\Completion\ImportCompletionData.cs" /> <Compile Include="Src\Completion\ImportCompletionData.cs" />
<Compile Include="Src\Completion\OverrideCompletionData.cs" /> <Compile Include="Src\Completion\OverrideCompletionData.cs" />
<Compile Include="Src\Completion\OverrideGetHashCodeCompletionData.cs" /> <Compile Include="Src\Completion\OverrideEqualsGetHashCodeCompletionData.cs" />
<Compile Include="Src\Completion\OverrideToStringCompletionData.cs" /> <Compile Include="Src\Completion\OverrideToStringCompletionData.cs" />
<Compile Include="Src\Completion\SegmentTrackingOutputFormatter.cs" /> <Compile Include="Src\Completion\SegmentTrackingOutputFormatter.cs" />
<Compile Include="Src\CSharpTextEditorExtension.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" />
<Compile Include="Src\Parser\FoldingVisitor.cs" /> <Compile Include="Src\Parser\FoldingVisitor.cs" />
<Compile Include="Src\Refactoring\AbstractInlineRefactorDialog.cs" /> <Compile Include="Src\Refactoring\AbstractInlineRefactorDialog.cs" />
@ -96,6 +97,9 @@
<Compile Include="Src\Refactoring\IssueManager.cs" /> <Compile Include="Src\Refactoring\IssueManager.cs" />
<Compile Include="Src\Refactoring\IssueOptionsViewModel.cs" /> <Compile Include="Src\Refactoring\IssueOptionsViewModel.cs" />
<Compile Include="Src\Refactoring\MoveTypeToFileContextAction.cs" /> <Compile Include="Src\Refactoring\MoveTypeToFileContextAction.cs" />
<Compile Include="Src\Refactoring\Options.cs" />
<Compile Include="Src\Refactoring\RefactoringExtensions.cs" />
<Compile Include="Src\Refactoring\RenameContextAction.cs" />
<Compile Include="Src\Refactoring\OverrideEqualsGetHashCodeMethodsDialog.xaml.cs"> <Compile Include="Src\Refactoring\OverrideEqualsGetHashCodeMethodsDialog.xaml.cs">
<DependentUpon>OverrideEqualsGetHashCodeMethodsDialog.xaml</DependentUpon> <DependentUpon>OverrideEqualsGetHashCodeMethodsDialog.xaml</DependentUpon>
</Compile> </Compile>

7
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) ICompletionData ICompletionDataFactory.CreateNewOverrideCompletionData(int declarationBegin, IUnresolvedTypeDefinition type, IMember m)
{ {
if ((m.EntityType == EntityType.Method) && (m.Name == "ToString")) if ((m.SymbolKind == SymbolKind.Method) && (m.Name == "ToString"))
return new OverrideToStringCompletionData(declarationBegin, m, contextAtCaret);
else if ((m.EntityType == EntityType.Method) && (m.Name == "GetHashCode"))
return new OverrideToStringCompletionData(declarationBegin, m, contextAtCaret); 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 else
return new OverrideCompletionData(declarationBegin, m, contextAtCaret); return new OverrideCompletionData(declarationBegin, m, contextAtCaret);
} }

80
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideGetHashCodeCompletionData.cs → src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs

@ -26,11 +26,11 @@ using CSharpBinding.Refactoring;
namespace CSharpBinding.Completion namespace CSharpBinding.Completion
{ {
/// <summary> /// <summary>
/// Item for 'override' completion of "GetHashCode()" methods. /// Item for 'override' completion of "Equals()" and "GetHashCode()" methods.
/// </summary> /// </summary>
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) : base(declarationBegin, m, contextAtCaret)
{ {
} }
@ -55,7 +55,7 @@ namespace CSharpBinding.Completion
if (!this.Entity.IsAbstract) { if (!this.Entity.IsAbstract) {
// modify body to call the base method // 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[] { }); var baseCall = new BaseReferenceExpression().Invoke(this.Entity.Name, new Expression[] { });
if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void)) if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void))
baseCallStatement = new ExpressionStatement(baseCall); baseCallStatement = new ExpressionStatement(baseCall);
@ -88,60 +88,26 @@ namespace CSharpBinding.Completion
return; return;
} }
var resolvedCurrent = typeResolveContext.CurrentTypeDefinition; var resolvedCurrent = typeResolveContext.CurrentTypeDefinition;
var entities = FindFieldsAndProperties(resolvedCurrent).ToList(); IEditorUIService uiService = context.Editor.GetService(typeof(IEditorUIService)) as IEditorUIService;
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 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 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;
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); InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, startAnchor.Offset);
// AbstractInlineRefactorDialog dialog = new OverrideToStringMethodDialog(insertionContext, context.Editor, startAnchor, insertionPos, entities, baseCallStatement); var current = typeResolveContext.CurrentTypeDefinition;
// dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog); AbstractInlineRefactorDialog dialog = new OverrideEqualsGetHashCodeMethodsDialog(insertionContext, context.Editor, startAnchor, endAnchor, insertionPos, current, Entity as IMethod, baseCallStatement);
insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog); dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog);
insertionContext.RaiseInsertionCompleted(EventArgs.Empty);
} insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog);
else { insertionContext.RaiseInsertionCompleted(EventArgs.Empty);
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<PropertyOrFieldWrapper> 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++;
} }
} }
} }

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs

@ -55,7 +55,7 @@ namespace CSharpBinding.Completion
if (!this.Entity.IsAbstract) { if (!this.Entity.IsAbstract) {
// modify body to call the base method // 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[] { }); var baseCall = new BaseReferenceExpression().Invoke(this.Entity.Name, new Expression[] { });
if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void)) if (((IMethod)this.Entity).ReturnType.IsKnownType(KnownTypeCode.Void))
baseCallStatement = new ExpressionStatement(baseCall); baseCallStatement = new ExpressionStatement(baseCall);

11
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs

@ -12,6 +12,7 @@ using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Snippets; using ICSharpCode.AvalonEdit.Snippets;
using ICSharpCode.Core.Presentation; using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -93,6 +94,16 @@ namespace CSharpBinding.Refactoring
optionBindings.Add(binding); 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) protected AstType ConvertType(IType type)
{ {
return refactoringContext.CreateShortType(type); return refactoringContext.CreateShortType(type);

50
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
{
/// <summary>
/// Description of Options.
/// </summary>
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); }
}
}
}

374
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) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.CodeDom;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -9,11 +10,9 @@ using System.Text;
using ICSharpCode.AvalonEdit.Snippets; using ICSharpCode.AvalonEdit.Snippets;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using Dom = ICSharpCode.SharpDevelop.Dom; using Dom = ICSharpCode.SharpDevelop.Dom;
@ -24,13 +23,13 @@ namespace CSharpBinding.Refactoring
/// </summary> /// </summary>
public partial class OverrideEqualsGetHashCodeMethodsDialog : AbstractInlineRefactorDialog public partial class OverrideEqualsGetHashCodeMethodsDialog : AbstractInlineRefactorDialog
{ {
IType selectedClass; ITypeDefinition selectedClass;
ITextAnchor startAnchor; ITextAnchor startAnchor;
IMethod selectedMethod; IMethod selectedMethod;
AstNode baseCallNode; AstNode baseCallNode;
public OverrideEqualsGetHashCodeMethodsDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor endAnchor, 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) : base(context, editor, insertionPosition)
{ {
if (selectedClass == null) if (selectedClass == null)
@ -51,15 +50,19 @@ namespace CSharpBinding.Refactoring
addOtherMethod.Content = StringParser.Parse("${res:AddIns.SharpRefactoring.OverrideEqualsGetHashCodeMethods.AddOtherMethod}", new StringTagPair("otherMethod", otherMethod)); addOtherMethod.Content = StringParser.Parse("${res:AddIns.SharpRefactoring.OverrideEqualsGetHashCodeMethods.AddOtherMethod}", new StringTagPair("otherMethod", otherMethod));
addIEquatable.IsEnabled = !selectedClass.BaseTypes.Any( addIEquatable.IsEnabled = !selectedClass.GetAllBaseTypes().Any(
type => { type => {
if (!type.IsGenericReturnType) if (!type.IsParameterized || (type.TypeParameterCount != 1))
return false; return false;
var genericType = type.CastToGenericReturnType(); if (type.FullName != "System.IEquatable")
var boundTo = genericType.TypeParameter.BoundTo;
if (boundTo == null)
return false; 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 return type != null
&& type.FullName != "System.Single" && type.FullName != "System.Single"
&& type.FullName != "System.Double" && type.FullName != "System.Double"
&& (!type.IsReferenceType && (!IsReferenceType(type)
|| type.FullName == "System.String"); || type.FullName == "System.String");
} }
static Expression TestEquality(string other, IField field) Expression TestEquality(string other, IField field)
{ {
if (CanCompareEqualityWithOperator(field.ReturnType)) { if (CanCompareEqualityWithOperator(field.ReturnType)) {
return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name), return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), field.Name),
@ -94,7 +97,7 @@ namespace CSharpBinding.Refactoring
new MemberReferenceExpression(new IdentifierExpression(other), field.Name)); new MemberReferenceExpression(new IdentifierExpression(other), field.Name));
} else { } else {
InvocationExpression ie = new InvocationExpression( 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 ThisReferenceExpression(), field.Name));
ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), 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)) { if (CanCompareEqualityWithOperator(property.ReturnType)) {
return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), property.Name), return new BinaryOperatorExpression(new MemberReferenceExpression(new ThisReferenceExpression(), property.Name),
@ -110,7 +113,7 @@ namespace CSharpBinding.Refactoring
new MemberReferenceExpression(new IdentifierExpression(other), property.Name)); new MemberReferenceExpression(new IdentifierExpression(other), property.Name));
} else { } else {
InvocationExpression ie = new InvocationExpression( 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 ThisReferenceExpression(), property.Name));
ie.Arguments.Add(new MemberReferenceExpression(new IdentifierExpression(other), 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) protected override string GenerateCode(ITypeDefinition currentClass)
{ {
StringBuilder code = new StringBuilder(); StringBuilder code = new StringBuilder();
@ -126,8 +138,18 @@ namespace CSharpBinding.Refactoring
string indent = DocumentUtilitites.GetWhitespaceAfter(editor.Document, line.Offset); 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) { // if (Options.AddIEquatableInterface) {
// TODO : add IEquatable<T> to class // TODO : add IEquatable<T> to class
// IAmbience ambience = currentClass.CompilationUnit.Language.GetAmbience(); // IAmbience ambience = currentClass.CompilationUnit.Language.GetAmbience();
@ -152,120 +174,132 @@ namespace CSharpBinding.Refactoring
// //
// editor.Document.Replace(startOffset, endOffset - startOffset, a); // 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<MethodDeclaration> equalsOverrides = CreateEqualsOverrides(currentClass);
MethodDeclaration defaultOverride = equalsOverrides.First();
equalsOverrides = equalsOverrides.Skip(1).ToList();
StringBuilder builder = new StringBuilder(); if (Options.SurroundWithRegion) {
script.InsertBefore(insertedOverrideMethod, new PreProcessorDirective(PreProcessorDirectiveType.Region, "Equals and GetHashCode implementation"));
foreach (AbstractNode element in defaultOverride.Body.Children.OfType<AbstractNode>()) {
builder.Append(language.CodeGenerator.GenerateCode(element, indent + "\t"));
} }
codeForMethodBody = builder.ToString().Trim(); if ("Equals".Equals(selectedMethod.Name, StringComparison.Ordinal)) {
IList<MethodDeclaration> equalsOverrides = CreateEqualsOverrides(currentClass);
if (addOtherMethod.IsChecked == true) { MethodDeclaration defaultOverride = equalsOverrides.First();
if (equalsOverrides.Any()) equalsOverrides = equalsOverrides.Skip(1).ToList();
code.Append(indent + "\n" + string.Join("\n", equalsOverrides.Select(item => generator.GenerateCode(item, indent))));
code.Append(indent + "\n" + generator.GenerateCode(CreateGetHashCodeOverride(currentClass), indent)); // Insert children of default Equals method into
} foreach (AstNode element in defaultOverride.Body.Children) {
} else { script.AddTo(insertedOverrideMethod.Body, element.Clone());
StringBuilder builder = new StringBuilder(); }
foreach (AbstractNode element in CreateGetHashCodeOverride(currentClass).Body.Children.OfType<AbstractNode>()) { // Add other Equals() overrides after our main inserted method
builder.Append(language.CodeGenerator.GenerateCode(element, indent + "\t")); 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 (Options.AddOperatorOverloads) {
var checkStatements = new[] {
if (addOtherMethod.IsChecked == true) new IfElseStatement(
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<Expression>() { new IdentifierExpression("lhs"), new IdentifierExpression("rhs") }
),
new ReturnStatement(new PrimitiveExpression(true))
),
new IfElseStatement(
new BinaryOperatorExpression(
new InvocationExpression( new InvocationExpression(
new IdentifierExpression("ReferenceEquals"), new IdentifierExpression("ReferenceEquals"),
new List<Expression>() { new IdentifierExpression("lhs"), new PrimitiveExpression(null) } new List<Expression>() { new IdentifierExpression("lhs"), new IdentifierExpression("rhs") }
), ),
BinaryOperatorType.LogicalOr, new ReturnStatement(new PrimitiveExpression(true))
new InvocationExpression(
new IdentifierExpression("ReferenceEquals"),
new List<Expression>() { new IdentifierExpression("rhs"), new PrimitiveExpression(null) }
)
), ),
new ReturnStatement(new PrimitiveExpression(false)) new IfElseStatement(
) new BinaryOperatorExpression(
}; new InvocationExpression(
new IdentifierExpression("ReferenceEquals"),
BlockStatement equalsOpBody = new BlockStatement() { new List<Expression>() { new IdentifierExpression("lhs"), new PrimitiveExpression(null) }
Children = { ),
BinaryOperatorType.ConditionalOr,
new InvocationExpression(
new IdentifierExpression("ReferenceEquals"),
new List<Expression>() { 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 ReturnStatement(
new InvocationExpression( new InvocationExpression(
new MemberReferenceExpression(new IdentifierExpression("lhs"), "Equals"), new MemberReferenceExpression(new IdentifierExpression("lhs"), "Equals"),
new List<Expression>() { new IdentifierExpression("rhs") } new List<Expression>() { new IdentifierExpression("rhs") }
) )
) )
} );
};
if (currentClass.ClassType == Dom.ClassType.Class) {
equalsOpBody.Children.InsertRange(0, checkStatements);
}
BlockStatement notEqualsOpBody = new BlockStatement() { BlockStatement notEqualsOpBody = new BlockStatement();
Children = { notEqualsOpBody.Add(new ReturnStatement(
new ReturnStatement( new UnaryOperatorExpression(
new UnaryOperatorExpression( UnaryOperatorType.Not,
new ParenthesizedExpression( new ParenthesizedExpression(
new BinaryOperatorExpression( new BinaryOperatorExpression(
new IdentifierExpression("lhs"), new IdentifierExpression("lhs"),
BinaryOperatorType.Equality, BinaryOperatorType.Equality,
new IdentifierExpression("rhs") new IdentifierExpression("rhs")
) )
),
UnaryOperatorType.Not
) )
) )
} )
}; );
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)); if (Options.SurroundWithRegion) {
code.Append(indent + "\n" + generator.GenerateCode(CreateOperatorOverload(OverloadableOperatorType.InEquality, currentClass, notEqualsOpBody), indent)); AppendNewLine(script, insertedOverrideMethod, nextNewLineNode);
} script.InsertAfter(insertedOverrideMethod, new PreProcessorDirective(PreProcessorDirectiveType.Endregion));
}
if (Options.SurroundWithRegion) {
code.AppendLine(indent + "#endregion");
} }
editor.Document.InsertNormalized(insertionEndAnchor.Offset, code.ToString()); return null;
}
return codeForMethodBody;
void AppendNewLine(Script script, AstNode afterNode, NewLineNode newLineNode)
{
if (newLineNode != null)
script.InsertAfter(afterNode, newLineNode.Clone());
} }
List<MethodDeclaration> CreateEqualsOverrides(IType currentClass) List<MethodDeclaration> CreateEqualsOverrides(IType currentClass)
{ {
List<MethodDeclaration> methods = new List<MethodDeclaration>(); List<MethodDeclaration> methods = new List<MethodDeclaration>();
AstType boolReference = new SimpleType("System.Boolean"); AstType boolReference = ConvertType(KnownTypeCode.Boolean);
AstType objectReference = new SimpleType("System.Object", true); AstType objectReference = ConvertType(KnownTypeCode.Object);
MethodDeclaration method = new MethodDeclaration { MethodDeclaration method = new MethodDeclaration {
Name = "Equals", Name = "Equals",
@ -275,22 +309,24 @@ namespace CSharpBinding.Refactoring
method.Parameters.Add(new ParameterDeclaration(objectReference, "obj")); method.Parameters.Add(new ParameterDeclaration(objectReference, "obj"));
method.Body = new BlockStatement(); method.Body = new BlockStatement();
AstType currentType = ConvertType(currentClass.DefaultReturnType); AstType currentType = ConvertType(currentClass);
Expression expr = null; Expression expr = null;
if (currentClass.ClassType == Dom.ClassType.Struct) { if (currentClass.Kind == TypeKind.Struct) {
// return obj is CurrentType && Equals((CurrentType)obj); // 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 ParenthesizedExpression(expr);
expr = new BinaryOperatorExpression( expr = new BinaryOperatorExpression(
expr, BinaryOperatorType.LogicalAnd, expr, BinaryOperatorType.ConditionalAnd,
new InvocationExpression( new InvocationExpression(
new IdentifierExpression("Equals"), new IdentifierExpression("Equals"),
new List<Expression> { new List<Expression> {
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); methods.Add(method);
@ -298,141 +334,132 @@ namespace CSharpBinding.Refactoring
method = new MethodDeclaration { method = new MethodDeclaration {
Name = "Equals", Name = "Equals",
Modifiers = Modifiers.Public, Modifiers = Modifiers.Public,
ReturnType = boolReference ReturnType = boolReference.Clone()
}; };
method.Parameters.Add(new ParameterDeclaration(currentType, "other")); method.Parameters.Add(new ParameterDeclaration(currentType, "other"));
method.Body = new BlockStatement(); method.Body = new BlockStatement();
} else { } else {
method.Body.AddChild(new VariableDeclaration( method.Body.Add(new VariableDeclarationStatement(
currentType.Clone(),
"other", "other",
new CastExpression(currentType, new IdentifierExpression("obj")), new CastExpression(currentType.Clone(), new IdentifierExpression("obj"))));
currentType)); method.Body.Add(new IfElseStatement(
method.Body.AddChild(new IfElseStatement(
new BinaryOperatorExpression(new IdentifierExpression("other"), BinaryOperatorType.Equality, new PrimitiveExpression(null, "null")), new BinaryOperatorExpression(new IdentifierExpression("other"), BinaryOperatorType.Equality, new PrimitiveExpression(null, "null")),
new ReturnStatement(new PrimitiveExpression(false, "false")))); 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; expr = null;
foreach (IField field in currentClass.Fields) { foreach (IField field in currentClass.GetFields()) {
if (field.IsStatic) continue; if (field.IsStatic) continue;
if (expr == null) { if (expr == null) {
expr = TestEquality("other", field); expr = TestEquality("other", field);
} else { } else {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.LogicalAnd, expr = new BinaryOperatorExpression(expr, BinaryOperatorType.ConditionalAnd,
TestEquality("other", field)); TestEquality("other", field));
} }
} }
foreach (IProperty property in currentClass.Properties) { foreach (IProperty property in currentClass.GetProperties()) {
if (property.IsStatic || !property.IsAutoImplemented()) continue; if (property.IsStatic || !property.IsAutoImplemented()) continue;
if (expr == null) { if (expr == null) {
expr = TestEquality("other", property); expr = TestEquality("other", property);
} else { } else {
expr = new BinaryOperatorExpression(expr, BinaryOperatorType.LogicalAnd, expr = new BinaryOperatorExpression(expr, BinaryOperatorType.ConditionalAnd,
TestEquality("other", property)); 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); methods.Add(method);
return methods; return methods;
} }
MethodDeclaration CreateGetHashCodeOverride(IClass currentClass) MethodDeclaration CreateGetHashCodeOverride(ITypeDefinition currentClass)
{ {
TypeReference intReference = new TypeReference("System.Int32", true); const string hashCodeVarName = "hashCode";
VariableDeclaration hashCodeVar = new VariableDeclaration("hashCode", new PrimitiveExpression(0, "0"), intReference); 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 { MethodDeclaration getHashCodeMethod = new MethodDeclaration {
Name = "GetHashCode", Name = "GetHashCode",
Modifier = Modifiers.Public | Modifiers.Override, Modifiers = Modifiers.Public | Modifiers.Override,
TypeReference = intReference, ReturnType = intReference.Clone(),
Body = new BlockStatement() 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())) { if (currentClass.Fields.Any(f => !f.IsStatic) || currentClass.Properties.Any(p => !p.IsStatic && p.IsAutoImplemented())) {
bool usePrimeMultiplication = currentClass.ProjectContent.Language == LanguageProperties.CSharp; bool usePrimeMultiplication = true; // Always leave true for C#?
BlockStatement hashCalculationBlock; BlockStatement hashCalculationBlock = new BlockStatement();
getHashCodeMethod.Body.Add(new UncheckedStatement(hashCalculationBlock));
if (usePrimeMultiplication) { // hashCalculationBlock = getHashCodeMethod.Body;
hashCalculationBlock = new BlockStatement();
getHashCodeMethod.Body.AddChild(new UncheckedStatement(hashCalculationBlock));
} else {
hashCalculationBlock = getHashCodeMethod.Body;
}
int fieldIndex = 0; int fieldIndex = 0;
foreach (IField field in currentClass.Fields) { foreach (IField field in currentClass.Fields) {
if (field.IsStatic) continue; 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) { foreach (IProperty property in currentClass.Properties) {
if (property.IsStatic || !property.IsAutoImplemented()) continue; 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; 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")); Expression expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(field.Name), "GetHashCode"));
if (usePrimeMultiplication) { if (usePrimeMultiplication) {
int prime = largePrimes[fieldIndex++ % largePrimes.Length]; 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 { } else {
expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.ExclusiveOr, expr); expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.ExclusiveOr, expr);
} }
if (IsValueType(field.ReturnType)) { if (IsReferenceType(field.ReturnType)) {
hashCalculationBlock.AddChild(new ExpressionStatement(expr)); hashCalculationBlock.Add(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(field.Name), BinaryOperatorType.InEquality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
} else { } 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")); Expression expr = new InvocationExpression(new MemberReferenceExpression(new IdentifierExpression(property.Name), "GetHashCode"));
if (usePrimeMultiplication) { if (usePrimeMultiplication) {
int prime = largePrimes[fieldIndex++ % largePrimes.Length]; 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 { } else {
expr = new AssignmentExpression(new IdentifierExpression(hashCodeVar.Name), AssignmentOperatorType.ExclusiveOr, expr); expr = new AssignmentExpression(new IdentifierExpression(hashCodeVarName), AssignmentOperatorType.ExclusiveOr, expr);
} }
if (IsValueType(property.ReturnType)) { if (IsReferenceType(property.ReturnType)) {
hashCalculationBlock.AddChild(new ExpressionStatement(expr)); hashCalculationBlock.Add(new IfElseStatement(new BinaryOperatorExpression(new IdentifierExpression(property.Name), BinaryOperatorType.InEquality, new PrimitiveExpression(null, "null")), new ExpressionStatement(expr)));
} else { } 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() { return new OperatorDeclaration() {
OverloadableOperator = op, OperatorType = op,
TypeReference = new TypeReference("System.Boolean", true), ReturnType = ConvertType(KnownTypeCode.Boolean),
Parameters = { Parameters = {
new ParameterDeclarationExpression(ConvertType(currentClass.DefaultReturnType), "lhs"), new ParameterDeclaration(ConvertType(currentClass), "lhs"),
new ParameterDeclarationExpression(ConvertType(currentClass.DefaultReturnType), "rhs") new ParameterDeclaration(ConvertType(currentClass), "rhs")
}, },
Modifier = Modifiers.Public | Modifiers.Static, Modifiers = Modifiers.Public | Modifiers.Static,
Body = body Body = body
}; };
} }
@ -441,15 +468,28 @@ namespace CSharpBinding.Refactoring
{ {
base.CancelButtonClick(sender, e); base.CancelButtonClick(sender, e);
editor.Document.Insert(anchor.Offset, baseCall); // editor.Document.Insert(anchor.Offset, baseCall);
editor.Select(anchor.Offset, baseCall.Length); // 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) protected override void OKButtonClick(object sender, System.Windows.RoutedEventArgs e)
{ {
base.OKButtonClick(sender, e); base.OKButtonClick(sender, e);
editor.Caret.Offset = insertionEndAnchor.Offset; // editor.Caret.Offset = insertionEndAnchor.Offset;
} }
} }
} }

85
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsRefactoring.cs

@ -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<AbstractNode>().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)");
}
}
}

4
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs

@ -25,7 +25,6 @@ namespace CSharpBinding.Refactoring
{ {
AstNode baseCallNode; AstNode baseCallNode;
string insertedCode; string insertedCode;
ITextEditor editor;
public OverrideToStringMethodDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor anchor, IList<PropertyOrFieldWrapper> fields, AstNode baseCallNode) public OverrideToStringMethodDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor anchor, IList<PropertyOrFieldWrapper> fields, AstNode baseCallNode)
: base(context, editor, anchor) : base(context, editor, anchor)
@ -34,7 +33,6 @@ namespace CSharpBinding.Refactoring
this.baseCallNode = baseCallNode; this.baseCallNode = baseCallNode;
this.listBox.ItemsSource = fields; this.listBox.ItemsSource = fields;
this.editor = editor;
listBox.SelectAll(); listBox.SelectAll();
} }
@ -45,7 +43,7 @@ namespace CSharpBinding.Refactoring
PrimitiveExpression formatString = new PrimitiveExpression(GenerateFormatString(currentClass, editor.Language.CodeGenerator, fields)); PrimitiveExpression formatString = new PrimitiveExpression(GenerateFormatString(currentClass, editor.Language.CodeGenerator, fields));
List<Expression> param = new List<Expression>() { formatString }; List<Expression> param = new List<Expression>() { formatString };
ReturnStatement ret = new ReturnStatement(new InvocationExpression( 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() param.Concat(fields.Select(f => new IdentifierExpression(f))).ToList()
)); ));

Loading…
Cancel
Save