|
|
|
@ -22,15 +22,22 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -22,15 +22,22 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
public class CaretReferencesRenderer |
|
|
|
|
{ |
|
|
|
|
/// <summary>
|
|
|
|
|
/// Delays the highlighting after the caret position changes, so that Find references does not get called too often.
|
|
|
|
|
/// Delays the Resolve check so that it does not get called too often when user holds an arrow.
|
|
|
|
|
/// </summary>
|
|
|
|
|
DispatcherTimer delayMoveTimer; |
|
|
|
|
const int delayMoveMs = 100; |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Delays the Find references (and highlight) after the caret stays at one point for a while.
|
|
|
|
|
/// </summary>
|
|
|
|
|
DispatcherTimer delayTimer; |
|
|
|
|
const int delayMilliseconds = 800; |
|
|
|
|
const int delayMs = 800; |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Delays the Resolve check so that it does not get called too often when user holds an arrow.
|
|
|
|
|
/// Maximum time for Find references. After this time it gets cancelled and no highlight is displayed.
|
|
|
|
|
/// Useful for very large files.
|
|
|
|
|
/// </summary>
|
|
|
|
|
DispatcherTimer delayMoveTimer; |
|
|
|
|
const int delayMoveMilliseconds = 100; |
|
|
|
|
const int findReferencesTimeoutMs = 200; |
|
|
|
|
|
|
|
|
|
CodeEditorView editorView; |
|
|
|
|
ITextEditor Editor { get { return editorView.Adapter; } } |
|
|
|
@ -53,10 +60,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -53,10 +60,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
{ |
|
|
|
|
this.editorView = editorView; |
|
|
|
|
this.highlightRenderer = new ExpressionHighlightRenderer(this.editorView.TextArea.TextView); |
|
|
|
|
this.delayTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMilliseconds) }; |
|
|
|
|
this.delayTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMs) }; |
|
|
|
|
this.delayTimer.Stop(); |
|
|
|
|
this.delayTimer.Tick += TimerTick; |
|
|
|
|
this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMilliseconds) }; |
|
|
|
|
this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMs) }; |
|
|
|
|
this.delayMoveTimer.Stop(); |
|
|
|
|
this.delayMoveTimer.Tick += TimerMoveTick; |
|
|
|
|
this.editorView.TextArea.Caret.PositionChanged += CaretPositionChanged; |
|
|
|
@ -67,13 +74,23 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -67,13 +74,23 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
this.highlightRenderer.ClearHighlight(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// In the current document, highlights all references to the expression
|
|
|
|
|
/// which is currently under the caret (local variable, class, property).
|
|
|
|
|
/// This gets called on every caret position change, so quite often.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void CaretPositionChanged(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
Restart(this.delayMoveTimer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void TimerTick(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
this.delayTimer.Stop(); |
|
|
|
|
|
|
|
|
|
if (!IsEnabled) |
|
|
|
|
return; |
|
|
|
|
var referencesToBeHighlighted = GetReferencesInCurrentFile(this.lastResolveResult); |
|
|
|
|
var referencesToBeHighlighted = FindReferencesInCurrentFile(this.lastResolveResult); |
|
|
|
|
this.highlightRenderer.SetHighlight(referencesToBeHighlighted); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -85,9 +102,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -85,9 +102,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
if (!IsEnabled) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
var resolveResult = GetExpressionUnderCaret(); |
|
|
|
|
var resolveResult = GetExpressionAtCaret(); |
|
|
|
|
if (resolveResult == null) { |
|
|
|
|
this.lastResolveResult = resolveResult; |
|
|
|
|
this.lastResolveResult = null; |
|
|
|
|
this.highlightRenderer.ClearHighlight(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
@ -97,25 +114,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -97,25 +114,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
this.lastResolveResult = resolveResult; |
|
|
|
|
this.highlightRenderer.ClearHighlight(); |
|
|
|
|
this.delayTimer.Start(); |
|
|
|
|
} else { |
|
|
|
|
// highlight stays the same, both timers are stopped (will start again when caret moves)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// In the current document, highlights all references to the expression
|
|
|
|
|
/// which is currently under the caret (local variable, class, property).
|
|
|
|
|
/// This gets called on every caret position change, so quite often.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void CaretPositionChanged(object sender, EventArgs e) |
|
|
|
|
{ |
|
|
|
|
this.delayMoveTimer.Stop(); |
|
|
|
|
this.delayMoveTimer.Start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Resolves the current expression under caret.
|
|
|
|
|
/// This gets called on every caret position change, so quite often.
|
|
|
|
|
/// </summary>
|
|
|
|
|
ResolveResult GetExpressionUnderCaret() |
|
|
|
|
ResolveResult GetExpressionAtCaret() |
|
|
|
|
{ |
|
|
|
|
if (string.IsNullOrEmpty(Editor.FileName) || ParserService.LoadSolutionProjectsThreadRunning) |
|
|
|
|
return null; |
|
|
|
@ -127,14 +135,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -127,14 +135,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Finds references to resolved expression in the current file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
List<Reference> GetReferencesInCurrentFile(ResolveResult resolveResult) |
|
|
|
|
List<Reference> FindReferencesInCurrentFile(ResolveResult resolveResult) |
|
|
|
|
{ |
|
|
|
|
var cancellationTokenSource = new CancellationTokenSource(); |
|
|
|
|
using (new Timer( |
|
|
|
|
delegate { |
|
|
|
|
LoggingService.Debug("Aborting GetReferencesInCurrentFile due to timeout"); |
|
|
|
|
LoggingService.Debug("Aborting FindReferencesInCurrentFile due to timeout"); |
|
|
|
|
cancellationTokenSource.Cancel(); |
|
|
|
|
}, null, 200, Timeout.Infinite)) |
|
|
|
|
}, null, findReferencesTimeoutMs, Timeout.Infinite)) |
|
|
|
|
{ |
|
|
|
|
var progressMonitor = new DummyProgressMonitor(); |
|
|
|
|
progressMonitor.CancellationToken = cancellationTokenSource.Token; |
|
|
|
@ -147,6 +155,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -147,6 +155,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Returns true if the 2 ResolveResults refer to the same symbol.
|
|
|
|
|
/// So that when caret moves but stays inside the same symbol, symbol stays highlighted.
|
|
|
|
|
/// </summary>
|
|
|
|
|
bool SameResolveResult(ResolveResult resolveResult, ResolveResult resolveResult2) |
|
|
|
|
{ |
|
|
|
@ -159,5 +168,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
@@ -159,5 +168,14 @@ namespace ICSharpCode.AvalonEdit.AddIn
|
|
|
|
|
// TODO determine if 2 ResolveResults refer to the same symbol
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Restarts a timer.
|
|
|
|
|
/// </summary>
|
|
|
|
|
void Restart(DispatcherTimer timer) |
|
|
|
|
{ |
|
|
|
|
timer.Stop(); |
|
|
|
|
timer.Start(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|