From e0fb42221eb4eaf163040cdb252a83afba68430e Mon Sep 17 00:00:00 2001 From: Andreas Weizel Date: Sat, 15 Jun 2013 15:17:24 +0200 Subject: [PATCH] Detecting all properties and fields and handling editor undo properly in InsertCtor/Override...Method dialogs. --- ...OverrideEqualsGetHashCodeCompletionData.cs | 7 +-- .../OverrideToStringCompletionData.cs | 13 ++--- .../AbstractInlineRefactorDialog.cs | 37 ++++++++------ .../Src/Refactoring/InsertCtorDialog.xaml.cs | 50 ++++++++++++++++--- .../InsertCtorSnippetRefactoring.cs | 48 +----------------- ...rideEqualsGetHashCodeMethodsDialog.xaml.cs | 24 +-------- .../OverrideToStringMethodDialog.xaml.cs | 6 ++- 7 files changed, 83 insertions(+), 102 deletions(-) diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs index 1f88e9e82f..10916c6c32 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs @@ -73,6 +73,9 @@ namespace CSharpBinding.Completion var segmentDict = SegmentTrackingOutputFormatter.WriteNode(w, entityDeclaration, formattingOptions, context.Editor.Options); using (document.OpenUndoGroup()) { + InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, declarationBegin); + insertionContext.InsertionPosition = context.Editor.Caret.Offset; + string newText = w.ToString().TrimEnd(); document.Replace(declarationBegin, context.EndOffset - declarationBegin, newText); var throwStatement = entityDeclaration.Descendants.FirstOrDefault(n => n is ThrowStatement); @@ -99,10 +102,8 @@ namespace CSharpBinding.Completion 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); - var current = typeResolveContext.CurrentTypeDefinition; - AbstractInlineRefactorDialog dialog = new OverrideEqualsGetHashCodeMethodsDialog(insertionContext, context.Editor, startAnchor, endAnchor, insertionPos, current, Entity as IMethod, baseCallStatement); + AbstractInlineRefactorDialog dialog = new OverrideEqualsGetHashCodeMethodsDialog(insertionContext, context.Editor, endAnchor, insertionPos, current, Entity as IMethod, baseCallStatement); dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs index 04f6709134..c49d86eac3 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs @@ -73,6 +73,9 @@ namespace CSharpBinding.Completion var segmentDict = SegmentTrackingOutputFormatter.WriteNode(w, entityDeclaration, formattingOptions, context.Editor.Options); using (document.OpenUndoGroup()) { + InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, declarationBegin); + insertionContext.InsertionPosition = context.Editor.Caret.Offset; + string newText = w.ToString().TrimEnd(); document.Replace(declarationBegin, context.EndOffset - declarationBegin, newText); var throwStatement = entityDeclaration.Descendants.FirstOrDefault(n => n is ThrowStatement); @@ -101,15 +104,11 @@ namespace CSharpBinding.Completion 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); + AbstractInlineRefactorDialog dialog = new OverrideToStringMethodDialog(insertionContext, context.Editor, insertionPos, entities, baseCallStatement); dialog.Element = uiService.CreateInlineUIElement(insertionPos, dialog); insertionContext.RegisterActiveElement(new InlineRefactorSnippetElement(cxt => null, ""), dialog); - insertionContext.RaiseInsertionCompleted(EventArgs.Empty); - } - else { + } else { if (baseCallStatement != null) { // Add default base call MethodDeclaration insertedOverrideMethod = refactoringContext.GetNode().PrevSibling as MethodDeclaration; @@ -123,6 +122,8 @@ namespace CSharpBinding.Completion } } } + + insertionContext.RaiseInsertionCompleted(EventArgs.Empty); } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs index 228b28f8d5..2431cfe6d4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs @@ -41,7 +41,6 @@ namespace CSharpBinding.Refactoring this.anchor = insertionEndAnchor = anchor; this.editor = editor; this.insertionContext = context; - this.refactoringContext = SDRefactoringContext.Create(editor, CancellationToken.None); this.Background = SystemColors.ControlBrush; } @@ -51,29 +50,31 @@ namespace CSharpBinding.Refactoring Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate { this.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); })); } + protected void AppendNewLine(Script script, AstNode afterNode, NewLineNode newLineNode) + { + if (newLineNode != null) + script.InsertAfter(afterNode, newLineNode.Clone()); + } + protected abstract string GenerateCode(ITypeDefinition currentClass); protected virtual void OKButtonClick(object sender, RoutedEventArgs e) { - ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName); - if (optionBindings != null) { foreach (OptionBinding binding in optionBindings) binding.Save(); } - if (parseInfo != null) { - var typeResolveContext = refactoringContext.GetTypeResolveContext(); - if (typeResolveContext == null) { - return; - } - var current = typeResolveContext.CurrentTypeDefinition; - - using (editor.Document.OpenUndoGroup()) { - // GenerateCode could modify the document. - // So read anchor.Offset after code generation. - GenerateCode(current); - } + var typeResolveContext = refactoringContext.GetTypeResolveContext(); + if (typeResolveContext == null) { + return; + } + var current = typeResolveContext.CurrentTypeDefinition; + + using (editor.Document.OpenUndoGroup()) { + // GenerateCode could modify the document. + // So read anchor.Offset after code generation. + GenerateCode(current); } Deactivate(); @@ -122,8 +123,14 @@ namespace CSharpBinding.Refactoring OnInsertionCompleted(); } + protected virtual void Initialize() + { + this.refactoringContext = SDRefactoringContext.Create(editor, CancellationToken.None); + } + protected virtual void OnInsertionCompleted() { + Initialize(); FocusFirstElement(); } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs index 1e80c9324d..912b4ea009 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs @@ -7,12 +7,14 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; +using System.Threading; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Threading; using ICSharpCode.AvalonEdit.Snippets; +using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Resolver; @@ -20,6 +22,7 @@ using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Parser; namespace CSharpBinding.Refactoring { @@ -30,15 +33,49 @@ namespace CSharpBinding.Refactoring { IList parameterList; - public InsertCtorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor, IUnresolvedTypeDefinition current, IList possibleParameters) + public InsertCtorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor) : base(context, editor, anchor) { InitializeComponent(); - this.varList.ItemsSource = parameterList = possibleParameters; + Visibility = System.Windows.Visibility.Collapsed; + } + + protected override void Initialize() + { + base.Initialize(); - if (!parameterList.Any()) - Visibility = System.Windows.Visibility.Collapsed; + var typeResolveContext = refactoringContext.GetTypeResolveContext(); + if (typeResolveContext == null) { + return; + } + var resolvedCurrent = typeResolveContext.CurrentTypeDefinition; + + parameterList = CreateCtorParams(resolvedCurrent).ToList(); + this.varList.ItemsSource = parameterList; + + if (parameterList.Any()) + Visibility = System.Windows.Visibility.Visible; + } + + IEnumerable CreateCtorParams(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.CanSet && !prop.IsIndexer + && prop.IsAutoImplemented() + && prop.IsStatic == sourceType.GetDefinition().IsStatic + && prop.ReturnType != null)) { + yield return new PropertyOrFieldWrapper(p) { Index = i }; + i++; + } } protected override string GenerateCode(ITypeDefinition currentClass) @@ -46,8 +83,9 @@ namespace CSharpBinding.Refactoring List filtered = this.varList.SelectedItems.OfType() .OrderBy(p => p.Index) .ToList(); - - var insertedConstructor = refactoringContext.GetNode(); + + var test = refactoringContext.GetNode(); + var insertedConstructor = refactoringContext.GetNode().PrevSibling as ConstructorDeclaration; if (insertedConstructor == null) { // We are not inside of a constructor declaration diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs index ff839761c4..089bc89741 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs @@ -39,60 +39,14 @@ namespace CSharpBinding.Refactoring if (uiService == null) return null; - ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(textEditor.FileName); - - if (parseInfo == null) - return null; - - // cannot use insertion position at this point, because it might not be - // valid, because we are still generating the elements. - // DOM is not updated - TextLocation loc = context.Document.GetLocation(context.StartPosition); - - IUnresolvedTypeDefinition current = parseInfo.UnresolvedFile.GetInnermostTypeDefinition(loc); - if (current == null) - return null; - - var refactoringContext = SDRefactoringContext.Create(textEditor, CancellationToken.None); - var typeResolveContext = refactoringContext.GetTypeResolveContext(); - if (typeResolveContext == null) { - return null; - } - var resolvedCurrent = typeResolveContext.CurrentTypeDefinition; - - List parameters = CreateCtorParams(resolvedCurrent).ToList(); - - if (!parameters.Any()) - return null; - ITextAnchor anchor = textEditor.Document.CreateAnchor(context.InsertionPosition); anchor.MovementType = AnchorMovementType.BeforeInsertion; - InsertCtorDialog dialog = new InsertCtorDialog(context, textEditor, anchor, current, parameters); + InsertCtorDialog dialog = new InsertCtorDialog(context, textEditor, anchor); dialog.Element = uiService.CreateInlineUIElement(anchor, dialog); return dialog; } - - IEnumerable CreateCtorParams(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.CanSet && !prop.IsIndexer - && prop.IsAutoImplemented() - && prop.IsStatic == sourceType.GetDefinition().IsStatic - && prop.ReturnType != null)) { - yield return new PropertyOrFieldWrapper(p) { Index = i }; - i++; - } - } } } 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 732391c8bb..9a7115b3ae 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideEqualsGetHashCodeMethodsDialog.xaml.cs @@ -24,11 +24,10 @@ namespace CSharpBinding.Refactoring public partial class OverrideEqualsGetHashCodeMethodsDialog : AbstractInlineRefactorDialog { ITypeDefinition selectedClass; - ITextAnchor startAnchor; IMethod selectedMethod; AstNode baseCallNode; - public OverrideEqualsGetHashCodeMethodsDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor endAnchor, + public OverrideEqualsGetHashCodeMethodsDialog(InsertionContext context, ITextEditor editor, ITextAnchor endAnchor, ITextAnchor insertionPosition, ITypeDefinition selectedClass, IMethod selectedMethod, AstNode baseCallNode) : base(context, editor, insertionPosition) { @@ -38,7 +37,6 @@ namespace CSharpBinding.Refactoring InitializeComponent(); this.selectedClass = selectedClass; - this.startAnchor = startAnchor; this.insertionEndAnchor = endAnchor; this.selectedMethod = selectedMethod; this.baseCallNode = baseCallNode; @@ -57,12 +55,6 @@ namespace CSharpBinding.Refactoring if (type.FullName != "System.IEquatable") return false; 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; } ); } @@ -132,14 +124,6 @@ namespace CSharpBinding.Refactoring protected override string GenerateCode(ITypeDefinition currentClass) { - StringBuilder code = new StringBuilder(); - - var line = editor.Document.GetLineByOffset(startAnchor.Offset); - - string indent = DocumentUtilities.GetWhitespaceAfter(editor.Document, line.Offset); - -// CodeGenerator generator = language.CodeGenerator; - MethodDeclaration insertedOverrideMethod = refactoringContext.GetNode().PrevSibling as MethodDeclaration; if (insertedOverrideMethod == null) { @@ -288,12 +272,6 @@ namespace CSharpBinding.Refactoring 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(); 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 f3967dcbe6..67f336cc6c 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/OverrideToStringMethodDialog.xaml.cs @@ -24,9 +24,8 @@ namespace CSharpBinding.Refactoring public partial class OverrideToStringMethodDialog : AbstractInlineRefactorDialog { AstNode baseCallNode; - string insertedCode; - public OverrideToStringMethodDialog(InsertionContext context, ITextEditor editor, ITextAnchor startAnchor, ITextAnchor anchor, IList fields, AstNode baseCallNode) + public OverrideToStringMethodDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor, IList fields, AstNode baseCallNode) : base(context, editor, anchor) { InitializeComponent(); @@ -56,8 +55,11 @@ namespace CSharpBinding.Refactoring } using (Script script = refactoringContext.StartScript()) { + NewLineNode nextNewLineNode = insertedOverrideMethod.NextSibling as NewLineNode; + // Find base method call and replace it by return statement script.AddTo(insertedOverrideMethod.Body, ret); + AppendNewLine(script, insertedOverrideMethod, nextNewLineNode); } }