Browse Source

Fixed several minor code completion bugs.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2949 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 18 years ago
parent
commit
7414e9ad6a
  1. 23
      src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs
  2. 11
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  3. 40
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  4. 115
      src/Main/Base/Test/NRefactoryResolverTests.cs
  5. 1
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs
  6. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs
  7. 5
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs
  8. 5
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs
  9. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs
  10. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs
  11. 7
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs
  12. 14
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs
  13. 11
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs
  14. 29
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs
  15. 27
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  16. 8
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
  17. 32
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs
  18. 36
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

23
src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs

@ -73,7 +73,12 @@ namespace ICSharpCode.PythonBinding @@ -73,7 +73,12 @@ namespace ICSharpCode.PythonBinding
DomRegion bodyRegion = GetBodyRegion(node.Body);
DomRegion region = GetMethodRegion(node);
DefaultMethod method = new DefaultMethod(methodName, CreateReturnType(methodName, currentClass), ModifierEnum.Public, region, bodyRegion, currentClass);
DefaultMethod method;
if (methodName == "__init__") {
method = new Constructor(ModifierEnum.Public, region, bodyRegion, currentClass);
} else {
method = new DefaultMethod(methodName, new DefaultReturnType(currentClass), ModifierEnum.Public, region, bodyRegion, currentClass);
}
foreach (IParameter parameter in ConvertParameters(node.Parameters)) {
method.Parameters.Add(parameter);
}
@ -105,7 +110,7 @@ namespace ICSharpCode.PythonBinding @@ -105,7 +110,7 @@ namespace ICSharpCode.PythonBinding
/// Note that SharpDevelop line numbers are zero based but the
/// DomRegion values are one based. IronPython columns are zero
/// based but the lines are one based.
/// Also note that IronPython seems to get the end column
/// Also note that IronPython seems to get the end column
/// incorrect for classes.
/// </remarks>
DomRegion GetBodyRegion(Node node)
@ -140,18 +145,6 @@ namespace ICSharpCode.PythonBinding @@ -140,18 +145,6 @@ namespace ICSharpCode.PythonBinding
return new DomRegion(statement.Start.Line, statement.Start.Column + 1, statement.Start.Line, statement.Body.Start.Column + 2);
}
/// <summary>
/// Creates a return type from the current class and method name.
/// If the method name is __init__ then this method returns null.
/// </summary>
IReturnType CreateReturnType(string methodName, IClass c)
{
if (methodName == "__init__") {
return null;
}
return new DefaultReturnType(currentClass);
}
/// <summary>
/// Looks for any base types for the class defined in the
/// list of expressions and adds them to the class.
@ -174,7 +167,7 @@ namespace ICSharpCode.PythonBinding @@ -174,7 +167,7 @@ namespace ICSharpCode.PythonBinding
/// </summary>
void AddBaseType(IClass c, string name)
{
c.BaseTypes.Add(new SearchClassReturnType(c.ProjectContent, c, 0, 0, name, 0));
c.BaseTypes.Add(new SearchClassReturnType(c.ProjectContent, c, 0, 0, name, 0));
}
/// <summary>

11
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -48,16 +48,21 @@ namespace ICSharpCode.SharpDevelop @@ -48,16 +48,21 @@ namespace ICSharpCode.SharpDevelop
ProjectService.ProjectItemAdded += OnProjectItemAdded;
ProjectService.ProjectItemRemoved += OnProjectItemRemoved;
UpdateDefaultImports(items);
progressMonitor.BeginTask("Resolving references for " + project.Name, 0, false);
// TODO: Translate me
progressMonitor.TaskName = "Resolving references for " + project.Name + "...";
project.ResolveAssemblyReferences();
progressMonitor.Done();
foreach (ProjectItem item in items) {
if (!initializing) return; // abort initialization
if (item.ItemType == ItemType.Reference
|| item.ItemType == ItemType.ProjectReference
|| item.ItemType == ItemType.COMReference)
{
AddReference(item as ReferenceProjectItem, false);
ReferenceProjectItem reference = item as ReferenceProjectItem;
if (reference != null) {
// TODO: Translate me
progressMonitor.TaskName = "Loading " + reference.ShortName + "...";
AddReference(reference, false);
}
}
}
UpdateReferenceInterDependencies();

40
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -172,26 +172,32 @@ namespace ICSharpCode.SharpDevelop @@ -172,26 +172,32 @@ namespace ICSharpCode.SharpDevelop
}
}
WorkbenchSingleton.SafeThreadAsyncCall(ProjectService.ParserServiceCreatedProjectContents);
int workAmount = 0;
foreach (ParseProjectContent newContent in createdContents) {
if (abortLoadSolutionProjectsThread) return;
try {
newContent.Initialize1(progressMonitor);
workAmount += newContent.GetInitializationWorkAmount();
} catch (Exception e) {
MessageService.ShowError(e, "Error while initializing project references:" + newContent);
try {
progressMonitor.BeginTask("Loading references...", createdContents.Count, false);
int workAmount = 0;
for (int i = 0; i < createdContents.Count; i++) {
if (abortLoadSolutionProjectsThread) return;
ParseProjectContent newContent = createdContents[i];
progressMonitor.WorkDone = i;
try {
newContent.Initialize1(progressMonitor);
workAmount += newContent.GetInitializationWorkAmount();
} catch (Exception e) {
MessageService.ShowError(e, "Error while initializing project references:" + newContent);
}
}
}
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false);
foreach (ParseProjectContent newContent in createdContents) {
if (abortLoadSolutionProjectsThread) break;
try {
newContent.Initialize2(progressMonitor);
} catch (Exception e) {
MessageService.ShowError(e, "Error while initializing project contents:" + newContent);
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false);
foreach (ParseProjectContent newContent in createdContents) {
if (abortLoadSolutionProjectsThread) return;
try {
newContent.Initialize2(progressMonitor);
} catch (Exception e) {
MessageService.ShowError(e, "Error while initializing project contents:" + newContent);
}
}
} finally {
progressMonitor.Done();
}
progressMonitor.Done();
}
static void InitAddedProject(object state)

115
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -278,6 +278,48 @@ interface IInterface2 { @@ -278,6 +278,48 @@ interface IInterface2 {
ResolveResult result = Resolve(program, "new ThisClassDoesNotExist()", 3);
Assert.IsNull(result);
}
[Test]
public void OverriddenMethodCallTest()
{
string program = @"class A {
void Method() {
}
public abstract int GetRandomNumber();
}
class B : A {
public override int GetRandomNumber() {
return 4; // chosen by fair dice roll.
// guaranteed to be random
}
}
";
MemberResolveResult result = Resolve<MemberResolveResult>(program, "new B().GetRandomNumber()", 3);
Assert.AreEqual("B.GetRandomNumber", result.ResolvedMember.FullyQualifiedName);
}
[Test]
public void OverriddenMethodCallTest2()
{
string program = @"class A {
void Method() {
}
public abstract int GetRandomNumber(string a, A b);
}
class B : A {
public override int GetRandomNumber(string b, A a) {
return 4; // chosen by fair dice roll.
// guaranteed to be random
}
}
";
MemberResolveResult result = Resolve<MemberResolveResult>(program, "new B().GetRandomNumber(\"x\", this)", 3);
Assert.AreEqual("B.GetRandomNumber", result.ResolvedMember.FullyQualifiedName);
}
[Test]
public void MethodCallTest()
@ -1039,7 +1081,7 @@ End Class @@ -1039,7 +1081,7 @@ End Class
Assert.AreEqual("B", result.ResolvedType.FullyQualifiedName);
Assert.IsTrue(ContainsMember(result.GetCompletionData(result.CallingClass.ProjectContent), mrr.ResolvedMember.FullyQualifiedName));
result = ResolveVB<ResolveResult>(program, "mybase", 7);
result = ResolveVB<BaseResolveResult>(program, "mybase", 7);
Assert.AreEqual("B", result.ResolvedType.FullyQualifiedName);
Assert.IsFalse(ContainsMember(result.GetCompletionData(result.CallingClass.ProjectContent), mrr.ResolvedMember.FullyQualifiedName));
}
@ -1099,7 +1141,7 @@ class B { @@ -1099,7 +1141,7 @@ class B {
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsFalse(MemberExists(cd, "member"), "member should not be in completion lookup");
result = Resolve(program, "b.member", 4);
Assert.IsNotNull(result, "member should be found even though it is not visible!");
Assert.IsTrue(result != null && result.IsValid, "member should be found even though it is not visible!");
}
[Test]
@ -1120,7 +1162,7 @@ class B { @@ -1120,7 +1162,7 @@ class B {
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsTrue(MemberExists(cd, "member"), "member should be in completion lookup");
result = Resolve(program, "a.member", 4);
Assert.IsNotNull(result, "member should be found!");
Assert.IsTrue(result != null && result.IsValid, "member should be found!");
}
[Test]
@ -1141,7 +1183,7 @@ class B { @@ -1141,7 +1183,7 @@ class B {
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsFalse(MemberExists(cd, "member"), "member should not be in completion lookup");
result = Resolve(program, "b.member", 4);
Assert.IsNotNull(result, "member should be found even though it is not visible!");
Assert.IsTrue(result != null && result.IsValid, "member should be found even though it is not visible!");
}
[Test]
@ -1162,7 +1204,70 @@ class B { @@ -1162,7 +1204,70 @@ class B {
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsFalse(MemberExists(cd, "member"), "member should not be in completion lookup");
result = Resolve(program, "b.member", 4);
Assert.IsNotNull(result, "member should be found even though it is not visible!");
Assert.IsTrue(result != null && result.IsValid, "member should be found even though it is not visible!");
}
[Test]
public void ProtectedMemberVisibleWhenUsingBaseReference()
{
string program = @"using System;
class A : B {
void TestMethod(B b) {
}
}
class B {
protected int member;
}
";
ResolveResult result = Resolve(program, "base", 4);
Assert.IsNotNull(result);
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsTrue(MemberExists(cd, "member"), "member should be in completion lookup");
result = Resolve(program, "base.member", 4);
Assert.IsTrue(result != null && result.IsValid, "member should be found!");
}
[Test]
public void ProtectedMethodInvisibleWhenNotUsingReferenceOfCurrentTypeTest()
{
string program = @"using System;
class A : B {
void TestMethod(B b) {
}
}
class B {
protected int Method();
}
";
ResolveResult result = Resolve(program, "b", 4);
Assert.IsNotNull(result);
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsFalse(MemberExists(cd, "Method"), "member should not be in completion lookup");
result = Resolve(program, "b.Method()", 4);
Assert.IsTrue(result != null && result.IsValid, "method should be found even though it is invisible!");
}
[Test]
public void ProtectedMethodVisibleWhenUsingBaseReference()
{
string program = @"using System;
class A : B {
void TestMethod(B b) {
}
}
class B {
protected int Method();
}
";
ResolveResult result = Resolve(program, "base", 4);
Assert.IsNotNull(result);
ArrayList cd = result.GetCompletionData(lastPC);
Assert.IsTrue(MemberExists(cd, "Method"), "member should be in completion lookup");
result = Resolve(program, "base.Method()", 4);
Assert.IsTrue(result != null && result.IsValid, "method should be found!");
}
bool MemberExists(ArrayList members, string name)

1
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs

@ -125,6 +125,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -125,6 +125,7 @@ namespace ICSharpCode.SharpDevelop.Dom
return conversionFlags;
}
set {
CheckThread();
conversionFlags = value;
}
}

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs

@ -382,7 +382,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp @@ -382,7 +382,7 @@ namespace ICSharpCode.SharpDevelop.Dom.CSharp
builder.Append(GetModifier(m));
}
if (m.ReturnType != null && ShowReturnType) {
if (!m.IsConstructor && m.ReturnType != null && ShowReturnType) {
builder.Append(Convert(m.ReturnType));
builder.Append(' ');
}

5
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs

@ -338,7 +338,10 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -338,7 +338,10 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
m.ReturnType = CreateType(this.ProjectContent, m, method.ReturnType.ReturnType);
if (method.IsConstructor)
m.ReturnType = this.DefaultReturnType;
else
m.ReturnType = CreateType(this.ProjectContent, m, method.ReturnType.ReturnType);
AddAttributes(CompilationUnit.ProjectContent, m.Attributes, method.CustomAttributes);
if (this.ClassType == ClassType.Interface) {
m.Modifiers = ModifierEnum.Public | ModifierEnum.Abstract;

5
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs

@ -41,10 +41,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -41,10 +41,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public override int GetHashCode()
{
if (fullyQualifiedName == null)
return 0;
else
return fullyQualifiedName.GetHashCode();
return DefaultReturnType.GetHashCode(this);
}
string fullyQualifiedName = null;

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs

@ -11,7 +11,7 @@ using System.Collections.Generic; @@ -11,7 +11,7 @@ using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Dom
{
/// <summary>
/// Combines multiple return types for use in contraints.
/// Combines multiple return types for use in constraints.
/// </summary>
public sealed class CombinedReturnType : AbstractReturnType
{

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs

@ -165,7 +165,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -165,7 +165,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public virtual bool IsConstructor {
get {
return ReturnType == null || Name == "#ctor";
return Name == "#ctor";
}
}

7
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs

@ -35,6 +35,13 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -35,6 +35,13 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public static int GetHashCode(IReturnType rt)
{
if (rt == null)
return 0;
return (rt.FullyQualifiedName ?? "").GetHashCode() ^ rt.TypeArgumentCount;
}
IClass c;
public DefaultReturnType(IClass c)

14
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs

@ -39,20 +39,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -39,20 +39,6 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public override bool Equals(IReturnType o)
{
IReturnType rt = o as IReturnType;
if (rt != null && rt.IsDefaultReturnType)
return DefaultReturnType.Equals(this, rt);
else
return false;
}
public override int GetHashCode()
{
return content.GetHashCode() ^ fullName.GetHashCode() ^ (typeArgumentCount * 5);
}
public override IReturnType BaseType {
get {
IClass c = content.GetClass(fullName, typeArgumentCount);

11
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs

@ -21,14 +21,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -21,14 +21,17 @@ namespace ICSharpCode.SharpDevelop.Dom
public sealed override bool Equals(object obj)
{
if (obj == this)
return true;
else
return Equals(obj as IReturnType);
return Equals(obj as IReturnType);
}
public virtual bool Equals(IReturnType other)
{
// this check is necessary because the underlying Equals implementation
// expects to be able to retrieve the base type of "other" - which fails when
// this==other and therefore other.busy.
if (other == this)
return true;
IReturnType baseType = BaseType;
bool tmp = (baseType != null && TryEnter()) ? baseType.Equals(other) : false;
busy = false;

29
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs

@ -41,23 +41,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -41,23 +41,6 @@ namespace ICSharpCode.SharpDevelop.Dom
shortName = name.Substring(pos + 1);
}
public override bool Equals(IReturnType o)
{
IReturnType rt2 = o as IReturnType;
if (rt2 != null && rt2.IsDefaultReturnType)
return DefaultReturnType.Equals(this, rt2);
else
return false;
}
public override int GetHashCode()
{
unchecked {
return declaringClass.GetHashCode() ^ name.GetHashCode()
^ (typeParameterCount << 16 + caretLine << 8 + caretColumn);
}
}
// we need to use a static Dictionary as cache to provide a easy was to clear all cached
// BaseTypes.
// When the cached BaseTypes could not be cleared as soon as the parse information is updated
@ -102,22 +85,26 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -102,22 +85,26 @@ namespace ICSharpCode.SharpDevelop.Dom
public override IReturnType BaseType {
get {
if (isSearching)
return null;
IReturnType type;
lock (cache) {
if (isSearching)
return null;
if (cache.TryGetValue(this, out type))
return type;
isSearching = true;
}
try {
isSearching = true;
type = pc.SearchType(new SearchTypeRequest(name, typeParameterCount, declaringClass, caretLine, caretColumn)).Result;
lock (cache) {
isSearching = false;
cache[this] = type;
}
return type;
} finally {
} catch {
isSearching = false;
throw;
}
}
}

27
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

@ -34,15 +34,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -34,15 +34,17 @@ namespace ICSharpCode.SharpDevelop.Dom
public static List<IList<IMember>> LookupMember(
IReturnType type, string name, IClass callingClass,
LanguageProperties language, bool isInvocation)
LanguageProperties language, bool isInvocation, bool? isClassInInheritanceTree)
{
if (language == null)
throw new ArgumentNullException("language");
bool isClassInInheritanceTree = false;
IClass underlyingClass = type.GetUnderlyingClass();
if (underlyingClass != null)
isClassInInheritanceTree = underlyingClass.IsTypeInInheritanceTree(callingClass);
if (isClassInInheritanceTree == null) {
isClassInInheritanceTree = false;
IClass underlyingClass = type.GetUnderlyingClass();
if (underlyingClass != null)
isClassInInheritanceTree = underlyingClass.IsTypeInInheritanceTree(callingClass);
}
IEnumerable<IMember> members;
if (language == LanguageProperties.VBNet && language.NameComparer.Equals(name, "New")) {
@ -51,7 +53,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -51,7 +53,7 @@ namespace ICSharpCode.SharpDevelop.Dom
members = GetAllMembers(type).Where(m => language.NameComparer.Equals(m.Name, name));
}
return LookupMember(members, callingClass, isClassInInheritanceTree, isInvocation);
return LookupMember(members, callingClass, (bool)isClassInInheritanceTree, isInvocation);
}
class SignatureComparer : IEqualityComparer<IMethod>
@ -180,13 +182,20 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -180,13 +182,20 @@ namespace ICSharpCode.SharpDevelop.Dom
/// </summary>
public static List<IMember> GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language)
{
if (language == null)
throw new ArgumentNullException("language");
bool isClassInInheritanceTree = false;
IClass underlyingClass = rt.GetUnderlyingClass();
if (underlyingClass != null)
isClassInInheritanceTree = underlyingClass.IsTypeInInheritanceTree(callingClass);
return GetAccessibleMembers(rt, callingClass, language, isClassInInheritanceTree);
}
/// <summary>
/// Gets all accessible members, including indexers and constructors.
/// </summary>
public static List<IMember> GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language, bool isClassInInheritanceTree)
{
if (language == null)
throw new ArgumentNullException("language");
List<IMember> result = new List<IMember>();
foreach (var g in GetAllMembers(rt).GroupBy(m => m.Name, language.NameComparer)) {

8
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs

@ -572,7 +572,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -572,7 +572,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
ResolveResult rr = ResolveMember(tmp.DefaultReturnType, identifier,
identifierExpression.TypeArguments,
identifierExpression.Parent is InvocationExpression,
false);
false, null);
if (rr != null && rr.IsValid)
return rr;
// also try to resolve the member in outer classes
@ -588,7 +588,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -588,7 +588,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
ResolveResult rr = ResolveMember(c.DefaultReturnType, identifier,
identifierExpression.TypeArguments,
identifierExpression.Parent is InvocationExpression,
false);
false, null);
if (rr != null && rr.IsValid)
return rr;
}
@ -626,9 +626,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -626,9 +626,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
#region ResolveMember
internal ResolveResult ResolveMember(IReturnType declaringType, string memberName,
List<TypeReference> typeArguments, bool isInvocation,
bool allowExtensionMethods)
bool allowExtensionMethods, bool? isClassInInheritanceTree)
{
List<IList<IMember>> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation);
List<IList<IMember>> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation, isClassInInheritanceTree);
if (members != null && typeArguments != null && typeArguments.Count != 0) {
List<IReturnType> typeArgs = typeArguments.ConvertAll(r => TypeVisitor.CreateReturnType(r, this));

32
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs

@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return new VBBaseOrThisReferenceInConstructorResolveResult(
resolver.CallingClass, resolver.CallingMember, resolver.CallingClass.BaseType);
} else {
return CreateResolveResult(resolver.CallingClass.BaseType);
return new BaseResolveResult(resolver.CallingClass, resolver.CallingMember, resolver.CallingClass.BaseType);
}
}
@ -296,7 +296,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -296,7 +296,11 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (firstResult == null)
firstResult = result;
}
return CreateMemberResolveResult(firstResult);
if (firstResult != null) {
return CreateMemberResolveResult(firstResult);
} else {
return FallbackResolveMethod(invocationExpression, mgrr, argumentTypes);
}
} else if (rr != null && rr.ResolvedType != null) {
IClass c = rr.ResolvedType.GetUnderlyingClass();
if (c != null && c.ClassType == ClassType.Delegate) {
@ -319,6 +323,26 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -319,6 +323,26 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return null;
}
ResolveResult FallbackResolveMethod(InvocationExpression invocation, MethodGroupResolveResult mgrr, IReturnType[] argumentTypes)
{
// method not found, let's try if we can find a method if we violate the
// accessibility rules
MemberReferenceExpression mre = invocation.TargetObject as MemberReferenceExpression;
if (mre != null) {
List<IMethod> methods = mgrr.ContainingType.GetMethods().Where(m => resolver.IsSameName(m.Name, mre.MemberName)).ToList();
bool resultIsAcceptable;
IMethod result = MemberLookupHelper.FindOverload(
methods,
argumentTypes, out resultIsAcceptable);
if (result != null) {
return CreateMemberResolveResult(result);
}
}
// TODO: method still not found, now return invalid ResolveResult describing the expected method
return null;
}
public override object VisitLambdaExpression(LambdaExpression lambdaExpression, object data)
{
return null;
@ -357,7 +381,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -357,7 +381,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
return resolver.ResolveMember(type, memberReferenceExpression.MemberName,
memberReferenceExpression.TypeArguments,
memberReferenceExpression.Parent is InvocationExpression,
typeRR == null /* allow extension methods only for non-static method calls */);
typeRR == null, // allow extension methods only for non-static method calls
targetRR is BaseResolveResult ? (bool?)true : null // allow calling protected members using "base."
);
}
return null;
}

36
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

@ -705,6 +705,42 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -705,6 +705,42 @@ namespace ICSharpCode.SharpDevelop.Dom
}
#endregion
#region BaseResolveResult
/// <summary>
/// Is used for "base"/"MyBase" expression.
/// The completion list always shows protected members.
/// </summary>
public sealed class BaseResolveResult : ResolveResult
{
public BaseResolveResult(IClass callingClass, IMember callingMember, IReturnType baseClassType)
: base(callingClass, callingMember, baseClassType)
{
}
public override ArrayList GetCompletionData(IProjectContent projectContent)
{
if (this.ResolvedType == null) return null;
ArrayList res = new ArrayList();
foreach (IMember m in MemberLookupHelper.GetAccessibleMembers(this.ResolvedType, this.CallingClass, projectContent.Language, true)) {
if (projectContent.Language.ShowMember(m, false))
res.Add(m);
}
if (this.CallingClass != null) {
AddExtensions(projectContent.Language, res, this.CallingClass, this.ResolvedType);
}
return res;
}
public override ResolveResult Clone()
{
return new BaseResolveResult(this.CallingClass, this.CallingMember, this.ResolvedType);
}
}
#endregion
#region UnknownIdentifierResolveResult
public class UnknownIdentifierResolveResult : ResolveResult
{

Loading…
Cancel
Save