Browse Source

Reintroduced "insert constructor snippet" feature.

pull/45/merge
Andreas Weizel 12 years ago
parent
commit
2c1c16e260
  1. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 8
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 17
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CodeManipulation.cs
  4. 161
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/AbstractInlineRefactorDialog.cs
  5. 35
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InlineRefactorSnippetElement.cs
  6. 57
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml
  7. 273
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs
  8. 93
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs
  9. 121
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/PropertyOrFieldWrapper.cs

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

@ -155,6 +155,12 @@
class="CSharpBinding.Refactoring.SearchForIssuesCommand"/> class="CSharpBinding.Refactoring.SearchForIssuesCommand"/>
</Path> </Path>
<Path name="/SharpDevelop/ViewContent/AvalonEdit/SnippetElementProviders">
<Class id="ctor" class="CSharpBinding.Refactoring.InsertCtorSnippetRefactoring" />
<!--<Class id="switch" class="CSharpBinding.Refactoring.SwitchSnippetProvider" />
<Class id="propall" class="CSharpBinding.Refactoring.CreateProperties" />-->
</Path>
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders"> <Path path = "/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders">
<Class class = "CSharpBinding.Refactoring.CSharpSyntaxIssue" /> <Class class = "CSharpBinding.Refactoring.CSharpSyntaxIssue" />
<Class class = "CSharpBinding.Refactoring.SDRedundantUsingIssue" /> <Class class = "CSharpBinding.Refactoring.SDRedundantUsingIssue" />

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

@ -76,8 +76,14 @@
<Compile Include="Src\CSharpTextEditorExtension.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\CSharpCodeGenerator.cs" /> <Compile Include="Src\Refactoring\CSharpCodeGenerator.cs" />
<Compile Include="Src\Refactoring\CSharpSyntaxIssue.cs" /> <Compile Include="Src\Refactoring\CSharpSyntaxIssue.cs" />
<Compile Include="Src\Refactoring\InlineRefactorSnippetElement.cs" />
<Compile Include="Src\Refactoring\InsertCtorDialog.xaml.cs">
<DependentUpon>InsertCtorDialog.xaml</DependentUpon>
</Compile>
<Compile Include="Src\Refactoring\InsertCtorSnippetRefactoring.cs" />
<Compile Include="Src\Refactoring\InsertionPoint.cs" /> <Compile Include="Src\Refactoring\InsertionPoint.cs" />
<Compile Include="Src\Refactoring\IssueOptions.xaml.cs"> <Compile Include="Src\Refactoring\IssueOptions.xaml.cs">
<DependentUpon>IssueOptions.xaml</DependentUpon> <DependentUpon>IssueOptions.xaml</DependentUpon>
@ -88,6 +94,7 @@
<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\RenameContextAction.cs" /> <Compile Include="Src\Refactoring\RenameContextAction.cs" />
<Compile Include="Src\Refactoring\PropertyOrFieldWrapper.cs" />
<Compile Include="Src\Refactoring\SDNamingConventionService.cs" /> <Compile Include="Src\Refactoring\SDNamingConventionService.cs" />
<Compile Include="Src\Refactoring\SDRedundantUsingIssue.cs" /> <Compile Include="Src\Refactoring\SDRedundantUsingIssue.cs" />
<Compile Include="Src\Refactoring\EditorScript.cs" /> <Compile Include="Src\Refactoring\EditorScript.cs" />
@ -183,6 +190,7 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Src\Refactoring\InsertCtorDialog.xaml" />
<Page Include="Src\Refactoring\IssueOptions.xaml" /> <Page Include="Src\Refactoring\IssueOptions.xaml" />
<Page Include="Src\OptionPanels\BuildOptions.xaml" /> <Page Include="Src\OptionPanels\BuildOptions.xaml" />
<Page Include="Src\Refactoring\SearchForIssuesDialog.xaml" /> <Page Include="Src\Refactoring\SearchForIssuesDialog.xaml" />

17
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CodeManipulation.cs

@ -3,16 +3,21 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
/* /*
using System.Windows.Input;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.PatternMatching;
//using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
using Ast = ICSharpCode.NRefactory.Ast; //using Ast = ICSharpCode.NRefactory.Ast;
namespace CSharpBinding namespace CSharpBinding
{ {
@ -100,8 +105,8 @@ namespace CSharpBinding
class Selection class Selection
{ {
public Location Start { get; set; } public TextLocation Start { get; set; }
public Location End { get; set; } public TextLocation End { get; set; }
} }
void CodeManipulationSelectionChanged(object sender, EventArgs e) void CodeManipulationSelectionChanged(object sender, EventArgs e)
@ -163,7 +168,7 @@ namespace CSharpBinding
string currentNodeText = editor.Document.GetText(statementSelection.Start, statementSelection.End); string currentNodeText = editor.Document.GetText(statementSelection.Start, statementSelection.End);
SwapText(editor.Document, statementSelection.Start, statementSelection.End, swapSibling.StartLocation, swapSibling.EndLocation); SwapText(editor.Document, statementSelection.Start, statementSelection.End, swapSibling.StartLocation, swapSibling.EndLocation);
// Move caret to the start of moved statement // Move caret to the start of moved statement
Location upperLocation = new Location[] {statementSelection.Start, swapSibling.StartLocation}.Min(); TextLocation upperLocation = new TextLocation[] {statementSelection.Start, swapSibling.StartLocation}.Min();
if (direction == MoveStatementDirection.Up) if (direction == MoveStatementDirection.Up)
editor.Caret.Position = upperLocation; editor.Caret.Position = upperLocation;
else { else {
@ -454,4 +459,4 @@ namespace CSharpBinding
} }
} }
} }
*/ */

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

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

35
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InlineRefactorSnippetElement.cs

@ -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 } };
}
}
}

57
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml

@ -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>

273
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorDialog.xaml.cs

@ -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;
}
}
}

93
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertCtorSnippetRefactoring.cs

@ -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++;
}
}
}
}

121
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/PropertyOrFieldWrapper.cs

@ -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…
Cancel
Save