Browse Source

Reimplemented F6 for members.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
8d12fe8a20
  1. 304
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs
  2. 6
      src/Main/Base/Project/Src/Commands/FileCommands.cs
  3. 155
      src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs
  4. 23
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs
  5. 125
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs
  6. 6
      src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs
  7. 1
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs

304
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpCompletionBinding.cs

@ -1,313 +1,33 @@ @@ -1,313 +1,33 @@
// 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 ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.CSharp;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using AST = ICSharpCode.NRefactory.Ast;
namespace CSharpBinding
{
public class CSharpCompletionBinding : NRefactoryCodeCompletionBinding
public class CSharpCompletionBinding : ICodeCompletionBinding
{
public CSharpCompletionBinding() : base(SupportedLanguage.CSharp)
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{
return CodeCompletionKeyPressResult.None;
}
static CSharpExpressionFinder CreateExpressionFinder(string fileName)
public bool HandleKeyPressed(ITextEditor editor, char ch)
{
return new CSharpExpressionFinder(ParserService.GetParseInformation(fileName));
if (ch == '.')
return CtrlSpace(editor);
else
return false;
}
public override CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
public bool CtrlSpace(ITextEditor editor)
{
CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName);
int cursor = editor.Caret.Offset;
if (ch == '[') {
var line = editor.Document.GetLineForOffset(cursor);
} else if (ch == ',' && CodeCompletionOptions.InsightRefreshOnComma && CodeCompletionOptions.InsightEnabled) {
IInsightWindow insightWindow;
if (insightHandler.InsightRefreshOnComma(editor, ch, out insightWindow)) {
return CodeCompletionKeyPressResult.Completed;
}
} else if(ch == '=') {
var curLine = editor.Document.GetLineForOffset(cursor);
string documentText = editor.Document.Text;
int position = editor.Caret.Offset - 2;
if (position > 0 && (documentText[position + 1] == '+')) {
ExpressionResult result = ef.FindFullExpression(documentText, position);
if(result.Expression != null) {
ResolveResult resolveResult = ParserService.Resolve(result, editor.Caret.Line, editor.Caret.Column, editor.FileName, documentText);
if (resolveResult != null && resolveResult.ResolvedType != null) {
IClass underlyingClass = resolveResult.ResolvedType.GetUnderlyingClass();
if (underlyingClass != null && underlyingClass.IsTypeInInheritanceTree(ParserService.CurrentProjectContent.GetClass("System.MulticastDelegate", 0))) {
EventHandlerCompletionItemProvider eventHandlerProvider = new EventHandlerCompletionItemProvider(result.Expression, resolveResult);
eventHandlerProvider.ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
}
}
}
} else if (position > 0) {
ExpressionResult result = ef.FindFullExpression(documentText, position);
if(result.Expression != null) {
ResolveResult resolveResult = ParserService.Resolve(result, editor.Caret.Line, editor.Caret.Column, editor.FileName, documentText);
if (resolveResult != null && resolveResult.ResolvedType != null) {
if (ProvideContextCompletion(editor, resolveResult.ResolvedType, ch)) {
return CodeCompletionKeyPressResult.Completed;
}
}
}
}
} else if (ch == '.') {
new CSharpCodeCompletionDataProvider().ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
} else if (ch == '>') {
if (IsInComment(editor)) return CodeCompletionKeyPressResult.None;
char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
if (prevChar == '-') {
new PointerArrowCompletionDataProvider().ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
}
}
if (char.IsLetter(ch) && CodeCompletionOptions.CompleteWhenTyping) {
if (editor.SelectionLength > 0) {
// allow code completion when overwriting an identifier
int endOffset = editor.SelectionStart + editor.SelectionLength;
// but block code completion when overwriting only part of an identifier
if (endOffset < editor.Document.TextLength && char.IsLetterOrDigit(editor.Document.GetCharAt(endOffset)))
return CodeCompletionKeyPressResult.None;
editor.Document.Remove(editor.SelectionStart, editor.SelectionLength);
// Read caret position again after removal - this is required because the document might change in other
// locations, too (e.g. bound elements in snippets).
cursor = editor.Caret.Offset;
}
char prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
bool afterUnderscore = prevChar == '_';
if (afterUnderscore) {
cursor--;
prevChar = cursor > 1 ? editor.Document.GetCharAt(cursor - 1) : ' ';
}
if (!char.IsLetterOrDigit(prevChar) && prevChar != '.' && !IsInComment(editor)) {
ExpressionResult result = ef.FindExpression(editor.Document.Text, cursor);
LoggingService.Debug("CC: Beginning to type a word, result=" + result);
if (result.Context != ExpressionContext.IdentifierExpected) {
var ctrlSpaceProvider = new NRefactoryCtrlSpaceCompletionItemProvider(LanguageProperties.CSharp, result.Context);
ctrlSpaceProvider.ShowTemplates = true;
ctrlSpaceProvider.AllowCompleteExistingExpression = afterUnderscore;
ctrlSpaceProvider.ShowCompletion(editor);
return CodeCompletionKeyPressResult.CompletedIncludeKeyInCompletion;
}
}
}
return base.HandleKeyPress(editor, ch);
}
class CSharpCodeCompletionDataProvider : DotCodeCompletionItemProvider
{
public override ResolveResult Resolve(ITextEditor editor, ExpressionResult expressionResult)
{
// bypass ParserService.Resolve and set resolver.LimitMethodExtractionUntilCaretLine
ParseInformation parseInfo = ParserService.GetParseInformation(editor.FileName);
NRefactoryResolver resolver = new NRefactoryResolver(LanguageProperties.CSharp);
resolver.LimitMethodExtractionUntilLine = editor.Caret.Line;
return resolver.Resolve(expressionResult, parseInfo, editor.Document.Text);
}
}
class PointerArrowCompletionDataProvider : DotCodeCompletionItemProvider
{
public override ResolveResult Resolve(ITextEditor editor, ExpressionResult expressionResult)
{
ResolveResult rr = base.Resolve(editor, expressionResult);
if (rr != null && rr.ResolvedType != null) {
PointerReturnType prt = rr.ResolvedType.CastToDecoratingReturnType<PointerReturnType>();
if (prt != null)
return new ResolveResult(rr.CallingClass, rr.CallingMember, prt.BaseType);
}
return null;
}
public override ExpressionResult GetExpression(ITextEditor editor)
{
// - 1 because the "-" is already inserted (the ">" is about to be inserted)
return GetExpressionFromOffset(editor, editor.Caret.Offset - 1);
}
}
bool IsInComment(ITextEditor editor)
{
CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName);
int cursor = editor.Caret.Offset - 1;
return ef.FilterComments(editor.Document.GetText(0, cursor + 1), ref cursor) == null;
}
public override bool HandleKeyword(ITextEditor editor, string word)
{
switch (word) {
case "using":
if (IsInComment(editor)) return false;
ParseInformation parseInfo = ParserService.GetParseInformation(editor.FileName);
if (parseInfo != null) {
IClass innerMostClass = parseInfo.CompilationUnit.GetInnermostClass(editor.Caret.Line, editor.Caret.Column);
if (innerMostClass == null) {
new NRefactoryCtrlSpaceCompletionItemProvider(LanguageProperties.CSharp, ExpressionContext.Namespace).ShowCompletion(editor);
return true;
}
}
break;
case "as":
case "is":
if (IsInComment(editor)) return false;
new NRefactoryCtrlSpaceCompletionItemProvider(LanguageProperties.CSharp, ExpressionContext.Type).ShowCompletion(editor);
return true;
case "override":
if (IsInComment(editor)) return false;
new OverrideCompletionItemProvider().ShowCompletion(editor);
return true;
case "new":
return ShowNewCompletion(editor);
case "case":
if (IsInComment(editor)) return false;
return DoCaseCompletion(editor);
case "return":
if (IsInComment(editor)) return false;
IMember m = GetCurrentMember(editor);
if (m != null) {
return ProvideContextCompletion(editor, m.ReturnType, ' ');
}
break;
}
return base.HandleKeyword(editor, word);
}
bool ShowNewCompletion(ITextEditor editor)
{
CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName);
int cursor = editor.Caret.Offset;
string documentToCursor = editor.Document.GetText(0, cursor);
ExpressionResult expressionResult = ef.FindExpression(documentToCursor, cursor);
LoggingService.Debug("ShowNewCompletion: expression is " + expressionResult);
if (expressionResult.Context.IsObjectCreation) {
var currentLine = editor.Document.GetLineForOffset(cursor);
string lineText = editor.Document.GetText(currentLine.Offset, cursor - currentLine.Offset);
// when the new follows an assignment, improve code-completion by detecting the
// type of the variable that is assigned to
if (lineText.Replace(" ", "").EndsWith("=new")) {
int pos = lineText.LastIndexOf('=');
ExpressionContext context = FindExactContextForNewCompletion(editor, documentToCursor,
currentLine, pos);
if (context != null)
expressionResult.Context = context;
}
new NRefactoryCtrlSpaceCompletionItemProvider(LanguageProperties.CSharp, expressionResult.Context).ShowCompletion(editor);
return true;
}
return false;
}
ExpressionContext FindExactContextForNewCompletion(ITextEditor editor, string documentToCursor,
IDocumentLine currentLine, int pos)
{
CSharpExpressionFinder ef = CreateExpressionFinder(editor.FileName);
// find expression on left hand side of the assignment
ExpressionResult lhsExpr = ef.FindExpression(documentToCursor, currentLine.Offset + pos);
if (lhsExpr.Expression != null) {
ResolveResult rr = ParserService.Resolve(lhsExpr, currentLine.LineNumber, pos, editor.FileName, editor.Document.Text);
if (rr != null && rr.ResolvedType != null) {
ExpressionContext context;
IClass c;
if (rr.ResolvedType.IsArrayReturnType) {
// when creating an array, all classes deriving from the array's element type are allowed
IReturnType elementType = rr.ResolvedType.CastToArrayReturnType().ArrayElementType;
c = elementType != null ? elementType.GetUnderlyingClass() : null;
context = ExpressionContext.TypeDerivingFrom(elementType, false);
} else {
// when creating a normal instance, all non-abstract classes deriving from the type
// are allowed
c = rr.ResolvedType.GetUnderlyingClass();
context = ExpressionContext.TypeDerivingFrom(rr.ResolvedType, true);
}
if (c != null && context.ShowEntry(c)) {
// Try to suggest an entry (List<int> a = new => suggest List<int>).
string suggestedClassName = LanguageProperties.CSharp.CodeGenerator.GenerateCode(
CodeGenerator.ConvertType(
rr.ResolvedType,
new ClassFinder(ParserService.GetParseInformation(editor.FileName), editor.Caret.Line, editor.Caret.Column)
), "");
if (suggestedClassName != c.Name) {
// create a special code completion item that completes also the type arguments
context.SuggestedItem = new SuggestedCodeCompletionItem(c, suggestedClassName);
} else {
context.SuggestedItem = new CodeCompletionItem(c);
}
}
return context;
}
}
return null;
}
#region "case"-keyword completion
bool DoCaseCompletion(ITextEditor editor)
{
ITextEditorCaret caret = editor.Caret;
NRefactoryResolver r = new NRefactoryResolver(LanguageProperties.CSharp);
if (r.Initialize(ParserService.GetParseInformation(editor.FileName), caret.Line, caret.Column)) {
AST.INode currentMember = r.ParseCurrentMember(editor.Document.Text);
if (currentMember != null) {
CaseCompletionSwitchFinder ccsf = new CaseCompletionSwitchFinder(caret.Line, caret.Column);
currentMember.AcceptVisitor(ccsf, null);
if (ccsf.bestStatement != null) {
r.RunLookupTableVisitor(currentMember);
ResolveResult rr = r.ResolveInternal(ccsf.bestStatement.SwitchExpression, ExpressionContext.Default);
if (rr != null && rr.ResolvedType != null) {
return ProvideContextCompletion(editor, rr.ResolvedType, ' ');
}
}
}
}
return false;
}
private class CaseCompletionSwitchFinder : AbstractAstVisitor
{
Location caretLocation;
internal AST.SwitchStatement bestStatement;
public CaseCompletionSwitchFinder(int caretLine, int caretColumn)
{
caretLocation = new Location(caretColumn, caretLine);
}
public override object VisitSwitchStatement(AST.SwitchStatement switchStatement, object data)
{
if (switchStatement.StartLocation < caretLocation && caretLocation < switchStatement.EndLocation) {
bestStatement = switchStatement;
}
return base.VisitSwitchStatement(switchStatement, data);
}
}
#endregion
}
}
*/

6
src/Main/Base/Project/Src/Commands/FileCommands.cs

@ -65,7 +65,8 @@ namespace ICSharpCode.SharpDevelop.Commands @@ -65,7 +65,8 @@ namespace ICSharpCode.SharpDevelop.Commands
internal static void Save(IWorkbenchWindow window)
{
window.ViewContents.ForEach(Save);
foreach (var vc in window.ViewContents)
Save(vc);
}
internal static void Save(IViewContent content)
@ -153,7 +154,8 @@ namespace ICSharpCode.SharpDevelop.Commands @@ -153,7 +154,8 @@ namespace ICSharpCode.SharpDevelop.Commands
// save remaining files once (display Save As dialog)
var files = remainingViewContents.SelectMany(content => content.Files).Distinct();
files.ForEach(Save);
foreach (var file in files)
Save(file);
}
internal static void Save(OpenedFile file)

155
src/Main/Base/Project/Src/Editor/CodeCompletion/CodeCompletionBinding.cs

@ -13,7 +13,28 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion @@ -13,7 +13,28 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion
/// </summary>
public interface ICodeCompletionBinding
{
/// <summary>
/// This method is called when typing a character in the editor, immediately before
/// the character is inserted into the document.
/// </summary>
/// <param name="editor">The editor</param>
/// <param name="ch">The character being inserted.</param>
/// <returns>Returns whether the completion binding has shown code completion.</returns>
CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch);
/// <summary>
/// This method is called after typing a character in the editor,
/// after character is inserted into the document.
/// </summary>
/// <param name="editor">The editor</param>
/// <param name="ch">The character that was inserted.</param>
/// <returns>Returns whether the completion binding has shown code completion.</returns>
bool HandleKeyPressed(ITextEditor editor, char ch);
/// <summary>
/// Invokes ctrl-space completion.
/// </summary>
/// <returns>Returns whether the completion binding has shown code completion.</returns>
bool CtrlSpace(ITextEditor editor);
}
@ -90,7 +111,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion @@ -90,7 +111,7 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion
this.extensions = extensions;
}
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
bool MatchesExtension(ITextEditor editor)
{
string ext = Path.GetExtension(editor.FileName);
foreach (string extension in extensions) {
@ -98,132 +119,36 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion @@ -98,132 +119,36 @@ namespace ICSharpCode.SharpDevelop.Editor.CodeCompletion
if (binding == null) {
binding = (ICodeCompletionBinding)codon.AddIn.CreateObject(codon.Properties["class"]);
if (binding == null)
break;
return false;
}
return binding.HandleKeyPress(editor, ch);
}
}
return CodeCompletionKeyPressResult.None;
}
public bool CtrlSpace(ITextEditor editor)
{
string ext = Path.GetExtension(editor.FileName);
foreach (string extension in extensions) {
if (ext.Equals(extension, StringComparison.OrdinalIgnoreCase)) {
if (binding == null) {
binding = (ICodeCompletionBinding)codon.AddIn.CreateObject(codon.Properties["class"]);
if (binding == null)
break;
}
return binding.CtrlSpace(editor);
return true;
}
}
return false;
}
}
/*
public class DefaultCodeCompletionBinding : ICodeCompletionBinding
{
bool enableMethodInsight = true;
bool enableIndexerInsight = true;
bool enableXmlCommentCompletion = true;
bool enableDotCompletion = true;
protected IInsightWindowHandler insightHandler;
public bool EnableMethodInsight {
get {
return enableMethodInsight;
}
set {
enableMethodInsight = value;
}
}
public bool EnableIndexerInsight {
get {
return enableIndexerInsight;
}
set {
enableIndexerInsight = value;
}
}
public bool EnableXmlCommentCompletion {
get {
return enableXmlCommentCompletion;
}
set {
enableXmlCommentCompletion = value;
}
}
public bool EnableDotCompletion {
get {
return enableDotCompletion;
}
set {
enableDotCompletion = value;
}
}
public virtual CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
public CodeCompletionKeyPressResult HandleKeyPress(ITextEditor editor, char ch)
{
switch (ch) {
case '(':
if (enableMethodInsight && CodeCompletionOptions.InsightEnabled) {
IInsightWindow insightWindow = editor.ShowInsightWindow(new MethodInsightProvider().ProvideInsight(editor));
if (insightWindow != null && insightHandler != null) {
insightHandler.InitializeOpenedInsightWindow(editor, insightWindow);
insightHandler.HighlightParameter(insightWindow, 0);
}
return CodeCompletionKeyPressResult.Completed;
}
break;
case '[':
if (enableIndexerInsight && CodeCompletionOptions.InsightEnabled) {
IInsightWindow insightWindow = editor.ShowInsightWindow(new IndexerInsightProvider().ProvideInsight(editor));
if (insightWindow != null && insightHandler != null)
insightHandler.InitializeOpenedInsightWindow(editor, insightWindow);
return CodeCompletionKeyPressResult.Completed;
}
break;
case '<':
if (enableXmlCommentCompletion) {
new CommentCompletionItemProvider().ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
}
break;
case '.':
if (enableDotCompletion) {
new DotCodeCompletionItemProvider().ShowCompletion(editor);
return CodeCompletionKeyPressResult.Completed;
}
break;
case ' ':
if (CodeCompletionOptions.KeywordCompletionEnabled) {
string word = editor.GetWordBeforeCaret();
if (!string.IsNullOrEmpty(word)) {
if (HandleKeyword(editor, word))
return CodeCompletionKeyPressResult.Completed;
}
}
break;
}
return CodeCompletionKeyPressResult.None;
if (MatchesExtension(editor))
return binding.HandleKeyPress(editor, ch);
else
return CodeCompletionKeyPressResult.None;
}
public virtual bool HandleKeyword(ITextEditor editor, string word)
public bool HandleKeyPressed(ITextEditor editor, char ch)
{
// DefaultCodeCompletionBinding does not support Keyword handling, but this
// method can be overridden
return false;
if (MatchesExtension(editor))
return binding.CtrlSpace(editor);
else
return false;
}
public virtual bool CtrlSpace(ITextEditor editor)
public bool CtrlSpace(ITextEditor editor)
{
return false;
if (MatchesExtension(editor))
return binding.CtrlSpace(editor);
else
return false;
}
}*/
}
}

23
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsHelper.cs

@ -40,16 +40,14 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -40,16 +40,14 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static ContextActionsPopup MakePopupWithOverrides(IMember member)
{
#warning Reimplement MakePopupWithOverrides
throw new NotImplementedException();
/*var derivedClassesTree = RefactoringService.FindDerivedClassesTree(member.DeclaringType);
var derivedClassesTree = FindReferenceService.BuildDerivedTypesGraph(member.DeclaringTypeDefinition).ConvertToDerivedTypeTree();
var popupViewModel = new ContextActionsViewModel {
Title = MenuService.ConvertLabel(StringParser.Parse(
"${res:SharpDevelop.Refactoring.OverridesOf}",
new StringTagPair("Name", member.FullyQualifiedName))
)};
popupViewModel.Actions = new OverridesPopupTreeViewModelBuilder(member).BuildTreeViewModel(derivedClassesTree);
return new ContextActionsPopup { Actions = popupViewModel, Symbol = member };*/
new StringTagPair("Name", member.FullName))
)};
popupViewModel.Actions = new OverridesPopupTreeViewModelBuilder(member).BuildTreeViewModel(derivedClassesTree.Children);
return new ContextActionsPopup { Actions = popupViewModel, Symbol = member };
}
class PopupViewModelBuilder
@ -92,7 +90,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -92,7 +90,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
}
/*
class OverridesPopupTreeViewModelBuilder : PopupViewModelBuilder
{
IMember member;
@ -106,13 +103,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -106,13 +103,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring
protected ContextActionViewModel MakeGoToMemberAction(ITypeDefinition containingClass, ObservableCollection<ContextActionViewModel> childActions)
{
var overridenMember = MemberLookupHelper.FindSimilarMember(containingClass, this.member);
if (overridenMember == null || overridenMember.Region.IsEmpty)
IMember derivedMember = FindReferenceService.GetDerivedMember(member, containingClass);
if (derivedMember == null)
return null;
return new ContextActionViewModel {
Action = new GoToMemberAction(overridenMember, this.LabelAmbience),
Image = ClassBrowserIconService.GetIcon(overridenMember).ImageSource,
Action = new GoToMemberAction(derivedMember, this.LabelAmbience),
Image = ClassBrowserIconService.GetIcon(derivedMember).ImageSource,
Comment = string.Format("(in {0})", containingClass.FullName),
ChildActions = childActions
};
@ -124,6 +121,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -124,6 +121,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring
classTree.Select(
node => MakeGoToMemberAction(node.Content, BuildTreeViewModel(node.Children))).Where(action => action != null));
}
}*/
}
}
}

125
src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs

@ -15,7 +15,8 @@ using ICSharpCode.SharpDevelop.Project; @@ -15,7 +15,8 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Refactoring
{
/// <summary>
/// Description of FindReferenceService.
/// Language-independent finds references implementation.
/// This call will call into the individual language bindings to perform the job.
/// </summary>
public static class FindReferenceService
{
@ -85,6 +86,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -85,6 +86,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
}
/// <summary>
/// Finds references to a local variable.
/// </summary>
public static void FindReferences(IVariable variable, Action<Reference> callback)
{
if (variable == null)
@ -96,8 +100,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -96,8 +100,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
ParseInformation pi = ParserService.Parse(fileName);
if (pi == null || parser == null)
return;
IProject project = ParserService.GetProject(pi.ProjectContent);
var context = project != null ? project.TypeResolveContext : ParserService.GetDefaultTypeResolveContext();
var context = ParserService.GetTypeResolveContext(pi.ProjectContent);
parser.FindLocalReferences(pi, variable, context, callback);
}
#endregion
@ -192,6 +195,122 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -192,6 +195,122 @@ namespace ICSharpCode.SharpDevelop.Refactoring
return dict;
}
#endregion
#region GetBaseMember
/// <summary>
/// Gets the base member that has the same signature.
/// </summary>
public static IMember GetBaseMember(IMember member)
{
return GetBaseMembers(member, false).FirstOrDefault();
}
/// <summary>
/// Gets all base members that have the same signature.
/// </summary>
/// <returns>
/// List of base members with the same signature. The member from the derived-most base class is returned first.
/// </returns>
public static IEnumerable<IMember> GetBaseMembers(IMember member, bool includeImplementedInterfaces)
{
if (member == null)
throw new ArgumentNullException("member");
member = member.MemberDefinition;
IMethod method = member as IMethod;
IProperty property = member as IProperty;
IEvent ev = member as IEvent;
IField field = member as IField;
using (var ctx = ParserService.GetTypeResolveContext(member.ProjectContent).Synchronize()) {
IEnumerable<IType> allBaseTypes;
if (includeImplementedInterfaces) {
allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(ctx);
} else {
allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes(ctx);
}
foreach (IType baseType in allBaseTypes.Reverse()) {
if (baseType == member.DeclaringTypeDefinition)
continue;
if (method != null) {
foreach (IMethod baseMethod in baseType.GetMethods(
ctx, m => m.Name == method.Name && m.Parameters.Count == method.Parameters.Count && m.TypeParameters.Count == method.TypeParameters.Count,
GetMemberOptions.IgnoreInheritedMembers))
{
if (ParameterListComparer.Compare(ctx, method, baseMethod))
yield return baseMethod;
}
}
if (property != null) {
foreach (IProperty baseProperty in baseType.GetProperties(
ctx, p => p.Name == property.Name && p.Parameters.Count == property.Parameters.Count,
GetMemberOptions.IgnoreInheritedMembers))
{
if (ParameterListComparer.Compare(ctx, property, baseProperty))
yield return baseProperty;
}
}
if (ev != null) {
IEvent baseEvent = baseType.GetEvents(ctx, e => e.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
if (baseEvent != null)
yield return baseEvent;
}
// Fields can't be overridden, but we handle them anyways, just for consistence
if (field != null) {
IField baseField = baseType.GetFields(ctx, f => f.Name == field.Name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
if (baseField != null)
yield return baseField;
}
}
}
}
#endregion
#region GetDerivedMember
/// <summary>
/// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'.
/// </summary>
public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType)
{
if (baseMember == null)
throw new ArgumentNullException("baseMember");
baseMember = baseMember.MemberDefinition;
IMethod method = baseMember as IMethod;
if (method != null) {
foreach (IMethod derivedMethod in derivedType.Methods) {
if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) {
if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) {
// The method could override the base method:
if (FindReferenceService.GetBaseMembers(derivedMethod, true).Any(m => m.MemberDefinition == baseMember))
return derivedMethod;
}
}
}
}
IProperty property = baseMember as IProperty;
if (property != null) {
foreach (IProperty derivedProperty in derivedType.Properties) {
if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) {
// The property could override the base property:
if (FindReferenceService.GetBaseMembers(derivedProperty, true).Any(m => m.MemberDefinition == baseMember))
return derivedProperty;
}
}
}
if (baseMember is IEvent) {
foreach (IEvent derivedEvent in derivedType.Events) {
if (derivedEvent.Name == baseMember.Name)
return derivedEvent;
}
}
if (baseMember is IField) {
foreach (IField derivedField in derivedType.Fields) {
if (derivedField.Name == baseMember.Name)
return derivedField;
}
}
return null;
}
#endregion
}
public class SymbolSearchArgs

6
src/Main/Base/Project/Src/Services/RefactoringService/GoToMemberAction.cs

@ -2,10 +2,11 @@ @@ -2,10 +2,11 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Refactoring
{
/*
public class GoToMemberAction : IContextAction
{
public string Title { get; private set; }
@ -18,7 +19,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -18,7 +19,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
if (member == null)
throw new ArgumentNullException("member");
this.Member = member;
this.Title = ambience.Convert(member);
this.Title = ambience.ConvertEntity(member, ParserService.CurrentTypeResolveContext);
}
public void Execute()
@ -26,5 +27,4 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -26,5 +27,4 @@ namespace ICSharpCode.SharpDevelop.Refactoring
NavigationService.NavigateTo(this.Member);
}
}
*/
}

1
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -72,6 +72,7 @@ namespace ICSharpCode.SharpDevelop @@ -72,6 +72,7 @@ namespace ICSharpCode.SharpDevelop
/// <summary>
/// Runs an action for all elements in the input.
/// </summary>
[Obsolete("Please use a regular foreach loop instead. ForEach() is executed for its side-effects, and side-effects mix poorly with a functional programming style.")]
public static void ForEach<T>(this IEnumerable<T> input, Action<T> action)
{
if (input == null)

Loading…
Cancel
Save