Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@204 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
21 changed files with 638 additions and 305 deletions
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version value="$version"/>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
/// <summary>
|
||||
/// Class describing a contexts in which an expressions can be.
|
||||
/// Serves as filter for code completion results.
|
||||
/// </summary>
|
||||
public abstract class ExpressionContext |
||||
{ |
||||
public abstract bool ShowEntry(object o); |
||||
|
||||
/// <summary>Default/unknown context</summary>
|
||||
public static ExpressionContext Default = new DefaultExpressionContext(); |
||||
|
||||
/// <summary>Context expects a namespace name</summary>
|
||||
/// <example>using *expr*;</example>
|
||||
public static ExpressionContext Namespace = new NamespaceExpressionContext(); |
||||
|
||||
/// <summary>Context expects a type name</summary>
|
||||
/// <example>typeof(*expr*), is *expr*, using(*expr* ...)</example>
|
||||
public static ExpressionContext Type = new TypeExpressionContext(null, false); |
||||
|
||||
/// <summary>Context expects a non-abstract type that has accessible constructors</summary>
|
||||
/// <example>new *expr*();</example>
|
||||
public static ExpressionContext ConstructableType = new TypeExpressionContext(null, true); |
||||
|
||||
/// <summary>Context expects a type name which has special base type</summary>
|
||||
/// <param name="baseClass">The class the expression must derive from.</param>
|
||||
/// <param name="allowAbstract">Specifies whether classes must be constructable.</param>
|
||||
/// <example>catch(*expr* ...), using(*expr* ...), throw new ***</example>
|
||||
public static ExpressionContext TypeDerivingFrom(IClass baseClass, bool mustBeConstructable) |
||||
{ |
||||
return new TypeExpressionContext(baseClass, mustBeConstructable); |
||||
} |
||||
|
||||
class DefaultExpressionContext : ExpressionContext |
||||
{ |
||||
public override bool ShowEntry(object o) |
||||
{ |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
class NamespaceExpressionContext : ExpressionContext |
||||
{ |
||||
public override bool ShowEntry(object o) |
||||
{ |
||||
return o is string; |
||||
} |
||||
} |
||||
|
||||
class TypeExpressionContext : ExpressionContext |
||||
{ |
||||
IClass baseClass; |
||||
bool mustBeConstructable; |
||||
|
||||
public TypeExpressionContext(IClass baseClass, bool mustBeConstructable) |
||||
{ |
||||
this.baseClass = baseClass; |
||||
this.mustBeConstructable = mustBeConstructable; |
||||
} |
||||
|
||||
public override bool ShowEntry(object o) |
||||
{ |
||||
if (o is string) |
||||
return true; |
||||
IClass c = o as IClass; |
||||
if (c == null) |
||||
return false; |
||||
if (mustBeConstructable) { |
||||
if (c.IsAbstract || c.IsStatic) return false; |
||||
if (c.ClassType == ClassType.Enum) return false; |
||||
} |
||||
if (baseClass == null) |
||||
return true; |
||||
return c.IsTypeInInheritanceTree(baseClass); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,98 @@
@@ -0,0 +1,98 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version value="$version"/>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Core; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Dom |
||||
{ |
||||
/// <summary>
|
||||
/// The GetClassReturnType is used when the class should be resolved on demand, but the
|
||||
/// full name is already known. Example: ReflectionReturnType
|
||||
/// </summary>
|
||||
public sealed class GetClassReturnType : ProxyReturnType |
||||
{ |
||||
IProjectContent content; |
||||
string fullName; |
||||
string shortName; |
||||
|
||||
public GetClassReturnType(IProjectContent content, string fullName) |
||||
{ |
||||
this.content = content; |
||||
this.fullName = fullName; |
||||
int pos = fullName.LastIndexOf('.'); |
||||
if (pos < 0) |
||||
shortName = fullName; |
||||
else |
||||
shortName = fullName.Substring(pos + 1); |
||||
} |
||||
|
||||
public override bool IsDefaultReturnType { |
||||
get { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
public override bool Equals(object o) |
||||
{ |
||||
GetClassReturnType rt = o as GetClassReturnType; |
||||
if (rt == null) { |
||||
IReturnType rt2 = o as IReturnType; |
||||
if (rt2 != null && rt2.IsDefaultReturnType) |
||||
return rt2.FullyQualifiedName == fullName; |
||||
else |
||||
return false; |
||||
} |
||||
return fullName == rt.fullName; |
||||
} |
||||
|
||||
public override int GetHashCode() |
||||
{ |
||||
return content.GetHashCode() ^ fullName.GetHashCode(); |
||||
} |
||||
|
||||
// TODO: Cache BaseType until a new CompilationUnit is generated (static counter in ParserService)
|
||||
public override IReturnType BaseType { |
||||
get { |
||||
IClass c = content.GetClass(fullName); |
||||
return (c != null) ? c.DefaultReturnType : null; |
||||
} |
||||
} |
||||
|
||||
public override string FullyQualifiedName { |
||||
get { |
||||
return fullName; |
||||
} |
||||
} |
||||
|
||||
public override string Name { |
||||
get { |
||||
return shortName; |
||||
} |
||||
} |
||||
|
||||
public override string Namespace { |
||||
get { |
||||
IReturnType baseType = BaseType; |
||||
return (baseType != null) ? baseType.Namespace : fullName.Substring(0, fullName.LastIndexOf('.')); |
||||
} |
||||
} |
||||
|
||||
public override string DotNetName { |
||||
get { |
||||
IReturnType baseType = BaseType; |
||||
return (baseType != null) ? baseType.DotNetName : fullName; |
||||
} |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return String.Format("[GetClassReturnType: {0}]", fullName); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,136 @@
@@ -0,0 +1,136 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
|
||||
// <version value="$version"/>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Drawing; |
||||
using System.Diagnostics; |
||||
using System.Windows.Forms; |
||||
using System.Reflection; |
||||
using System.Collections; |
||||
using System.Collections.Specialized; |
||||
using System.Xml; |
||||
|
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Internal.Templates; |
||||
using ICSharpCode.TextEditor.Document; |
||||
using ICSharpCode.TextEditor; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.TextEditor.Gui.CompletionWindow; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor |
||||
{ |
||||
public abstract class AbstractCompletionDataProvider : ICompletionDataProvider |
||||
{ |
||||
Hashtable insertedElements = new Hashtable(); |
||||
Hashtable insertedPropertiesElements = new Hashtable(); |
||||
Hashtable insertedEventElements = new Hashtable(); |
||||
|
||||
public ImageList ImageList { |
||||
get { |
||||
return ClassBrowserIconService.ImageList; |
||||
} |
||||
} |
||||
|
||||
protected int caretLineNumber; |
||||
protected int caretColumn; |
||||
protected string fileName; |
||||
protected string preSelection = null; |
||||
|
||||
public string PreSelection { |
||||
get { |
||||
return preSelection; |
||||
} |
||||
} |
||||
protected ArrayList completionData = null; |
||||
protected ExpressionContext context = ExpressionContext.Default; |
||||
|
||||
public ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped) |
||||
{ |
||||
completionData = new ArrayList(); |
||||
this.fileName = fileName; |
||||
IDocument document = textArea.Document; |
||||
|
||||
// the parser works with 1 based coordinates
|
||||
caretLineNumber = document.GetLineNumberForOffset(textArea.Caret.Offset) + 1; |
||||
caretColumn = textArea.Caret.Offset - document.GetLineSegment(caretLineNumber - 1).Offset + 1; |
||||
|
||||
GenerateCompletionData(textArea, charTyped); |
||||
|
||||
return (ICompletionData[])completionData.ToArray(typeof(ICompletionData)); |
||||
} |
||||
|
||||
protected string GetExpression(TextArea textArea) |
||||
{ |
||||
IDocument document = textArea.Document; |
||||
IExpressionFinder expressionFinder = ParserService.GetExpressionFinder(fileName); |
||||
if (expressionFinder == null) { |
||||
return TextUtilities.GetExpressionBeforeOffset(textArea, textArea.Caret.Offset); |
||||
} else { |
||||
ExpressionResult er = expressionFinder.FindExpression(document.GetText(0, textArea.Caret.Offset), textArea.Caret.Offset - 1); |
||||
if (er.Context != ExpressionContext.Default) |
||||
context = er.Context; |
||||
return er.Expression; |
||||
} |
||||
} |
||||
|
||||
protected abstract void GenerateCompletionData(TextArea textArea, char charTyped); |
||||
|
||||
protected void AddResolveResults(ICollection list) |
||||
{ |
||||
if (list == null) { |
||||
return; |
||||
} |
||||
completionData.Capacity += list.Count; |
||||
foreach (object o in list) { |
||||
if (context != null && !context.ShowEntry(o)) |
||||
continue; |
||||
if (o is string) { |
||||
completionData.Add(new CodeCompletionData(o.ToString(), ClassBrowserIconService.NamespaceIndex)); |
||||
} else if (o is IClass) { |
||||
completionData.Add(new CodeCompletionData((IClass)o)); |
||||
} else if (o is IProperty) { |
||||
IProperty property = (IProperty)o; |
||||
if (property.Name != null && insertedPropertiesElements[property.Name] == null) { |
||||
completionData.Add(new CodeCompletionData(property)); |
||||
insertedPropertiesElements[property.Name] = property; |
||||
} |
||||
} else if (o is IMethod) { |
||||
IMethod method = (IMethod)o; |
||||
if (method.Name != null &&!method.IsConstructor) { |
||||
CodeCompletionData ccd = new CodeCompletionData(method); |
||||
if (insertedElements[method.Name] == null) { |
||||
completionData.Add(ccd); |
||||
insertedElements[method.Name] = ccd; |
||||
} else { |
||||
CodeCompletionData oldMethod = (CodeCompletionData)insertedElements[method.Name]; |
||||
++oldMethod.Overloads; |
||||
} |
||||
} |
||||
} else if (o is IField) { |
||||
completionData.Add(new CodeCompletionData((IField)o)); |
||||
} else if (o is IEvent) { |
||||
IEvent e = (IEvent)o; |
||||
if (e.Name != null && insertedEventElements[e.Name] == null) { |
||||
completionData.Add(new CodeCompletionData(e)); |
||||
insertedEventElements[e.Name] = e; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected void AddResolveResults(ResolveResult results) |
||||
{ |
||||
insertedElements.Clear(); |
||||
insertedPropertiesElements.Clear(); |
||||
insertedEventElements.Clear(); |
||||
|
||||
if (results != null) { |
||||
AddResolveResults(results.GetCompletionData(ParserService.CurrentProjectContent)); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
using System; |
||||
using System.Collections; |
||||
using System.IO; |
||||
using NUnit.Framework; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Dom; |
||||
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Tests |
||||
{ |
||||
[TestFixture] |
||||
public class RefactoringTests |
||||
{ |
||||
const string code = @"using System;
|
||||
abstract class BaseClass { |
||||
protected abstract void FirstMethod(); |
||||
|
||||
protected virtual void SecondMethod() |
||||
{ |
||||
} |
||||
} |
||||
class DerivedClass : BaseClass |
||||
{ |
||||
protected override void FirstMethod() |
||||
{ |
||||
SecondMethod(); |
||||
} |
||||
} |
||||
class SecondDerivedClass : DerivedClass |
||||
{ |
||||
protected override void FirstMethod() |
||||
{ |
||||
Console.Beep(); |
||||
} |
||||
protected override void SecondMethod() |
||||
{ |
||||
FirstMethod(); |
||||
} |
||||
} |
||||
";
|
||||
|
||||
// TODO: Write unit tests for find references / find overrides / go to base class.
|
||||
} |
||||
} |
Loading…
Reference in new issue