9 changed files with 765 additions and 6 deletions
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
// 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.Collections.Generic; |
||||
using System.Threading; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using System.Windows.Threading; |
||||
|
||||
using ICSharpCode.AvalonEdit.Snippets; |
||||
using ICSharpCode.Core.Presentation; |
||||
using ICSharpCode.NRefactory.CSharp; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using CSharpBinding.Refactoring; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
public abstract class AbstractInlineRefactorDialog : GroupBox, IOptionBindingContainer, IActiveElement |
||||
{ |
||||
protected ITextAnchor anchor; |
||||
protected ITextAnchor insertionEndAnchor; |
||||
protected ITextEditor editor; |
||||
|
||||
protected SDRefactoringContext refactoringContext; |
||||
protected InsertionContext insertionContext; |
||||
|
||||
public IInlineUIElement Element { get; set; } |
||||
|
||||
protected AbstractInlineRefactorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor) |
||||
{ |
||||
if (context == null) |
||||
throw new ArgumentNullException("context"); |
||||
|
||||
this.anchor = insertionEndAnchor = anchor; |
||||
this.editor = editor; |
||||
this.insertionContext = context; |
||||
this.refactoringContext = SDRefactoringContext.Create(editor, CancellationToken.None); |
||||
|
||||
this.Background = SystemColors.ControlBrush; |
||||
} |
||||
|
||||
protected virtual void FocusFirstElement() |
||||
{ |
||||
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate { this.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); })); |
||||
} |
||||
|
||||
protected abstract string GenerateCode(IUnresolvedTypeDefinition 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) { |
||||
IUnresolvedTypeDefinition current = parseInfo.UnresolvedFile.GetInnermostTypeDefinition(anchor.Line, anchor.Column); |
||||
|
||||
using (editor.Document.OpenUndoGroup()) { |
||||
// GenerateCode could modify the document.
|
||||
// So read anchor.Offset after code generation.
|
||||
GenerateCode(current); |
||||
} |
||||
} |
||||
|
||||
Deactivate(); |
||||
} |
||||
|
||||
protected virtual void CancelButtonClick(object sender, RoutedEventArgs e) |
||||
{ |
||||
Deactivate(); |
||||
} |
||||
|
||||
List<OptionBinding> optionBindings; |
||||
|
||||
public void AddBinding(OptionBinding binding) |
||||
{ |
||||
if (optionBindings == null) |
||||
optionBindings = new List<OptionBinding>(); |
||||
|
||||
optionBindings.Add(binding); |
||||
} |
||||
|
||||
protected AstType ConvertType(IType type) |
||||
{ |
||||
return refactoringContext.CreateShortType(type); |
||||
} |
||||
|
||||
bool IActiveElement.IsEditable { |
||||
get { return false; } |
||||
} |
||||
|
||||
ISegment IActiveElement.Segment { |
||||
get { return null; } |
||||
} |
||||
|
||||
void IActiveElement.OnInsertionCompleted() |
||||
{ |
||||
OnInsertionCompleted(); |
||||
} |
||||
|
||||
protected virtual void OnInsertionCompleted() |
||||
{ |
||||
FocusFirstElement(); |
||||
} |
||||
|
||||
void IActiveElement.Deactivate(SnippetEventArgs e) |
||||
{ |
||||
if (e.Reason == DeactivateReason.Deleted) { |
||||
Deactivate(); |
||||
return; |
||||
} |
||||
|
||||
if (e.Reason == DeactivateReason.ReturnPressed) |
||||
OKButtonClick(null, null); |
||||
|
||||
if (e.Reason == DeactivateReason.EscapePressed) |
||||
CancelButtonClick(null, null); |
||||
|
||||
Deactivate(); |
||||
} |
||||
|
||||
bool deactivated; |
||||
|
||||
void Deactivate() |
||||
{ |
||||
if (Element == null) |
||||
throw new InvalidOperationException("no IInlineUIElement set!"); |
||||
if (deactivated) |
||||
return; |
||||
|
||||
deactivated = true; |
||||
Element.Remove(); |
||||
|
||||
insertionContext.Deactivate(null); |
||||
} |
||||
|
||||
protected Key? GetAccessKeyFromButton(ContentControl control) |
||||
{ |
||||
if (control == null) |
||||
return null; |
||||
string text = control.Content as string; |
||||
if (text == null) |
||||
return null; |
||||
int index = text.IndexOf('_'); |
||||
if (index < 0 || index > text.Length - 2) |
||||
return null; |
||||
char ch = text[index + 1]; |
||||
// works only for letter keys!
|
||||
return (Key)new KeyConverter().ConvertFrom(ch.ToString()); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
// 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 System.Windows.Documents; |
||||
|
||||
using ICSharpCode.AvalonEdit.Snippets; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
class InlineRefactorSnippetElement : SnippetElement |
||||
{ |
||||
Func<InsertionContext, AbstractInlineRefactorDialog> createDialog; |
||||
string previewText; |
||||
|
||||
public InlineRefactorSnippetElement(Func<InsertionContext, AbstractInlineRefactorDialog> createDialog, string previewText) |
||||
{ |
||||
this.createDialog = createDialog; |
||||
this.previewText = previewText; |
||||
} |
||||
|
||||
public override void Insert(InsertionContext context) |
||||
{ |
||||
AbstractInlineRefactorDialog dialog = createDialog(context); |
||||
if (dialog != null) |
||||
context.RegisterActiveElement(this, dialog); |
||||
} |
||||
|
||||
public override Inline ToTextRun() |
||||
{ |
||||
return new Italic() { Inlines = { previewText } }; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
<ref:AbstractInlineRefactorDialog x:Class="CSharpBinding.Refactoring.InsertCtorDialog" |
||||
Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor}" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:ref="clr-namespace:CSharpBinding.Refactoring" |
||||
xmlns:sd="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||
<ref:AbstractInlineRefactorDialog.Resources> |
||||
<ref:IntToBoolConverter x:Key="intToBoolConverter" /> |
||||
<Style TargetType="Button" BasedOn="{x:Static sd:GlobalStyles.ButtonStyle}"/> |
||||
</ref:AbstractInlineRefactorDialog.Resources> |
||||
<Grid Cursor="Arrow" KeyboardNavigation.TabNavigation="Cycle"> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto" /> |
||||
<RowDefinition Height="*" /> |
||||
<RowDefinition Height="Auto" /> |
||||
</Grid.RowDefinitions> |
||||
<TextBlock Margin="3" |
||||
Text="{sd:Localize AddIns.SharpRefactoring.InsertCtor.Description}" |
||||
TextWrapping="Wrap" /> |
||||
<ListView x:Name="varList" Grid.Row="1" |
||||
SelectionMode="Multiple" KeyboardNavigation.TabNavigation="Cycle" |
||||
ItemContainerStyle="{x:Static sd:GlobalStyles.ListViewItemFocusHighlightStyle}" MaxHeight="300"> |
||||
<ListView.View> |
||||
<GridView> |
||||
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.VariableLabel}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<CheckBox Content="{Binding Text}" IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.AddCheckForNullLabel}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<CheckBox IsChecked="{Binding AddCheckForNull, Mode=TwoWay}" IsEnabled="{Binding IsNullable}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.AddRangeCheckLabel}"> |
||||
<GridViewColumn.CellTemplate> |
||||
<DataTemplate> |
||||
<CheckBox IsChecked="{Binding AddRangeCheck, Mode=TwoWay}" IsEnabled="{Binding HasRange}" /> |
||||
</DataTemplate> |
||||
</GridViewColumn.CellTemplate> |
||||
</GridViewColumn> |
||||
</GridView> |
||||
</ListView.View> |
||||
</ListView> |
||||
<DockPanel Grid.Row="2" LastChildFill="False"> |
||||
<Button DockPanel.Dock="Left" Content="{sd:Localize Global.OKButtonText}" Margin="3" Click="OKButtonClick" /> |
||||
<Button DockPanel.Dock="Left" Content="{sd:Localize Global.CancelButtonText}" Margin="3" Click="CancelButtonClick" /> |
||||
<Button x:Name="moveDown" DockPanel.Dock="Right" Content="{sd:Localize Global.MoveDown}" Margin="3" IsEnabled="{Binding SelectedIndex, ElementName=varList, Converter={StaticResource intToBoolConverter}}" Click="DownClick" /> |
||||
<Button x:Name="moveUp" DockPanel.Dock="Right" Content="{sd:Localize Global.MoveUp}" Margin="3" IsEnabled="{Binding SelectedIndex, ElementName=varList, Converter={StaticResource intToBoolConverter}}" Click="UpClick" /> |
||||
<ToggleButton x:Name="selectAll" DockPanel.Dock="Right" Content="{sd:Localize Global.SelectAllButtonText}" Margin="3" IsChecked="{Binding AllSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ref:InsertCtorDialog}}, Mode=OneWay}" Checked="SelectAllChecked" Unchecked="SelectAllUnchecked" /> |
||||
</DockPanel> |
||||
</Grid> |
||||
</ref:AbstractInlineRefactorDialog> |
@ -0,0 +1,273 @@
@@ -0,0 +1,273 @@
|
||||
// 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.Collections.Generic; |
||||
using System.Globalization; |
||||
using System.IO; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Data; |
||||
using System.Windows.Input; |
||||
using System.Windows.Threading; |
||||
|
||||
using ICSharpCode.AvalonEdit.Snippets; |
||||
using ICSharpCode.NRefactory.CSharp; |
||||
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for InsertCtorDialog.xaml
|
||||
/// </summary>
|
||||
public partial class InsertCtorDialog : AbstractInlineRefactorDialog |
||||
{ |
||||
IList<PropertyOrFieldWrapper> parameterList; |
||||
|
||||
public InsertCtorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor, IUnresolvedTypeDefinition current, IList<PropertyOrFieldWrapper> possibleParameters) |
||||
: base(context, editor, anchor) |
||||
{ |
||||
InitializeComponent(); |
||||
|
||||
this.varList.ItemsSource = parameterList = possibleParameters; |
||||
|
||||
if (!parameterList.Any()) |
||||
Visibility = System.Windows.Visibility.Collapsed; |
||||
} |
||||
|
||||
protected override string GenerateCode(IUnresolvedTypeDefinition currentClass) |
||||
{ |
||||
List<PropertyOrFieldWrapper> filtered = this.varList.SelectedItems.OfType<PropertyOrFieldWrapper>() |
||||
.OrderBy(p => p.Index) |
||||
.ToList(); |
||||
|
||||
var insertedConstructor = refactoringContext.GetNode<ConstructorDeclaration>(); |
||||
if (insertedConstructor == null) |
||||
{ |
||||
// We are not inside of a constructor declaration
|
||||
return null; |
||||
} |
||||
|
||||
using (Script script = refactoringContext.StartScript()) { |
||||
BlockStatement originalCtorBody = insertedConstructor.Body; |
||||
|
||||
foreach (PropertyOrFieldWrapper w in filtered) { |
||||
if (w.AddCheckForNull) { |
||||
// true = reference, null = generic or unknown
|
||||
if (w.Type.IsReferenceType != false) |
||||
script.AddTo(originalCtorBody, |
||||
new IfElseStatement( |
||||
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.Equality, new PrimitiveExpression(null)), |
||||
new ThrowStatement(new ObjectCreateExpression(new SimpleType("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) |
||||
) |
||||
); |
||||
else |
||||
script.AddTo(originalCtorBody, |
||||
new IfElseStatement( |
||||
new UnaryOperatorExpression(UnaryOperatorType.Not, new MemberReferenceExpression(new IdentifierExpression(w.MemberName), "HasValue")), |
||||
new ThrowStatement(new ObjectCreateExpression(new SimpleType("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) |
||||
) |
||||
); |
||||
} |
||||
if (w.AddRangeCheck) { |
||||
script.AddTo(originalCtorBody, |
||||
new IfElseStatement( |
||||
new BinaryOperatorExpression( |
||||
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.LessThan, new IdentifierExpression("lower")), |
||||
BinaryOperatorType.ConditionalOr, |
||||
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.GreaterThan, new IdentifierExpression("upper")) |
||||
), |
||||
new ThrowStatement( |
||||
new ObjectCreateExpression( |
||||
new SimpleType("ArgumentOutOfRangeException"), |
||||
new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"'), new IdentifierExpression(w.ParameterName), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Add, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Add, new IdentifierExpression("upper")))) } |
||||
) |
||||
) |
||||
) |
||||
); |
||||
} |
||||
} |
||||
|
||||
foreach (PropertyOrFieldWrapper w in filtered) { |
||||
script.AddTo(originalCtorBody, |
||||
new ExpressionStatement(new AssignmentExpression(new MemberReferenceExpression(new ThisReferenceExpression(), w.MemberName), AssignmentOperatorType.Assign, new IdentifierExpression(w.ParameterName))) |
||||
); |
||||
} |
||||
} |
||||
|
||||
AnchorElement parameterListElement = insertionContext.ActiveElements |
||||
.OfType<AnchorElement>() |
||||
.FirstOrDefault(item => item.Name.Equals("parameterList", StringComparison.OrdinalIgnoreCase)); |
||||
|
||||
if (parameterListElement != null) { |
||||
StringBuilder pList = new StringBuilder(); |
||||
|
||||
var parameters = filtered |
||||
.Select(p => new ParameterDeclaration(refactoringContext.CreateShortType(p.Type), p.ParameterName)) |
||||
.ToList(); |
||||
|
||||
using (StringWriter textWriter = new StringWriter(pList)) { |
||||
// Output parameter list as string
|
||||
var formattingOptions = FormattingOptionsFactory.CreateMono(); |
||||
CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(textWriter, formattingOptions); |
||||
for (int i = 0; i < parameters.Count; i++) { |
||||
if (i > 0) |
||||
textWriter.Write(","); |
||||
outputVisitor.VisitParameterDeclaration(parameters[i]); |
||||
} |
||||
} |
||||
|
||||
parameterListElement.Text = pList.ToString(); |
||||
} |
||||
|
||||
return null; |
||||
} |
||||
|
||||
void UpClick(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
int selection = varList.SelectedIndex; |
||||
|
||||
if (selection <= 0) |
||||
return; |
||||
|
||||
var curItem = parameterList.First(p => p.Index == selection); |
||||
var exchangeItem = parameterList.First(p => p.Index == selection - 1); |
||||
|
||||
curItem.Index = selection - 1; |
||||
exchangeItem.Index = selection; |
||||
|
||||
varList.ItemsSource = parameterList.OrderBy(p => p.Index); |
||||
varList.SelectedIndex = selection - 1; |
||||
} |
||||
|
||||
void DownClick(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
int selection = varList.SelectedIndex; |
||||
|
||||
if (selection < 0 || selection >= parameterList.Count - 1) |
||||
return; |
||||
|
||||
var curItem = parameterList.First(p => p.Index == selection); |
||||
var exchangeItem = parameterList.First(p => p.Index == selection + 1); |
||||
|
||||
curItem.Index = selection + 1; |
||||
exchangeItem.Index = selection; |
||||
|
||||
varList.ItemsSource = parameterList.OrderBy(p => p.Index); |
||||
varList.SelectedIndex = selection + 1; |
||||
} |
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e) |
||||
{ |
||||
Key? downAccessKey = GetAccessKeyFromButton(moveDown); |
||||
Key? upAccessKey = GetAccessKeyFromButton(moveUp); |
||||
Key? allAccessKey = GetAccessKeyFromButton(selectAll); |
||||
|
||||
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && allAccessKey == e.SystemKey) { |
||||
if (AllSelected) |
||||
varList.UnselectAll(); |
||||
else |
||||
varList.SelectAll(); |
||||
e.Handled = true; |
||||
} |
||||
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && upAccessKey == e.SystemKey) { |
||||
UpClick(this, null); |
||||
e.Handled = true; |
||||
} |
||||
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && downAccessKey == e.SystemKey) { |
||||
DownClick(this, null); |
||||
e.Handled = true; |
||||
} |
||||
|
||||
base.OnKeyDown(e); |
||||
} |
||||
|
||||
protected override void FocusFirstElement() |
||||
{ |
||||
Dispatcher.BeginInvoke((Action)TryFocusAndSelectItem, DispatcherPriority.Background); |
||||
} |
||||
|
||||
void TryFocusAndSelectItem() |
||||
{ |
||||
if (!parameterList.Any()) |
||||
return; |
||||
|
||||
object ctorParamWrapper = varList.Items.GetItemAt(0); |
||||
if (ctorParamWrapper != null) { |
||||
ListBoxItem item = (ListBoxItem)varList.ItemContainerGenerator.ContainerFromItem(ctorParamWrapper); |
||||
item.Focus(); |
||||
|
||||
varList.ScrollIntoView(item); |
||||
varList.SelectedItem = item; |
||||
Keyboard.Focus(item); |
||||
} |
||||
} |
||||
|
||||
protected override void OnInsertionCompleted() |
||||
{ |
||||
base.OnInsertionCompleted(); |
||||
|
||||
Dispatcher.BeginInvoke( |
||||
DispatcherPriority.Background, |
||||
(Action)( |
||||
() => { |
||||
if (!parameterList.Any()) |
||||
insertionContext.Deactivate(null); |
||||
else { |
||||
insertionEndAnchor = editor.Document.CreateAnchor(anchor.Offset); |
||||
insertionEndAnchor.MovementType = AnchorMovementType.AfterInsertion; |
||||
} |
||||
} |
||||
) |
||||
); |
||||
} |
||||
|
||||
void SelectAllChecked(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
this.varList.SelectAll(); |
||||
} |
||||
|
||||
void SelectAllUnchecked(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
this.varList.UnselectAll(); |
||||
} |
||||
|
||||
bool AllSelected { |
||||
get { return varList.SelectedItems.Count == varList.Items.Count; } |
||||
} |
||||
|
||||
protected override void CancelButtonClick(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
base.CancelButtonClick(sender, e); |
||||
|
||||
editor.Caret.Offset = anchor.Offset; |
||||
} |
||||
|
||||
protected override void OKButtonClick(object sender, System.Windows.RoutedEventArgs e) |
||||
{ |
||||
base.OKButtonClick(sender, e); |
||||
|
||||
editor.Caret.Offset = insertionEndAnchor.Offset; |
||||
} |
||||
} |
||||
|
||||
[ValueConversion(typeof(int), typeof(bool))] |
||||
public class IntToBoolConverter : IValueConverter |
||||
{ |
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
return ((int)value) != -1; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
return ((bool)value) ? 0 : -1; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,93 @@
@@ -0,0 +1,93 @@
|
||||
// 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.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Threading; |
||||
|
||||
using ICSharpCode.AvalonEdit.Snippets; |
||||
using ICSharpCode.NRefactory; |
||||
using ICSharpCode.NRefactory.Editor; |
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
using ICSharpCode.SharpDevelop.Parser; |
||||
using CSharpBinding.Refactoring; |
||||
using ICSharpCode.SharpDevelop.Editor; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
public class InsertCtorSnippetRefactoring : ISnippetElementProvider |
||||
{ |
||||
public SnippetElement GetElement(SnippetInfo snippetInfo) |
||||
{ |
||||
if ("refactoring:ctor".Equals(snippetInfo.Tag, StringComparison.OrdinalIgnoreCase)) |
||||
return new InlineRefactorSnippetElement(CreateDialog, "{" + snippetInfo.Tag + "}"); |
||||
|
||||
return null; |
||||
} |
||||
|
||||
InsertCtorDialog CreateDialog(InsertionContext context) |
||||
{ |
||||
ITextEditor textEditor = context.TextArea.GetService(typeof(ITextEditor)) as ITextEditor; |
||||
|
||||
if (textEditor == null) |
||||
return null; |
||||
|
||||
IEditorUIService uiService = textEditor.GetService(typeof(IEditorUIService)) as IEditorUIService; |
||||
|
||||
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 resolvedCurrent = current.Resolve(refactoringContext.Resolver.TypeResolveContext); |
||||
|
||||
List<PropertyOrFieldWrapper> parameters = CreateCtorParams(current, 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); |
||||
|
||||
dialog.Element = uiService.CreateInlineUIElement(anchor, dialog); |
||||
|
||||
return dialog; |
||||
} |
||||
|
||||
IEnumerable<PropertyOrFieldWrapper> CreateCtorParams(IUnresolvedTypeDefinition sourceType, IType resolvedSourceType) |
||||
{ |
||||
int i = 0; |
||||
|
||||
foreach (var f in resolvedSourceType.GetFields().Where(field => !field.IsConst |
||||
&& field.IsStatic == sourceType.IsStatic |
||||
&& field.ReturnType != null)) { |
||||
yield return new PropertyOrFieldWrapper(f) { Index = i }; |
||||
i++; |
||||
} |
||||
|
||||
foreach (var p in resolvedSourceType.GetProperties().Where(prop => prop.CanSet && !prop.IsIndexer |
||||
&& prop.IsStatic == sourceType.IsStatic |
||||
&& prop.ReturnType != null)) { |
||||
yield return new PropertyOrFieldWrapper(p) { Index = i }; |
||||
i++; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,121 @@
@@ -0,0 +1,121 @@
|
||||
// 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.ComponentModel; |
||||
using System.Linq; |
||||
|
||||
using ICSharpCode.NRefactory.TypeSystem; |
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace CSharpBinding.Refactoring |
||||
{ |
||||
public class PropertyOrFieldWrapper : INotifyPropertyChanged |
||||
{ |
||||
/// <summary>
|
||||
/// Underlying member. Always IField or IProperty.
|
||||
/// </summary>
|
||||
public readonly IMember Member; |
||||
private readonly string text; |
||||
|
||||
public PropertyOrFieldWrapper(IMember member) |
||||
{ |
||||
if (member == null) |
||||
throw new ArgumentNullException("member"); |
||||
if (!(member is IField || member is IProperty)) |
||||
throw new ArgumentException("member must be IField or IProperty"); |
||||
|
||||
this.Member = member; |
||||
IAmbience ambience = AmbienceService.GetCurrentAmbience(); |
||||
ambience.ConversionFlags |= |
||||
ConversionFlags.ShowReturnType |
||||
| ConversionFlags.ShowModifiers |
||||
| ConversionFlags.ShowAccessibility; |
||||
this.text = ambience.ConvertEntity(member); |
||||
} |
||||
|
||||
public string MemberName { |
||||
get { return Member.Name; } |
||||
} |
||||
|
||||
string parameterName; |
||||
public string ParameterName { |
||||
get { |
||||
if (parameterName == null) |
||||
parameterName = ToParameterName(this.MemberName); |
||||
return parameterName; |
||||
} |
||||
} |
||||
|
||||
public IType Type { |
||||
get { return Member.ReturnType; } |
||||
} |
||||
|
||||
public string Text { |
||||
get { return text; } |
||||
} |
||||
|
||||
public int Index { get; set; } |
||||
|
||||
public bool IsNullable { |
||||
get { |
||||
// true = reference, null = generic or unknown
|
||||
return Member.ReturnType.IsReferenceType != false |
||||
|| (Member.ReturnType.FullName == "System.Nullable"); |
||||
} |
||||
} |
||||
|
||||
public bool HasRange { |
||||
get { |
||||
return IsTypeWithRange(Member.ReturnType) || |
||||
(Member.ReturnType.FullName == "System.Nullable") |
||||
&& IsTypeWithRange(Member.ReturnType.TypeArguments.First()); |
||||
} |
||||
} |
||||
|
||||
bool addCheckForNull; |
||||
public bool AddCheckForNull { |
||||
get { return addCheckForNull; } |
||||
set { |
||||
addCheckForNull = value; |
||||
} |
||||
} |
||||
|
||||
bool addRangeCheck; |
||||
public bool AddRangeCheck { |
||||
get { return addRangeCheck; } |
||||
set { |
||||
addRangeCheck = value; |
||||
} |
||||
} |
||||
|
||||
bool IsTypeWithRange(IType type) |
||||
{ |
||||
string crtType = type.FullName; |
||||
return crtType == "System.Int32" || |
||||
crtType == "System.Int16" || |
||||
crtType == "System.Int64" || |
||||
crtType == "System.Single" || |
||||
crtType == "System.Double" || |
||||
crtType == "System.UInt16" || |
||||
crtType == "System.UInt32" || |
||||
crtType == "System.UInt64"; |
||||
} |
||||
|
||||
static string ToParameterName(string memberName) |
||||
{ |
||||
if (string.IsNullOrEmpty(memberName)) |
||||
return memberName; |
||||
return char.ToLower(memberName[0]) + memberName.Substring(1); |
||||
} |
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged; |
||||
|
||||
protected virtual void OnPropertyChanged(string property) |
||||
{ |
||||
if (PropertyChanged != null) { |
||||
PropertyChanged(this, new PropertyChangedEventArgs(property)); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue