Browse Source

Do not try to infer a type from the null literal.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
a6433d43f3
  1. 12
      ICSharpCode.NRefactory.CSharp/Resolver/Log.cs
  2. 39
      ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs
  3. 10
      ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs
  4. 18
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs
  5. 17
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

12
ICSharpCode.NRefactory.CSharp/Resolver/Log.cs

@ -40,19 +40,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -40,19 +40,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string text)
{
// Debug.WriteLine(text);
Debug.WriteLine(text);
}
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string format, params object[] args)
{
// Debug.WriteLine(format, args);
Debug.WriteLine(format, args);
}
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteCollection<T>(string text, IEnumerable<T> lines)
{
/* #if DEBUG
#if DEBUG
T[] arr = lines.ToArray();
if (arr.Length == 0) {
Debug.WriteLine(text + "<empty collection>");
@ -62,19 +62,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -62,19 +62,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Debug.WriteLine(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "<null>"));
}
}
#endif*/
#endif
}
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
public static void Indent()
{
// Debug.Indent();
Debug.Indent();
}
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
public static void Unindent()
{
// Debug.Unindent();
Debug.Unindent();
}
}
}

39
ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs

@ -86,28 +86,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -86,28 +86,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return false;
case Accessibility.Private:
// check for members of outer classes (private members of outer classes can be accessed)
var lookupTypeDefinition = currentTypeDefinition;
while (lookupTypeDefinition != null) {
if (entity.DeclaringTypeDefinition.Equals (lookupTypeDefinition))
for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) {
if (t.Equals(entity.DeclaringTypeDefinition))
return true;
lookupTypeDefinition = lookupTypeDefinition.DeclaringTypeDefinition;
}
return false;
case Accessibility.Public:
return true;
case Accessibility.Protected:
// For static members and type definitions, we do not require the qualifying reference
// to be derived from the current class (allowProtectedAccess).
return (allowProtectedAccess || entity.IsStatic || entity.EntityType == EntityType.TypeDefinition)
&& IsProtectedAccessible(entity.DeclaringTypeDefinition);
return IsProtectedAccessible(allowProtectedAccess, entity);
case Accessibility.Internal:
return IsInternalAccessible(entity.ParentAssembly);
case Accessibility.ProtectedOrInternal:
return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition))
|| IsInternalAccessible(entity.ParentAssembly);
return IsInternalAccessible(entity.ParentAssembly) || IsProtectedAccessible(allowProtectedAccess, entity);
case Accessibility.ProtectedAndInternal:
return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition))
&& IsInternalAccessible(entity.ParentAssembly);
return IsInternalAccessible(entity.ParentAssembly) && IsProtectedAccessible(allowProtectedAccess, entity);
default:
throw new Exception("Invalid value for Accessibility");
}
@ -118,13 +111,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -118,13 +111,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return assembly != null && currentAssembly != null && assembly.InternalsVisibleTo(currentAssembly);
}
bool IsProtectedAccessible(ITypeDefinition declaringType)
bool IsProtectedAccessible(bool allowProtectedAccess, IEntity entity)
{
if (declaringType.Equals (currentTypeDefinition))
return true;
// PERF: this might hurt performance as this method is called several times (once for each member)
// make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance
return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType);
// For static members and type definitions, we do not require the qualifying reference
// to be derived from the current class (allowProtectedAccess).
if (entity.IsStatic || entity.EntityType == EntityType.TypeDefinition)
allowProtectedAccess = true;
for (var t = currentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) {
if (t.Equals(entity.DeclaringTypeDefinition))
return true;
// PERF: this might hurt performance as this method is called several times (once for each member)
// make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance
if (allowProtectedAccess && currentTypeDefinition.IsDerivedFrom(entity.DeclaringTypeDefinition))
return true;
}
return false;
}
#endregion

10
ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs

@ -271,8 +271,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -271,8 +271,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
IType U = Ei.Type;
if (U != SpecialType.UnknownType) {
if (IsValidType(Ei.Type)) {
if (Ti is ByReferenceType) {
MakeExactInference(Ei.Type, Ti);
} else {
@ -282,6 +281,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -282,6 +281,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
static bool IsValidType(IType type)
{
return type.Kind != TypeKind.Unknown && type.Kind != TypeKind.Null;
}
bool PhaseTwo()
{
// C# 4.0 spec: §7.5.2.2 The second phase
@ -516,7 +520,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -516,7 +520,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return;
}
// Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T.
if (e.Type != SpecialType.UnknownType) {
if (IsValidType(e.Type)) {
MakeLowerBoundInference(e.Type, t);
}
}

18
ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs

@ -475,5 +475,23 @@ class A { @@ -475,5 +475,23 @@ class A {
Assert.IsFalse(rr.IsError);
Assert.AreEqual("ILeft.Method", rr.Member.FullName);
}
[Test]
public void AcceptVisitor()
{
string program = @"
interface IVisitor<in T, out S> { }
class Test : IVisitor<object, object> {
void M() {
$Accept(this, null)$;
}
S Accept<T, S>(IVisitor<T, S> v, T input) { }
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
var typeArguments = ((SpecializedMethod)rr.Member).TypeArguments;
Assert.AreEqual("System.Object", typeArguments[0].ReflectionName);
Assert.AreEqual("System.Object", typeArguments[1].ReflectionName);
}
}
}

17
ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs

@ -90,6 +90,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -90,6 +90,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
out success));
Assert.IsTrue(success);
}
[Test]
public void InferFromObjectAndFromNullLiteral()
{
// M<T>(T a, T b);
ITypeParameter tp = new DefaultTypeParameter(compilation, EntityType.Method, 0, "T");
// M(new object(), null);
bool success;
Assert.AreEqual(
new [] { compilation.FindType(KnownTypeCode.Object) },
ti.InferTypeArguments(new [] { tp },
new [] { new ResolveResult(compilation.FindType(KnownTypeCode.Object)), new ResolveResult(SpecialType.NullType) },
new [] { tp, tp },
out success));
Assert.IsTrue(success);
}
#endregion
#region Inference with Method Groups

Loading…
Cancel
Save