Browse Source

Fixed various resolver bugs.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
4d4f1f42b7
  1. 9
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  2. 2
      ICSharpCode.NRefactory.CSharp/Resolver/Log.cs
  3. 2
      ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs
  4. 16
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  5. 12
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  6. 52
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs
  7. 6
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  8. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  9. 34
      ICSharpCode.NRefactory/Semantics/ThisResolveResult.cs

9
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -1830,7 +1830,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
ITypeDefinition t = CurrentTypeDefinition; ITypeDefinition t = CurrentTypeDefinition;
if (t != null) { if (t != null) {
return new ResolveResult(t); if (t.TypeParameterCount != 0) {
// Self-parameterize the type
return new ThisResolveResult(new ParameterizedType(t, t.TypeParameters));
} else {
return new ThisResolveResult(t);
}
} }
return ErrorResult; return ErrorResult;
} }
@ -1844,7 +1849,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (t != null) { if (t != null) {
foreach (IType baseType in t.DirectBaseTypes) { foreach (IType baseType in t.DirectBaseTypes) {
if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) { if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) {
return new ResolveResult(baseType); return new ThisResolveResult(baseType);
} }
} }
} }

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

@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary> /// </summary>
static class Log static class Log
{ {
const bool logEnabled = true; const bool logEnabled = false;
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string text) internal static void WriteLine(string text)

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

@ -236,7 +236,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter;
bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult.Type); bool allowProtectedAccess = (targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type));
Predicate<ITypeDefinition> nestedTypeFilter = delegate(ITypeDefinition entity) { Predicate<ITypeDefinition> nestedTypeFilter = delegate(ITypeDefinition entity) {
return entity.Name == name && IsAccessible(entity, allowProtectedAccess); return entity.Name == name && IsAccessible(entity, allowProtectedAccess);
}; };

16
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -743,6 +743,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember; IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember;
if (pm == null && resolver.CurrentTypeDefinition != null) {
// Also consider delegate parameters:
pm = resolver.CurrentTypeDefinition.GetDelegateInvokeMethod();
// pm will be null if the current type isn't a delegate
}
if (pm != null) { if (pm != null) {
foreach (IParameter p in pm.Parameters) { foreach (IParameter p in pm.Parameters) {
if (p.Name == name) { if (p.Name == name) {
@ -750,6 +755,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} }
} }
} }
return errorResult; return errorResult;
} else { } else {
return null; return null;
@ -1653,7 +1659,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
AstNodeCollection<ParameterDeclaration> parameterDeclarations, AstNodeCollection<ParameterDeclaration> parameterDeclarations,
AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync) AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync)
{ {
List<IParameter> parameters = new List<IParameter>(); List<IParameter> parameters = (hasParameterList || parameterDeclarations.Any()) ? new List<IParameter>() : null;
resolver.PushBlock(); resolver.PushBlock();
bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression; bool oldIsWithinLambdaExpression = resolver.IsWithinLambdaExpression;
resolver.IsWithinLambdaExpression = true; resolver.IsWithinLambdaExpression = true;
@ -3019,6 +3025,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (!resolverEnabled) if (!resolverEnabled)
return null; return null;
KnownTypeCode typeCode = TypeSystemConvertVisitor.GetTypeCodeForPrimitiveType(primitiveType.Keyword); KnownTypeCode typeCode = TypeSystemConvertVisitor.GetTypeCodeForPrimitiveType(primitiveType.Keyword);
if (typeCode == KnownTypeCode.None && primitiveType.Parent is Constraint && primitiveType.Role == Constraint.BaseTypeRole) {
switch (primitiveType.Keyword) {
case "class":
case "struct":
case "new":
return voidResult;
}
}
IType type = resolver.Compilation.FindType(typeCode); IType type = resolver.Compilation.FindType(typeCode);
return new TypeResolveResult(type); return new TypeResolveResult(type);
} }

12
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

@ -380,6 +380,18 @@ class TestClass {
Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", crr.Type.ReflectionName); Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", crr.Type.ReflectionName);
} }
[Test]
public void AnonymousMethodWithoutParameterList()
{
string program = @"using System;
class TestClass {
event EventHandler Ev = $delegate {}$;
}";
var rr = Resolve<LambdaResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.IsFalse(rr.HasParameterList);
}
/* TODO write test for this /* TODO write test for this
class A class A
{ {

52
ICSharpCode.NRefactory.Tests/CSharp/Resolver/MemberLookupTests.cs

@ -209,5 +209,57 @@ public class Test {
var mrr = Resolve<MemberResolveResult>(program); var mrr = Resolve<MemberResolveResult>(program);
Assert.AreEqual("Foo`1+TestFoo[[Test]]", mrr.Type.ReflectionName); Assert.AreEqual("Foo`1+TestFoo[[Test]]", mrr.Type.ReflectionName);
} }
[Test]
public void ProtectedBaseMethodCall()
{
string program = @"using System;
public class Base {
protected virtual void M() {}
}
public class Test : Base {
protected override void M() {
$base.M()$;
}
}";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual("Base.M", rr.Member.FullName);
}
[Test]
public void ProtectedBaseFieldAccess()
{
string program = @"using System;
public class Base {
protected int Field;
}
public class Test : Base {
public new int Field;
protected override void M() {
$base.Field$ = 1;
}
}";
var rr = Resolve<MemberResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual("Base.Field", rr.Member.FullName);
}
[Test]
public void ThisHasSameTypeAsFieldInGenericClass()
{
string program = @"using System;
public struct C<T> {
public C(C<T> other) {
$M(this, other)$;
}
static void M<T>(T a, T b) {}
}
";
var rr = Resolve<CSharpInvocationResolveResult>(program);
Assert.IsFalse(rr.IsError);
Assert.AreEqual("C`1[[`0]]", rr.Arguments[0].Type.ReflectionName);
Assert.AreEqual("C`1[[`0]]", rr.Arguments[1].Type.ReflectionName);
}
} }
} }

6
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -190,7 +190,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{ {
ResolveResult rr = Resolve(code); ResolveResult rr = Resolve(code);
Assert.IsNotNull(rr); Assert.IsNotNull(rr);
Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name); if (typeof(T) == typeof(LambdaResolveResult)) {
Assert.IsTrue(rr is LambdaResolveResult, "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name);
} else {
Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name);
}
return (T)rr; return (T)rr;
} }

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -94,6 +94,7 @@
<Compile Include="Semantics\NamespaceResolveResult.cs" /> <Compile Include="Semantics\NamespaceResolveResult.cs" />
<Compile Include="Semantics\OperatorResolveResult.cs" /> <Compile Include="Semantics\OperatorResolveResult.cs" />
<Compile Include="Semantics\ResolveResult.cs" /> <Compile Include="Semantics\ResolveResult.cs" />
<Compile Include="Semantics\ThisResolveResult.cs" />
<Compile Include="Semantics\TypeOfResolveResult.cs" /> <Compile Include="Semantics\TypeOfResolveResult.cs" />
<Compile Include="Semantics\TypeResolveResult.cs" /> <Compile Include="Semantics\TypeResolveResult.cs" />
<Compile Include="Semantics\UnknownMemberResolveResult.cs" /> <Compile Include="Semantics\UnknownMemberResolveResult.cs" />

34
ICSharpCode.NRefactory/Semantics/ThisResolveResult.cs

@ -0,0 +1,34 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.Semantics
{
/// <summary>
/// Represents the 'this' reference.
/// Also used for the 'base' reference.
/// </summary>
public class ThisResolveResult : ResolveResult
{
public ThisResolveResult(IType type) : base(type)
{
}
}
}
Loading…
Cancel
Save