Browse Source

first implementation of #247: Reimplement 'highlight symbols' (CaretReferencesRenderer)

missing:
 - ctor/method calls are not highlighted properly
 - not bound to options
pull/343/merge
Siegfried Pammer 12 years ago
parent
commit
3f999348cf
  1. 20
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  2. 98
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs
  3. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
  4. 202
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CaretReferencesRenderer.cs
  5. 97
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ExpressionHighlightRenderer.cs
  6. 11
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingBrush.cs
  7. 4
      src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs
  8. 15
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

20
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

@ -19,7 +19,10 @@ @@ -19,7 +19,10 @@
using System;
using System.Collections.Generic;
using System.Threading;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using CSharpBinding.Completion;
using CSharpBinding.FormattingStrategy;
@ -58,12 +61,15 @@ namespace CSharpBinding @@ -58,12 +61,15 @@ namespace CSharpBinding
IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders;
CodeManipulation codeManipulation;
CSharpSemanticHighlighter highlighter;
CancellationTokenSource caretMovementTokenSource;
public void Attach(ITextEditor editor)
{
this.editor = editor;
inspectionManager = new IssueManager(editor);
codeManipulation = new CodeManipulation(editor);
this.editor.Caret.LocationChanged += CaretLocationChanged;
if (!editor.ContextActionProviders.IsReadOnly) {
contextActionProviders = AddInTree.BuildItems<IContextActionProvider>("/SharpDevelop/ViewContent/TextEditor/C#/ContextActions", null);
@ -81,7 +87,21 @@ namespace CSharpBinding @@ -81,7 +87,21 @@ namespace CSharpBinding
if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveAll(contextActionProviders.Contains);
}
this.editor.Caret.LocationChanged -= CaretLocationChanged;
this.editor = null;
}
void CaretLocationChanged(object sender, EventArgs e)
{
if (highlighter == null)
highlighter = editor.GetService<CSharpSemanticHighlighter>();
if (highlighter == null)
return;
if (caretMovementTokenSource != null)
caretMovementTokenSource.Cancel();
caretMovementTokenSource = new CancellationTokenSource();
var rr = SD.ParserService.Resolve(editor.FileName, editor.Caret.Location, editor.Document, cancellationToken: caretMovementTokenSource.Token);
highlighter.SetCurrentSymbol(rr.GetSymbol());
}
}
}

98
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs

@ -18,14 +18,19 @@ @@ -18,14 +18,19 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Linq;
using System.Windows.Media;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Parser;
@ -50,6 +55,9 @@ namespace CSharpBinding @@ -50,6 +55,9 @@ namespace CSharpBinding
int lineNumber;
HighlightedLine line;
CSharpFullParseInformation parseInfo;
ISymbolReference currentSymbolReference;
IResolveVisitorNavigator currentNavigator;
HighlightingColor symbolReferenceColor;
#region Constructor + Dispose
public CSharpSemanticHighlighter(IDocument document)
@ -66,6 +74,7 @@ namespace CSharpBinding @@ -66,6 +74,7 @@ namespace CSharpBinding
this.enumerationTypeColor = this.valueKeywordColor;
this.typeParameterTypeColor = this.referenceTypeColor;
this.delegateTypeColor = this.referenceTypeColor;
this.symbolReferenceColor = new HighlightingColor { Background = new SimpleHighlightingBrush(DefaultFillColor) };
this.methodDeclarationColor = this.methodCallColor = highlighting.GetNamedColor("MethodCall");
//this.eventDeclarationColor = this.eventAccessColor = defaultTextColor;
@ -92,6 +101,7 @@ namespace CSharpBinding @@ -92,6 +101,7 @@ namespace CSharpBinding
SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
SD.ParserService.LoadSolutionProjectsThread.Finished += ParserService_LoadSolutionProjectsThreadEnded;
eventHandlersAreRegistered = true;
document.GetService<IServiceContainer>().AddService(typeof(CSharpSemanticHighlighter), this);
}
}
@ -101,6 +111,7 @@ namespace CSharpBinding @@ -101,6 +111,7 @@ namespace CSharpBinding
SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
SD.ParserService.LoadSolutionProjectsThread.Finished -= ParserService_LoadSolutionProjectsThreadEnded;
eventHandlersAreRegistered = false;
document.GetService<IServiceContainer>().RemoveService(typeof(CSharpSemanticHighlighter));
}
this.resolver = null;
this.parseInfo = null;
@ -174,10 +185,7 @@ namespace CSharpBinding @@ -174,10 +185,7 @@ namespace CSharpBinding
void ParserService_LoadSolutionProjectsThreadEnded(object sender, EventArgs e)
{
cachedLines.Clear();
invalidLines.Clear();
forceParseOnNextRefresh = true;
OnHighlightingStateChanged(1, document.LineCount);
InvalidateAll();
}
void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e)
@ -389,6 +397,88 @@ namespace CSharpBinding @@ -389,6 +397,88 @@ namespace CSharpBinding
});
}
}
protected override void Colorize(AstNode node, HighlightingColor color)
{
if (currentSymbolReference != null && currentNavigator == null)
currentNavigator = InitNavigator();
if (currentNavigator != null) {
var resolverNode = node;
while (CSharpAstResolver.IsUnresolvableNode(resolverNode) && resolverNode.Parent != null)
resolverNode = resolverNode.Parent;
currentNavigator.Resolved(resolverNode, resolver.Resolve(resolverNode));
}
base.Colorize(node, color);
}
protected override void Colorize(Identifier identifier, ResolveResult rr)
{
if (currentSymbolReference != null && currentNavigator == null)
currentNavigator = InitNavigator();
if (currentNavigator != null) {
currentNavigator.Resolved(identifier, rr);
}
base.Colorize(identifier, rr);
}
public readonly Color DefaultFillColor = Color.FromArgb(22, 30, 130, 255);
public void SetCurrentSymbol(ISymbol symbol)
{
currentNavigator = null;
currentSymbolReference = null;
if (symbol != null)
currentSymbolReference = symbol.ToReference();
InvalidateAll();
}
void InvalidateAll()
{
cachedLines.Clear();
invalidLines.Clear();
forceParseOnNextRefresh = true;
OnHighlightingStateChanged(1, document.LineCount);
}
FindReferences findReferences = new FindReferences();
IResolveVisitorNavigator InitNavigator()
{
if (currentSymbolReference == null) return null;
var compilation = resolver.Compilation;
var symbol = currentSymbolReference.Resolve(compilation.TypeResolveContext);
var searchScopes = findReferences.GetSearchScopes(symbol);
if (searchScopes.Count == 0)
return null;
var navigators = new IResolveVisitorNavigator[searchScopes.Count];
for (int i = 0; i < navigators.Length; i++) {
navigators[i] = searchScopes[i].GetNavigator(compilation, Colorize);
}
IResolveVisitorNavigator combinedNavigator;
if (searchScopes.Count == 1) {
combinedNavigator = navigators[0];
} else {
combinedNavigator = new CompositeResolveVisitorNavigator(navigators);
}
return combinedNavigator;
}
void Colorize(AstNode node, ResolveResult result)
{
Identifier identifier = node.GetChildByRole(Roles.Identifier);
if (!identifier.IsNull)
AddMarker(identifier.StartLocation, identifier.EndLocation);
else
AddMarker(node.StartLocation, node.EndLocation);
}
void AddMarker(TextLocation start, TextLocation end)
{
Colorize(start, end, symbolReferenceColor);
}
#endregion
}
}

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj

@ -134,7 +134,6 @@ @@ -134,7 +134,6 @@
<Compile Include="Src\AvalonEditorControlService.cs" />
<Compile Include="Src\AvalonEditViewContent.cs" />
<Compile Include="Src\BracketHighlightRenderer.cs" />
<Compile Include="Src\CaretReferencesRenderer.cs" />
<Compile Include="Src\ChooseEncodingDialog.xaml.cs">
<DependentUpon>ChooseEncodingDialog.xaml</DependentUpon>
<SubType>Code</SubType>
@ -143,7 +142,6 @@ @@ -143,7 +142,6 @@
<Compile Include="Src\CodeEditor.cs" />
<Compile Include="Src\CodeEditorAdapter.cs" />
<Compile Include="Src\CodeEditorView.cs" />
<Compile Include="Src\ExpressionHighlightRenderer.cs" />
<Compile Include="Src\CaretHighlightAdorner.cs" />
<Compile Include="Src\NewLineConsistencyCheck.cs" />
<Compile Include="Src\SearchPanelLocalization.cs" />

202
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CaretReferencesRenderer.cs

@ -1,202 +0,0 @@ @@ -1,202 +0,0 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.AddIn.Options;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.AvalonEdit.AddIn
{
/* /// <summary>
/// In the code editor, highlights all references to the expression under the caret (for better code readability).
/// </summary>
public class CaretReferencesRenderer
{
/// <summary>
/// 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 delayMs = 800;
/// <summary>
/// Maximum time for Find references. After this time it gets cancelled and no highlight is displayed.
/// Useful for very large files.
/// </summary>
const int findReferencesTimeoutMs = 200;
CodeEditorView editorView;
ITextEditor Editor { get { return editorView.Adapter; } }
ExpressionHighlightRenderer highlightRenderer;
ResolveResult lastResolveResult;
public bool IsEnabled
{
get {
string fileName = this.Editor.FileName;
return CodeEditorOptions.Instance.HighlightSymbol && (fileName.EndsWith(".cs") || fileName.EndsWith(".vb"));
}
}
/// <summary>
/// In the code editor, highlights all references to the expression under the caret (for better code readability).
/// </summary>
public CaretReferencesRenderer(CodeEditorView editorView)
{
this.editorView = editorView;
this.highlightRenderer = new ExpressionHighlightRenderer(this.editorView.TextArea.TextView);
this.delayTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMs) };
this.delayTimer.Stop();
this.delayTimer.Tick += TimerTick;
this.delayMoveTimer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(delayMoveMs) };
this.delayMoveTimer.Stop();
this.delayMoveTimer.Tick += TimerMoveTick;
this.editorView.TextArea.Caret.PositionChanged += CaretPositionChanged;
// fixes SD-1873 - Unhandled WPF Exception when deleting text in text editor
// clear highlights to avoid exceptions when trying to draw highlights in
// locations that have been deleted already.
this.editorView.Document.Changed += delegate { lastResolveResult = null; ClearHighlight(); };
}
public void ClearHighlight()
{
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 = FindReferencesInCurrentFile(this.lastResolveResult);
this.highlightRenderer.SetHighlight(referencesToBeHighlighted);
}
void TimerMoveTick(object sender, EventArgs e)
{
this.delayMoveTimer.Stop();
this.delayTimer.Stop();
if (!IsEnabled)
return;
var resolveResult = GetExpressionAtCaret();
if (resolveResult == null) {
this.lastResolveResult = null;
this.highlightRenderer.ClearHighlight();
return;
}
// caret is over symbol and that symbol is different from the last time
if (!SameResolveResult(resolveResult, lastResolveResult))
{
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>
/// Resolves the current expression under caret.
/// This gets called on every caret position change, so quite often.
/// </summary>
ResolveResult GetExpressionAtCaret()
{
if (string.IsNullOrEmpty(Editor.FileName) || ParserService.LoadSolutionProjectsThreadRunning)
return null;
int line = Editor.Caret.Position.Line;
int column = Editor.Caret.Position.Column;
return ParserService.Resolve(line, column, Editor.Document, Editor.FileName);
}
/// <summary>
/// Finds references to resolved expression in the current file.
/// </summary>
List<Reference> FindReferencesInCurrentFile(ResolveResult resolveResult)
{
if (resolveResult == null)
return null;
var cancellationTokenSource = new CancellationTokenSource();
using (new Timer(
delegate {
LoggingService.Debug("Aborting FindReferencesInCurrentFile due to timeout");
cancellationTokenSource.Cancel();
}, null, findReferencesTimeoutMs, Timeout.Infinite))
{
var progressMonitor = new DummyProgressMonitor();
progressMonitor.CancellationToken = cancellationTokenSource.Token;
var references = RefactoringService.FindReferencesLocal(resolveResult, Editor.FileName, progressMonitor);
if (references == null || references.Count == 0)
return null;
return references;
}
}
/// <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)
{
//if (resolveResult == null && resolveResult2 == null)
// return true;
//if (resolveResult == null && resolveResult2 != null)
// return false;
//if (resolveResult != null && resolveResult2 == null)
// return false;
// 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();
}
}
*/
}

97
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ExpressionHighlightRenderer.cs

@ -1,97 +0,0 @@ @@ -1,97 +0,0 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Windows.Media;
using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.AvalonEdit.AddIn
{
/*
/// <summary>
/// Highlights expressions (references to expression under current caret).
/// </summary>
public class ExpressionHighlightRenderer : IBackgroundRenderer
{
List<Reference> renderedReferences;
Pen borderPen;
Brush backgroundBrush;
TextView textView;
public readonly Color DefaultBorderColor = Color.FromArgb(52, 30, 130, 255); //Color.FromArgb(180, 70, 230, 70))
public readonly Color DefaultFillColor = Color.FromArgb(22, 30, 130, 255); //Color.FromArgb(40, 60, 255, 60)
readonly int borderThickness = 1;
readonly int cornerRadius = 1;
public void SetHighlight(List<Reference> renderedReferences)
{
if (this.renderedReferences != renderedReferences) {
this.renderedReferences = renderedReferences;
textView.InvalidateLayer(this.Layer);
}
}
public void ClearHighlight()
{
this.SetHighlight(null);
}
public ExpressionHighlightRenderer(TextView textView)
{
if (textView == null)
throw new ArgumentNullException("textView");
this.textView = textView;
this.borderPen = new Pen(new SolidColorBrush(DefaultBorderColor), borderThickness);
this.backgroundBrush = new SolidColorBrush(DefaultFillColor);
this.borderPen.Freeze();
this.backgroundBrush.Freeze();
this.textView.BackgroundRenderers.Add(this);
}
public KnownLayer Layer {
get {
return KnownLayer.Selection;
}
}
public void Draw(TextView textView, DrawingContext drawingContext)
{
if (this.renderedReferences == null)
return;
BackgroundGeometryBuilder builder = new BackgroundGeometryBuilder();
builder.CornerRadius = cornerRadius;
builder.AlignToMiddleOfPixels = true;
foreach (var reference in this.renderedReferences) {
builder.AddSegment(textView, new TextSegment() {
StartOffset = reference.Offset,
Length = reference.Length });
builder.CloseFigure();
}
Geometry geometry = builder.CreateGeometry();
if (geometry != null) {
drawingContext.DrawGeometry(backgroundBrush, borderPen, geometry);
}
}
}
*/
}

11
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/HighlightingBrush.cs

@ -58,23 +58,26 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -58,23 +58,26 @@ namespace ICSharpCode.AvalonEdit.Highlighting
/// Highlighting brush implementation that takes a frozen brush.
/// </summary>
[Serializable]
sealed class SimpleHighlightingBrush : HighlightingBrush, ISerializable
public sealed class SimpleHighlightingBrush : HighlightingBrush, ISerializable
{
readonly SolidColorBrush brush;
public SimpleHighlightingBrush(SolidColorBrush brush)
internal SimpleHighlightingBrush(SolidColorBrush brush)
{
brush.Freeze();
this.brush = brush;
}
/// <inheritdoc/>
public SimpleHighlightingBrush(Color color) : this(new SolidColorBrush(color)) {}
/// <inheritdoc/>
public override Brush GetBrush(ITextRunConstructionContext context)
{
return brush;
}
/// <inheritdoc/>
public override string ToString()
{
return brush.ToString();
@ -91,6 +94,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -91,6 +94,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
info.AddValue("color", brush.Color.ToString(CultureInfo.InvariantCulture));
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
SimpleHighlightingBrush other = obj as SimpleHighlightingBrush;
@ -99,6 +103,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting @@ -99,6 +103,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting
return this.brush.Color.Equals(other.brush.Color);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return brush.Color.GetHashCode();

4
src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Analysis/SemanticHighlightingVisitor.cs

@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
protected abstract void Colorize(TextLocation start, TextLocation end, TColor color);
#region Colorize helper methods
protected void Colorize(Identifier identifier, ResolveResult rr)
protected virtual void Colorize(Identifier identifier, ResolveResult rr)
{
if (identifier.IsNull)
return;
@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -141,7 +141,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
VisitIdentifier(identifier); // un-colorize contextual keywords
}
protected void Colorize(AstNode node, TColor color)
protected virtual void Colorize(AstNode node, TColor color)
{
if (node.IsNull)
return;

15
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeSystemExtensions.cs

@ -765,5 +765,20 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -765,5 +765,20 @@ namespace ICSharpCode.NRefactory.TypeSystem
return assembly.GetTypeDefinition (new TopLevelTypeName (namespaceName, name, typeParameterCount));
}
#endregion
#region ResolveResult
public static ISymbol GetSymbol(this ResolveResult rr)
{
if (rr is LocalResolveResult) {
return ((LocalResolveResult)rr).Variable;
} else if (rr is MemberResolveResult) {
return ((MemberResolveResult)rr).Member;
} else if (rr is TypeResolveResult) {
return ((TypeResolveResult)rr).Type.GetDefinition();
}
return null;
}
#endregion
}
}

Loading…
Cancel
Save