diff --git a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs
index f6ad58747a..fa4932153e 100644
--- a/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs
+++ b/src/AddIns/BackendBindings/Python/PythonBinding/Project/Src/PythonAstWalker.cs
@@ -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
/// 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.
///
DomRegion GetBodyRegion(Node node)
@@ -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);
}
- ///
- /// Creates a return type from the current class and method name.
- /// If the method name is __init__ then this method returns null.
- ///
- IReturnType CreateReturnType(string methodName, IClass c)
- {
- if (methodName == "__init__") {
- return null;
- }
- return new DefaultReturnType(currentClass);
- }
-
///
/// 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
///
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));
}
///
diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
index 7c797f6960..0f896b8e57 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
@@ -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();
diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
index c16c3d2b15..3bc3853668 100644
--- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
+++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
@@ -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)
diff --git a/src/Main/Base/Test/NRefactoryResolverTests.cs b/src/Main/Base/Test/NRefactoryResolverTests.cs
index 4fda21c4e7..6b9266e8e8 100644
--- a/src/Main/Base/Test/NRefactoryResolverTests.cs
+++ b/src/Main/Base/Test/NRefactoryResolverTests.cs
@@ -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(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(program, "new B().GetRandomNumber(\"x\", this)", 3);
+ Assert.AreEqual("B.GetRandomNumber", result.ResolvedMember.FullyQualifiedName);
+ }
[Test]
public void MethodCallTest()
@@ -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(program, "mybase", 7);
+ result = ResolveVB(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 {
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 {
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 {
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 {
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)
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs
index 468ae6e10b..e41ca7415a 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Ambience.cs
@@ -125,6 +125,7 @@ namespace ICSharpCode.SharpDevelop.Dom
return conversionFlags;
}
set {
+ CheckThread();
conversionFlags = value;
}
}
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs
index e48ab4a864..fcf85879eb 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CSharp/CSharpAmbience.cs
@@ -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(' ');
}
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs
index f73434c4ac..13887dbef5 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/CecilReader.cs
@@ -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;
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs
index 886ef12c7f..43d8e21c5f 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractReturnType.cs
@@ -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;
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs
index 6da949b90a..6f2da88c64 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/CombinedReturnType.cs
@@ -11,7 +11,7 @@ using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Dom
{
///
- /// Combines multiple return types for use in contraints.
+ /// Combines multiple return types for use in constraints.
///
public sealed class CombinedReturnType : AbstractReturnType
{
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs
index 4c7a89096e..63fe46c47c 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultMethod.cs
@@ -165,7 +165,7 @@ namespace ICSharpCode.SharpDevelop.Dom
public virtual bool IsConstructor {
get {
- return ReturnType == null || Name == "#ctor";
+ return Name == "#ctor";
}
}
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs
index c6c821eca7..1b04b0699f 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/DefaultReturnType.cs
@@ -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)
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs
index 5518881812..b1a4935462 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/GetClassReturnType.cs
@@ -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);
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs
index 23aa551fd1..32376b8075 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ProxyReturnType.cs
@@ -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;
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs
index 2461d26f62..8c7d49d4a3 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/SearchClassReturnType.cs
@@ -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
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;
}
}
}
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
index 9f1ce73fe0..91649491fa 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
@@ -34,15 +34,17 @@ namespace ICSharpCode.SharpDevelop.Dom
public static List> 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 members;
if (language == LanguageProperties.VBNet && language.NameComparer.Equals(name, "New")) {
@@ -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
@@ -180,13 +182,20 @@ namespace ICSharpCode.SharpDevelop.Dom
///
public static List 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);
+ }
+
+ ///
+ /// Gets all accessible members, including indexers and constructors.
+ ///
+ public static List GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language, bool isClassInInheritanceTree)
+ {
+ if (language == null)
+ throw new ArgumentNullException("language");
List result = new List();
foreach (var g in GetAllMembers(rt).GroupBy(m => m.Name, language.NameComparer)) {
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
index 98a2fe1f28..05c682950f 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
@@ -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
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
#region ResolveMember
internal ResolveResult ResolveMember(IReturnType declaringType, string memberName,
List typeArguments, bool isInvocation,
- bool allowExtensionMethods)
+ bool allowExtensionMethods, bool? isClassInInheritanceTree)
{
- List> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation);
+ List> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation, isClassInInheritanceTree);
if (members != null && typeArguments != null && typeArguments.Count != 0) {
List typeArgs = typeArguments.ConvertAll(r => TypeVisitor.CreateReturnType(r, this));
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs
index 5f35747953..264e35d7ef 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs
@@ -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
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
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 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
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;
}
diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs
index dea3667dfc..f954f6a8f2 100644
--- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs
+++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs
@@ -705,6 +705,42 @@ namespace ICSharpCode.SharpDevelop.Dom
}
#endregion
+ #region BaseResolveResult
+ ///
+ /// Is used for "base"/"MyBase" expression.
+ /// The completion list always shows protected members.
+ ///
+ 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
{