Browse Source

Fixed SD2-1487: protected static members not visible in code completion of derived class

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3719 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
c4cca90012
  1. 7
      src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs
  2. 5
      src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs
  3. 6
      src/Main/Base/Test/GenericResolverTests.cs
  4. 77
      src/Main/Base/Test/NRefactoryResolverTests.cs
  5. 58
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs
  6. 3
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IEntity.cs
  7. 24
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  8. 4
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryResolver.cs
  9. 7
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs
  10. 5
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs

7
src/AddIns/BackendBindings/Python/PythonBinding/Test/Utils/MockProjectContent.cs

@ -348,6 +348,11 @@ namespace PythonBinding.Tests.Utils @@ -348,6 +348,11 @@ namespace PythonBinding.Tests.Utils
if (ReferencedContentsChanged != null) {
ReferencedContentsChanged(this, e);
}
}
}
public bool InternalsVisibleTo(IProjectContent otherProjectContent)
{
throw new NotImplementedException();
}
}
}

5
src/AddIns/Misc/UnitTesting/Test/Utils/MockProjectContent.cs

@ -175,5 +175,10 @@ namespace UnitTesting.Tests.Utils @@ -175,5 +175,10 @@ namespace UnitTesting.Tests.Utils
{
throw new NotImplementedException();
}
public bool InternalsVisibleTo(IProjectContent otherProjectContent)
{
throw new NotImplementedException();
}
}
}

6
src/Main/Base/Test/GenericResolverTests.cs

@ -408,13 +408,13 @@ class Program { @@ -408,13 +408,13 @@ class Program {
d.T<char, int>('a', 1);
d.T<int, char>('a', 2);
}
protected virtual void T<A, B>(A a, B b) {
public virtual void T<A, B>(A a, B b) {
}
protected virtual void T<X, Y>(Y a, X b) {
public virtual void T<X, Y>(Y a, X b) {
}
}
class D : Program {
protected override void T<X, Y>(X a, Y b) {
public override void T<X, Y>(X a, Y b) {
// overrides T<A,B> - type arguments are identified by position
}
}";

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

@ -1395,6 +1395,7 @@ class Method { } @@ -1395,6 +1395,7 @@ class Method { }
bool MemberExists(ArrayList members, string name)
{
Assert.IsNotNull(members);
foreach (object o in members) {
IMember m = o as IMember;
if (m != null && m.Name == name) return true;
@ -2671,5 +2672,81 @@ class Flags { @@ -2671,5 +2672,81 @@ class Flags {
IReturnType rt = result.ResolvedClass.Attributes[0].AttributeType;
Assert.AreEqual("System.FlagsAttribute", rt.FullyQualifiedName);
}
[Test]
public void SD2_1487a()
{
string program = @"using System;
class C2 : C1 {
public static void M() {
}
}
class C1 {
protected static int Field;
}";
MemberResolveResult mrr;
mrr = Resolve<MemberResolveResult>(program, "Field", 4, 1, ExpressionContext.Default);
Assert.AreEqual("C1.Field", mrr.ResolvedMember.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "C1.Field", 4, 1, ExpressionContext.Default);
Assert.AreEqual("C1.Field", mrr.ResolvedMember.FullyQualifiedName);
mrr = Resolve<MemberResolveResult>(program, "C2.Field", 4, 1, ExpressionContext.Default);
Assert.AreEqual("C1.Field", mrr.ResolvedMember.FullyQualifiedName);
}
[Test]
public void SD2_1487b()
{
string program = @"using System;
class C2 : C1 {
public static void M() {
}
}
class C1 {
protected static int Field;
}";
ArrayList arr = CtrlSpaceResolveCSharp(program, 4, ExpressionContext.Default);
Assert.IsTrue(MemberExists(arr, "Field"));
ResolveResult rr = Resolve(program, "C1", 4);
arr = rr.GetCompletionData(rr.CallingClass.ProjectContent);
Assert.IsTrue(MemberExists(arr, "Field"));
rr = Resolve(program, "C2", 4);
arr = rr.GetCompletionData(rr.CallingClass.ProjectContent);
Assert.IsTrue(MemberExists(arr, "Field"));
}
[Test]
public void ProtectedPrivateVisibilityTest()
{
string program = @"using System;
class B : A {
void M(C c) {
}
private int P2;
protected int Y;
}
class A {
private int P1;
protected int X;
}
class C : B {
private int P3;
protected int Z;
}";
LocalResolveResult rr = Resolve<LocalResolveResult>(program, "c", 4);
ArrayList arr = rr.GetCompletionData(lastPC);
Assert.IsFalse(MemberExists(arr, "P1"));
Assert.IsTrue(MemberExists(arr, "P2"));
Assert.IsFalse(MemberExists(arr, "P3"));
Assert.IsTrue(MemberExists(arr, "X"));
Assert.IsTrue(MemberExists(arr, "Y"));
Assert.IsFalse(MemberExists(arr, "Z"));
}
}
}

58
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractEntity.cs

@ -258,12 +258,14 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -258,12 +258,14 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
[Obsolete("This property does not do what one would expect - it merely checks if protected+internal are set, it is not the equivalent of AssemblyAndFamily in Reflection!")]
public bool IsProtectedAndInternal {
get {
return (modifiers & (ModifierEnum.Internal | ModifierEnum.Protected)) == (ModifierEnum.Internal | ModifierEnum.Protected);
}
}
[Obsolete("This property does not do what one would expect - it merely checks if one of protected+internal is set, it is not the equivalent of AssemblyOrFamily in Reflection!")]
public bool IsProtectedOrInternal {
get {
return IsProtected || IsInternal;
@ -298,44 +300,32 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -298,44 +300,32 @@ namespace ICSharpCode.SharpDevelop.Dom
}
#endregion
bool IsInnerClass(IClass c, IClass possibleInnerClass)
public bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass)
{
foreach (IClass inner in c.InnerClasses) {
if (inner.FullyQualifiedName == possibleInnerClass.FullyQualifiedName) {
return true;
}
if (IsInnerClass(inner, possibleInnerClass)) {
return true;
}
}
return false;
}
// TODO: check inner classes for protected members too.
public bool IsAccessible(IClass callingClass, bool isClassInInheritanceTree)
{
if (IsInternal) {
return true;
}
if (IsPublic) {
return true;
} else if (IsInternal) {
return callingClass != null && this.DeclaringType.ProjectContent.InternalsVisibleTo(callingClass.ProjectContent);
}
// protected or private:
// search in callingClass and, if callingClass is a nested class, in its outer classes
while (callingClass != null) {
if (IsProtected) {
if (!isAccessThoughReferenceOfCurrentClass && !IsStatic)
return false;
return callingClass.IsTypeInInheritanceTree(this.DeclaringType);
} else {
// private
if (DeclaringType.FullyQualifiedName == callingClass.FullyQualifiedName
&& DeclaringType.TypeParameters.Count == callingClass.TypeParameters.Count)
{
return true;
}
}
callingClass = callingClass.DeclaringType;
}
if (isClassInInheritanceTree && IsProtected) {
return true;
}
return callingClass != null && (DeclaringType.FullyQualifiedName == callingClass.FullyQualifiedName || IsInnerClass(DeclaringType, callingClass));
}
public bool MustBeShown(IClass callingClass, bool showStatic, bool isClassInInheritanceTree)
{
if (DeclaringType.ClassType == ClassType.Enum) {
return true;
}
if (!showStatic && IsStatic || (showStatic && !(IsStatic || IsConst))) { // const is automatically static
return false;
}
return IsAccessible(callingClass, isClassInInheritanceTree);
return false;
}
public virtual int CompareTo(IEntity value)

3
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IEntity.cs

@ -130,7 +130,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -130,7 +130,6 @@ namespace ICSharpCode.SharpDevelop.Dom
set;
}
bool IsAccessible(IClass callingClass, bool isClassInInheritanceTree);
//bool MustBeShown(IClass callingClass, bool showStatic, bool isClassInInheritanceTree);
bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass);
}
}

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

@ -35,16 +35,16 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -35,16 +35,16 @@ namespace ICSharpCode.SharpDevelop.Dom
public static List<IList<IMember>> LookupMember(
IReturnType type, string name, IClass callingClass,
LanguageProperties language, bool isInvocation, bool? isClassInInheritanceTree)
LanguageProperties language, bool isInvocation, bool? isAccessThoughReferenceOfCurrentClass)
{
if (language == null)
throw new ArgumentNullException("language");
if (isClassInInheritanceTree == null) {
isClassInInheritanceTree = false;
if (isAccessThoughReferenceOfCurrentClass == null) {
isAccessThoughReferenceOfCurrentClass = false;
IClass underlyingClass = type.GetUnderlyingClass();
if (underlyingClass != null)
isClassInInheritanceTree = underlyingClass.IsTypeInInheritanceTree(callingClass);
isAccessThoughReferenceOfCurrentClass = underlyingClass.IsTypeInInheritanceTree(callingClass);
}
IEnumerable<IMember> members;
@ -54,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -54,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Dom
members = GetAllMembers(type).Where(m => language.NameComparer.Equals(m.Name, name));
}
return LookupMember(members, callingClass, (bool)isClassInInheritanceTree, isInvocation);
return LookupMember(members, callingClass, (bool)isAccessThoughReferenceOfCurrentClass, isInvocation);
}
class SignatureComparer : IEqualityComparer<IMethod>
@ -120,14 +120,14 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -120,14 +120,14 @@ namespace ICSharpCode.SharpDevelop.Dom
public static List<IList<IMember>> LookupMember(
IEnumerable<IMember> possibleMembers, IClass callingClass,
bool isClassInInheritanceTree, bool isInvocation)
bool isAccessThoughReferenceOfCurrentClass, bool isInvocation)
{
// Console.WriteLine("Possible members:");
// foreach (IMember m in possibleMembers) {
// Console.WriteLine(" " + m.DotNetName);
// }
IEnumerable<IMember> accessibleMembers = possibleMembers.Where(member => member.IsAccessible(callingClass, isClassInInheritanceTree));
IEnumerable<IMember> accessibleMembers = possibleMembers.Where(member => member.IsAccessible(callingClass, isAccessThoughReferenceOfCurrentClass));
if (isInvocation) {
accessibleMembers = accessibleMembers.Where(IsInvocable);
}
@ -202,24 +202,24 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -202,24 +202,24 @@ namespace ICSharpCode.SharpDevelop.Dom
/// </summary>
public static List<IMember> GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language)
{
bool isClassInInheritanceTree = false;
bool isAccessThoughReferenceOfCurrentClass = false;
IClass underlyingClass = rt.GetUnderlyingClass();
if (underlyingClass != null)
isClassInInheritanceTree = underlyingClass.IsTypeInInheritanceTree(callingClass);
return GetAccessibleMembers(rt, callingClass, language, isClassInInheritanceTree);
isAccessThoughReferenceOfCurrentClass = underlyingClass.IsTypeInInheritanceTree(callingClass);
return GetAccessibleMembers(rt, callingClass, language, isAccessThoughReferenceOfCurrentClass);
}
/// <summary>
/// Gets all accessible members, including indexers and constructors.
/// </summary>
public static List<IMember> GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language, bool isClassInInheritanceTree)
public static List<IMember> GetAccessibleMembers(IReturnType rt, IClass callingClass, LanguageProperties language, bool isAccessThoughReferenceOfCurrentClass)
{
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).OrderBy(g2=>g2.Key)) {
foreach (var group in LookupMember(g, callingClass, isClassInInheritanceTree, false)) {
foreach (var group in LookupMember(g, callingClass, isAccessThoughReferenceOfCurrentClass, false)) {
result.AddRange(group);
}
}

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

@ -640,9 +640,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -640,9 +640,9 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
#region ResolveMember
internal ResolveResult ResolveMember(IReturnType declaringType, string memberName,
List<TypeReference> typeArguments, bool isInvocation,
bool allowExtensionMethods, bool? isClassInInheritanceTree)
bool allowExtensionMethods, bool? isAccessThoughReferenceOfCurrentClass)
{
List<IList<IMember>> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation, isClassInInheritanceTree);
List<IList<IMember>> members = MemberLookupHelper.LookupMember(declaringType, memberName, callingClass, languageProperties, isInvocation, isAccessThoughReferenceOfCurrentClass);
List<IReturnType> typeArgs = null;
if (members != null && typeArguments != null && typeArguments.Count != 0) {
typeArgs = typeArguments.ConvertAll(r => TypeVisitor.CreateReturnType(r, this));

7
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/DefaultProjectContent.cs

@ -579,7 +579,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -579,7 +579,7 @@ namespace ICSharpCode.SharpDevelop.Dom
// check the outermost class (which is either public or internal)
while (c.DeclaringType != null)
c = c.DeclaringType;
return c.IsPublic || c.ProjectContent == this;
return c.IsPublic || c.ProjectContent.InternalsVisibleTo(this);
}
public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, GetClassOptions options)
@ -967,6 +967,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -967,6 +967,11 @@ namespace ICSharpCode.SharpDevelop.Dom
}
}
public bool InternalsVisibleTo(IProjectContent otherProjectContent)
{
return this == otherProjectContent;
}
public static readonly IProjectContent DummyProjectContent = new DummyContent();
private class DummyContent : DefaultProjectContent

5
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ProjectContent/IProjectContent.cs

@ -113,6 +113,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -113,6 +113,11 @@ namespace ICSharpCode.SharpDevelop.Dom
/// </summary>
/// <param name="entity">The entity to get the position from.</param>
FilePosition GetPosition(IEntity entity);
/// <summary>
/// Gets whether internals in the project content are visible to the other project content.
/// </summary>
bool InternalsVisibleTo(IProjectContent otherProjectContent);
}
[Flags]

Loading…
Cancel
Save