Browse Source

More work on context actions.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
3ce7c07e75
  1. 55
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs
  2. 36
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs
  3. 9
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs
  4. 12
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SimpleSelection.cs
  5. 22
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  6. 104
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs
  7. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs
  8. 2
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs
  9. 12
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateBackingStore.cs
  10. 22
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs
  11. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs
  12. 10
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsBulbViewModel.cs

55
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
@ -10,6 +11,7 @@ using ICSharpCode.NRefactory.CSharp.Refactoring; @@ -10,6 +11,7 @@ using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding.Refactoring
{
@ -20,33 +22,32 @@ namespace CSharpBinding.Refactoring @@ -20,33 +22,32 @@ namespace CSharpBinding.Refactoring
{
int indentationSize = 4;
readonly ITextEditor editor;
readonly TextSegmentCollection<TextSegment> textSegmentCollection = new TextSegmentCollection<TextSegment>();
readonly OffsetChangeMap offsetChangeMap = new OffsetChangeMap();
readonly List<Action> actions = new List<Action>();
readonly IDocument originalDocument;
readonly TextSegmentCollection<TextSegment> textSegmentCollection;
readonly IDisposable undoGroup;
public SDScript(ITextEditor editor, string eolMarker) : base(eolMarker, new CSharpFormattingOptions())
{
this.editor = editor;
this.textSegmentCollection = new TextSegmentCollection<TextSegment>((TextDocument)editor.Document);
this.originalDocument = editor.Document.CreateDocumentSnapshot();
undoGroup = editor.Document.OpenUndoGroup();
}
public override int GetCurrentOffset(TextLocation originalDocumentLocation)
{
int offset = editor.Document.GetOffset(originalDocumentLocation);
return offsetChangeMap.GetNewOffset(offset, AnchorMovementType.Default);
int offset = originalDocument.GetOffset(originalDocumentLocation);
return GetCurrentOffset(offset);
}
public override int GetCurrentOffset(int originalDocumentOffset)
{
return offsetChangeMap.GetNewOffset(originalDocumentOffset, AnchorMovementType.Default);
return originalDocument.Version.MoveOffsetTo(editor.Document.Version, originalDocumentOffset, AnchorMovementType.Default);
}
public override void Replace(int offset, int length, string newText)
{
var changeMapEntry = new OffsetChangeMapEntry(offset, length, newText.Length);
textSegmentCollection.UpdateOffsets(changeMapEntry);
offsetChangeMap.Add(changeMapEntry);
actions.Add(delegate { editor.Document.Replace(offset, length, newText); });
editor.Document.Replace(offset, length, newText);
}
protected override ISegment CreateTrackedSegment(int offset, int length)
@ -60,7 +61,7 @@ namespace CSharpBinding.Refactoring @@ -60,7 +61,7 @@ namespace CSharpBinding.Refactoring
protected override int GetIndentLevelAt(int offset)
{
int oldOffset = offsetChangeMap.Invert().GetNewOffset(offset, AnchorMovementType.Default);
int oldOffset = editor.Document.Version.MoveOffsetTo(originalDocument.Version, offset, AnchorMovementType.Default);
var line = editor.Document.GetLineByOffset(oldOffset);
int spaces = 0;
int indentationLevel = 0;
@ -84,29 +85,53 @@ namespace CSharpBinding.Refactoring @@ -84,29 +85,53 @@ namespace CSharpBinding.Refactoring
public override void Rename(IEntity entity, string name)
{
// TODO
}
public override void InsertWithCursor(string operation, AstNode node, InsertPosition defaultPosition)
{
// TODO
}
public override void FormatText(int offset, int length)
{
var parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo != null) {
//var startLocation = editor.Document.GetLocation(offset);
//var endLocation = editor.Document.GetLocation(offset + length);
//var node = parseInfo.CompilationUnit.GetNodeContaining(startLocation, endLocation);
var formatter = new AstFormattingVisitor(new CSharpFormattingOptions(), editor.Document, false, 4);
parseInfo.CompilationUnit.AcceptVisitor(formatter);
formatter.ApplyChanges(offset, length);
}
}
public override void Select(AstNode node)
{
var segment = GetSegment(node);
int startOffset = segment.Offset;
int endOffset = segment.EndOffset;
// If the area to select includes a newline (e.g. node is a statement),
// exclude that newline from the selection.
if (endOffset > startOffset && editor.Document.GetLineByOffset(endOffset).Offset == endOffset) {
endOffset = editor.Document.GetLineByOffset(endOffset).PreviousLine.EndOffset;
}
editor.Select(startOffset, endOffset - startOffset);
}
public override void Select(int offset, int length)
{
actions.Add(delegate { editor.Select(offset, length); });
editor.Select(offset, length);
}
public override void Link(params AstNode[] nodes)
{
// TODO
}
public override void Dispose()
{
foreach (var action in actions)
action();
undoGroup.Dispose();
}
}
}

36
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActionsRenderer.cs

@ -67,7 +67,6 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -67,7 +67,6 @@ namespace ICSharpCode.AvalonEdit.AddIn
public void Dispose()
{
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchSingleton_Workbench_ActiveViewContentChanged;
delayMoveTimer.Stop();
ClosePopup();
}
@ -75,8 +74,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -75,8 +74,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
if (this.popup == null)
return;
if (e.Key == Key.T && Keyboard.Modifiers == ModifierKeys.Control)
{
if (e.Key == Key.T && Keyboard.Modifiers == ModifierKeys.Control) {
if (popup.ViewModel != null && popup.ViewModel.Actions != null && popup.ViewModel.Actions.Count > 0) {
popup.IsDropdownOpen = true;
popup.Focus();
@ -87,18 +85,20 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -87,18 +85,20 @@ namespace ICSharpCode.AvalonEdit.AddIn
this.cancellationTokenSourceForPopupBeingOpened = new CancellationTokenSource();
var cancellationToken = cancellationTokenSourceForPopupBeingOpened.Token;
try {
await Task.WhenAll(popupVM.LoadActionsAsync(cancellationToken), popupVM.LoadHiddenActionsAsync(cancellationToken));
await popupVM.LoadActionsAsync(cancellationToken);
if (popupVM.Actions.Count == 0)
await popupVM.LoadHiddenActionsAsync(cancellationToken);
} catch (OperationCanceledException) {
return;
}
if (cancellationToken.IsCancellationRequested)
return;
this.cancellationTokenSourceForPopupBeingOpened = null;
if (popupVM.HiddenActions.Count == 0)
if (popupVM.Actions.Count == 0 && popupVM.HiddenActions.Count == 0)
return;
this.popup.ViewModel = popupVM;
this.popup.IsDropdownOpen = true;
this.popup.IsHiddenActionsExpanded = true;
this.popup.IsHiddenActionsExpanded = popupVM.Actions.Count == 0;
this.popup.OpenAtLineStart(this.Editor);
this.popup.Focus();
}
@ -107,17 +107,18 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -107,17 +107,18 @@ namespace ICSharpCode.AvalonEdit.AddIn
void ScrollChanged(object sender, EventArgs e)
{
ClosePopup();
StartTimer();
}
CancellationTokenSource cancellationTokenSourceForPopupBeingOpened;
async void TimerMoveTick(object sender, EventArgs e)
{
this.delayMoveTimer.Stop();
if (!IsEnabled)
if (!delayMoveTimer.IsEnabled)
return;
ClosePopup();
if (!IsEnabled)
return;
ContextActionsBulbViewModel popupVM = BuildPopupViewModel(this.Editor);
this.cancellationTokenSourceForPopupBeingOpened = new CancellationTokenSource();
@ -144,10 +145,16 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -144,10 +145,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
}
void CaretPositionChanged(object sender, EventArgs e)
{
StartTimer();
}
void StartTimer()
{
ClosePopup();
this.delayMoveTimer.Stop();
this.delayMoveTimer.Start();
IViewContent activeViewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
if (activeViewContent != null && activeViewContent.PrimaryFileName == this.Editor.FileName)
delayMoveTimer.Start();
}
void ClosePopup()
@ -158,6 +165,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -158,6 +165,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
cancellationTokenSourceForPopupBeingOpened = null;
}
this.delayMoveTimer.Stop();
this.popup.Close();
this.popup.IsDropdownOpen = false;
this.popup.IsHiddenActionsExpanded = false;
@ -166,11 +174,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -166,11 +174,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
void WorkbenchSingleton_Workbench_ActiveViewContentChanged(object sender, EventArgs e)
{
// open the popup again if in current file
IViewContent activeViewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
if (activeViewContent != null && activeViewContent.PrimaryFileName == this.Editor.FileName)
CaretPositionChanged(this, EventArgs.Empty);
else // otherwise close popup
ClosePopup();
StartTimer();
}
}
}

9
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/Caret.cs

@ -167,7 +167,14 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -167,7 +167,14 @@ namespace ICSharpCode.AvalonEdit.Editing
{
InvalidateVisualColumn();
if (storedCaretOffset >= 0) {
int newCaretOffset = e.GetNewOffset(storedCaretOffset, AnchorMovementType.Default);
// If the caret is at the end of a selection, we don't expand the selection if something
// is inserted at the end. Thus we also need to keep the caret in front of the insertion.
AnchorMovementType caretMovementType;
if (!textArea.Selection.IsEmpty && storedCaretOffset == textArea.Selection.SurroundingSegment.EndOffset)
caretMovementType = AnchorMovementType.BeforeInsertion;
else
caretMovementType = AnchorMovementType.Default;
int newCaretOffset = e.GetNewOffset(storedCaretOffset, caretMovementType);
TextDocument document = textArea.Document;
if (document != null) {
// keep visual column

12
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SimpleSelection.cs

@ -89,10 +89,18 @@ namespace ICSharpCode.AvalonEdit.Editing @@ -89,10 +89,18 @@ namespace ICSharpCode.AvalonEdit.Editing
{
if (e == null)
throw new ArgumentNullException("e");
int newStartOffset, newEndOffset;
if (startOffset <= endOffset) {
newStartOffset = e.GetNewOffset(startOffset, AnchorMovementType.Default);
newEndOffset = Math.Max(newStartOffset, e.GetNewOffset(endOffset, AnchorMovementType.BeforeInsertion));
} else {
newEndOffset = e.GetNewOffset(endOffset, AnchorMovementType.Default);
newStartOffset = Math.Max(newEndOffset, e.GetNewOffset(startOffset, AnchorMovementType.BeforeInsertion));
}
return Selection.Create(
textArea,
new TextViewPosition(textArea.Document.GetLocation(e.GetNewOffset(startOffset, AnchorMovementType.Default)), start.VisualColumn),
new TextViewPosition(textArea.Document.GetLocation(e.GetNewOffset(endOffset, AnchorMovementType.Default)), end.VisualColumn)
new TextViewPosition(textArea.Document.GetLocation(newStartOffset), start.VisualColumn),
new TextViewPosition(textArea.Document.GetLocation(newEndOffset), end.VisualColumn)
);
}

22
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -169,6 +169,13 @@ namespace ICSharpCode.NRefactory.CSharp @@ -169,6 +169,13 @@ namespace ICSharpCode.NRefactory.CSharp
public Role Role {
get { return role; }
set {
if (value == null)
throw new ArgumentNullException("value");
if (!value.IsValid(this))
throw new ArgumentException("This node is not valid in the new role.");
role = value;
}
}
public AstNode NextSibling {
@ -350,7 +357,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -350,7 +357,6 @@ namespace ICSharpCode.NRefactory.CSharp
parent.lastChild = prevSibling;
}
parent = null;
role = Roles.Root;
prevSibling = null;
nextSibling = null;
}
@ -408,7 +414,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -408,7 +414,6 @@ namespace ICSharpCode.NRefactory.CSharp
parent = null;
prevSibling = null;
nextSibling = null;
role = Roles.Root;
}
}
@ -450,7 +455,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -450,7 +455,6 @@ namespace ICSharpCode.NRefactory.CSharp
AstNode copy = (AstNode)MemberwiseClone ();
// First, reset the shallow pointer copies
copy.parent = null;
copy.role = Roles.Root;
copy.firstChild = null;
copy.lastChild = null;
copy.prevSibling = null;
@ -590,6 +594,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -590,6 +594,18 @@ namespace ICSharpCode.NRefactory.CSharp
return result;
}
/// <summary>
/// Gets the node that fully contains the range from startLocation to endLocation.
/// </summary>
public AstNode GetNodeContaining(TextLocation startLocation, TextLocation endLocation)
{
for (AstNode child = firstChild; child != null; child = child.nextSibling) {
if (child.StartLocation <= startLocation && endLocation <= child.EndLocation)
return child.GetNodeContaining(startLocation, endLocation);
}
return this;
}
public IEnumerable<AstNode> GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn)
{
return GetNodesBetween (new TextLocation (startLine, startColumn), new TextLocation (endLine, endColumn));

104
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs

@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Text;
using System.Collections.Generic;
using System.Linq;
@ -35,10 +36,23 @@ namespace ICSharpCode.NRefactory.CSharp @@ -35,10 +36,23 @@ namespace ICSharpCode.NRefactory.CSharp
{
public class AstFormattingVisitor : DepthFirstAstVisitor<object, object>
{
struct TextReplaceAction
{
internal readonly int Offset;
internal readonly int RemovalLength;
internal readonly string NewText;
public TextReplaceAction(int offset, int removalLength, string newText)
{
this.Offset = offset;
this.RemovalLength = removalLength;
this.NewText = newText;
}
}
CSharpFormattingOptions policy;
IDocument document;
Script script;
//List<TextReplaceAction> changes = new List<TextReplaceAction> ();
List<TextReplaceAction> changes = new List<TextReplaceAction> ();
Indent curIndent = new Indent ();
public int IndentLevel {
@ -67,23 +81,71 @@ namespace ICSharpCode.NRefactory.CSharp @@ -67,23 +81,71 @@ namespace ICSharpCode.NRefactory.CSharp
public string EolMarker { get; set; }
public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, Script script, bool tabsToSpaces = false, int indentationSize = 4)
public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, bool tabsToSpaces = false, int indentationSize = 4)
{
if (policy == null)
throw new ArgumentNullException("policy");
if (document == null)
throw new ArgumentNullException("document");
if (script == null)
throw new ArgumentNullException("script");
this.policy = policy;
this.document = document;
this.script = script;
this.curIndent.TabsToSpaces = tabsToSpaces;
this.curIndent.TabSize = indentationSize;
this.EolMarker = Environment.NewLine;
CorrectBlankLines = true;
}
/// <summary>
/// Applies the changes to the input document.
/// </summary>
public void ApplyChanges()
{
ApplyChanges(0, document.TextLength, document.Replace);
}
public void ApplyChanges(int startOffset, int length)
{
ApplyChanges(startOffset, length, document.Replace);
}
/// <summary>
/// Applies the changes to the given Script instance.
/// </summary>
public void ApplyChanges(Script script)
{
ApplyChanges(0, document.TextLength, script.Replace);
}
public void ApplyChanges(int startOffset, int length, Script script)
{
ApplyChanges(startOffset, length, script.Replace);
}
void ApplyChanges(int startOffset, int length, Action<int, int, string> documentReplace)
{
int endOffset = startOffset + length;
int lastChangeEnd = 0;
int delta = 0;
foreach (var change in changes.OrderBy(c => c.Offset)) {
if (change.Offset < lastChangeEnd) {
Debug.Fail("Detected overlapping change");
continue;
}
lastChangeEnd = change.Offset + change.RemovalLength;
if (change.Offset < startOffset) {
// skip all changes in front of the begin offset
continue;
} else if (change.Offset > endOffset) {
// skip this change unless it depends on one that we already applied
continue;
}
documentReplace(change.Offset + delta, change.RemovalLength, change.NewText);
delta += change.NewText.Length - change.RemovalLength;
}
changes.Clear();
}
public override object VisitCompilationUnit (CompilationUnit unit, object data)
{
base.VisitCompilationUnit (unit, data);
@ -971,35 +1033,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -971,35 +1033,7 @@ namespace ICSharpCode.NRefactory.CSharp
void AddChange (int offset, int removedChars, string insertedText)
{
script.Replace(offset, removedChars, insertedText);
// if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars
// && c.InsertedText == insertedText))
// return;
// string currentText = document.GetText (offset, removedChars);
// if (currentText == insertedText)
// return;
// if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}')))
// throw new InvalidOperationException ("Tried to remove non ws chars: '" + currentText + "'");
// foreach (var change in changes) {
// if (change.Offset == offset) {
// if (removedChars > 0 && insertedText == change.InsertedText) {
// change.RemovedChars = removedChars;
//// change.InsertedText = insertedText;
// return;
// }
// if (!string.IsNullOrEmpty (change.InsertedText)) {
// change.InsertedText += insertedText;
// } else {
// change.InsertedText = insertedText;
// }
// change.RemovedChars = System.Math.Max (removedChars, change.RemovedChars);
// return;
// }
// }
// //Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "<null>" : insertedText.Replace ("\n", "\\n").Replace ("\r", "\\r").Replace ("\t", "\\t").Replace (" ", "."));
// //Console.WriteLine (Environment.StackTrace);
//
// changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText));
changes.Add(new TextReplaceAction(offset, removedChars, insertedText));
}
public bool IsLineIsEmptyUpToEol (TextLocation startLocation)

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -1510,7 +1510,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1510,7 +1510,7 @@ namespace ICSharpCode.NRefactory.CSharp
else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole)
style = policy.EventRemoveBraceStyle;
else
throw new NotSupportedException ("Unknown type of accessor");
style = policy.StatementBraceStyle;
} else {
style = policy.StatementBraceStyle;
}

2
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
Body = new BlockStatement { accessorStatement }
};
pdecl.AddChild (accessor, pdecl.Setter.IsNull ? PropertyDeclaration.SetterRole : PropertyDeclaration.GetterRole);
accessor.Role = pdecl.Setter.IsNull ? PropertyDeclaration.SetterRole : PropertyDeclaration.GetterRole;
using (var script = context.StartScript ()) {
script.InsertBefore (pdecl.RBraceToken, accessor);

12
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateBackingStore.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CreateBackingStore.cs
//
// Author:
@ -53,13 +53,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -53,13 +53,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// create new property & implement the get/set bodies
var newProperty = (PropertyDeclaration)property.Clone ();
var id1 = new IdentifierExpression (backingStoreName);
var id2 = new IdentifierExpression (backingStoreName);
Expression id1;
if (backingStoreName == "value")
id1 = new ThisReferenceExpression().Member("value");
else
id1 = new IdentifierExpression (backingStoreName);
Expression id2 = id1.Clone();
newProperty.Getter.Body = new BlockStatement () {
new ReturnStatement (id1)
};
newProperty.Setter.Body = new BlockStatement () {
new ExpressionStatement (new AssignmentExpression (id2, AssignmentOperatorType.Assign, new IdentifierExpression ("value")))
new AssignmentExpression (id2, AssignmentOperatorType.Assign, new IdentifierExpression ("value"))
};
using (var script = context.StartScript ()) {

22
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs

@ -178,15 +178,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -178,15 +178,33 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
output.RegisterTrackedSegments(this, startOffset);
}
public void FormatText (AstNode node)
public virtual void FormatText (AstNode node)
{
var segment = GetSegment(node);
FormatText(segment.Offset, segment.Length);
}
/// <summary>
/// Format the specified node and surrounding whitespace.
/// </summary>
public virtual void FormatTextAround (AstNode node)
{
int startOffset;
if (node.PrevSibling != null)
startOffset = GetSegment(node.PrevSibling).EndOffset;
else
startOffset = GetSegment(node).Offset;
int endOffset;
if (node.NextSibling != null)
endOffset = GetSegment(node.NextSibling).Offset;
else
endOffset = GetSegment(node).EndOffset;
FormatText(startOffset, endOffset - startOffset);
}
public abstract void FormatText (int offset, int length);
public void Select (AstNode node)
public virtual void Select (AstNode node)
{
var segment = GetSegment(node);
Select(segment.Offset, segment.Length);

5
src/Libraries/NRefactory/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs

@ -220,8 +220,9 @@ namespace ICSharpCode.NRefactory.Editor @@ -220,8 +220,9 @@ namespace ICSharpCode.NRefactory.Editor
get { return lines.Length; }
}
ITextSourceVersion ITextSource.Version {
get { return null; }
/// <inheritdoc/>
public ITextSourceVersion Version {
get { return textSource.Version; }
}
/// <inheritdoc/>

10
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsBulbViewModel.cs

@ -39,16 +39,26 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -39,16 +39,26 @@ namespace ICSharpCode.SharpDevelop.Refactoring
this.ActionVisibleChangedCommand = new ActionVisibleChangedCommand(model);
}
bool actionsLoaded;
public async Task LoadActionsAsync(CancellationToken cancellationToken)
{
if (actionsLoaded)
return;
actionsLoaded = true;
this.Actions.Clear();
foreach (var action in await Model.GetVisibleActionsAsync(cancellationToken)) {
this.Actions.Add(new ContextActionViewModel(action, this.Model.EditorContext) { IsVisible = true });
}
}
bool hiddenActionsLoaded;
public async Task LoadHiddenActionsAsync(CancellationToken cancellationToken)
{
if (hiddenActionsLoaded)
return;
hiddenActionsLoaded = true;
this.HiddenActions.Clear();
foreach (var action in await Model.GetHiddenActionsAsync(cancellationToken)) {
this.HiddenActions.Add(new ContextActionViewModel(action, this.Model.EditorContext) { IsVisible = false });

Loading…
Cancel
Save