Browse Source

Use explicit interface implementation in ResolveVisitor to make it clear what the public API is supposed to be.

Added support for QueryJoinClause and QueryOrderClause to the resolver.
newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
5b17740bea
  1. 47
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs
  2. 4
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs
  3. 153
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs
  4. 4
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  5. 6
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  6. 5
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  7. 4
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs
  8. 6
      ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs
  9. 57
      ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs
  10. 2
      ICSharpCode.NRefactory/CSharp/Resolver/Log.cs
  11. 415
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  12. 5
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs
  13. 11
      ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

47
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs

@ -313,5 +313,52 @@ select new { c.Name, o.OrderID, o.Total }",
} }
}}); }});
} }
[Test]
public void QueryWithJoin()
{
ParseUtilCSharp.AssertExpression(
"from a in b join c in d on e equals f select g",
new QueryExpression {
Clauses = {
new QueryFromClause {
Identifier = "a",
Expression = new IdentifierExpression("b")
},
new QueryJoinClause {
JoinIdentifier = "c",
InExpression = new IdentifierExpression("d"),
OnExpression = new IdentifierExpression("e"),
EqualsExpression = new IdentifierExpression("f")
},
new QuerySelectClause {
Expression = new IdentifierExpression("g")
}
}});
}
[Test]
public void QueryWithGroupJoin()
{
ParseUtilCSharp.AssertExpression(
"from a in b join c in d on e equals f into g select h",
new QueryExpression {
Clauses = {
new QueryFromClause {
Identifier = "a",
Expression = new IdentifierExpression("b")
},
new QueryJoinClause {
JoinIdentifier = "c",
InExpression = new IdentifierExpression("d"),
OnExpression = new IdentifierExpression("e"),
EqualsExpression = new IdentifierExpression("f"),
IntoIdentifier = "g"
},
new QuerySelectClause {
Expression = new IdentifierExpression("h")
}
}});
}
} }
} }

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

@ -216,10 +216,10 @@ class Program {
static void T(ref int y) {} static void T(ref int y) {}
}"; }";
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program, "T(a)"); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program.Replace("T(a)", "$T(a)$"));
Assert.IsFalse(mrr.Member.Parameters[0].IsRef); Assert.IsFalse(mrr.Member.Parameters[0].IsRef);
mrr = Resolve<InvocationResolveResult>(program, "T(ref a)"); mrr = Resolve<InvocationResolveResult>(program.Replace("T(ref a)", "$T(ref a)$"));
Assert.IsTrue(mrr.Member.Parameters[0].IsRef); Assert.IsTrue(mrr.Member.Parameters[0].IsRef);
} }

153
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public class LinqTests : ResolverTestBase public class LinqTests : ResolverTestBase
{ {
[Test] [Test]
public void SimpleLinqTest() public void SimpleLinq()
{ {
string program = @"using System; using System.Linq; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
@ -51,7 +51,7 @@ class TestClass {
} }
[Test] [Test]
public void LinqGroupTest() public void Group()
{ {
string program = @"using System; using System.Linq; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
@ -71,7 +71,7 @@ class TestClass {
} }
[Test] [Test]
public void LinqQueryableGroupTest() public void QueryableGroup()
{ {
string program = @"using System; using System.Linq; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
@ -91,7 +91,7 @@ class TestClass {
} }
[Test] [Test]
public void ParenthesizedLinqTest() public void Parenthesized()
{ {
string program = @"using System; using System.Linq; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
@ -100,13 +100,14 @@ class TestClass {
} }
} }
"; ";
ResolveResult rr = Resolve<ResolveResult>(program); var rr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("System.Linq.Enumerable.Select", rr.Member.FullName);
Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName); Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName);
Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName); Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName);
} }
[Test] [Test]
public void LinqSelectReturnTypeTest() public void SelectReturnType()
{ {
string program = @"using System; string program = @"using System;
class TestClass { static void M() { class TestClass { static void M() {
@ -115,12 +116,13 @@ class TestClass { static void M() {
class XYZ { class XYZ {
public int Select<U>(Func<string, U> f) { return 42; } public int Select<U>(Func<string, U> f) { return 42; }
}"; }";
ResolveResult rr = Resolve<ResolveResult>(program); var rr = Resolve<InvocationResolveResult>(program);
Assert.AreEqual("XYZ.Select", rr.Member.FullName);
Assert.AreEqual("System.Int32", rr.Type.FullName); Assert.AreEqual("System.Int32", rr.Type.FullName);
} }
[Test] [Test]
public void LinqQueryContinuationTest() public void Continuation()
{ {
string program = @"using System; using System.Linq; string program = @"using System; using System.Linq;
class TestClass { class TestClass {
@ -147,5 +149,140 @@ class TestClass {
lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString")); lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString"));
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName); Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName);
} }
[Test]
public void OrderingWithSelectCall()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
orderby x.Length
select x + x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void OrderingWithoutSelectCall()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
orderby x.Length
select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Linq.IOrderedEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void OrderingWithSelectCallDueToSecondRangeVariable1()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
from y in input
orderby x.Length
select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void OrderingWithSelectCallDueToSecondRangeVariable2()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
join y in input on x equals y
orderby x.Length
select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void OrderingWithSelectCallDueToSecondRangeVariable3()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
join y in input on x equals y into g
orderby x.Length
select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void OrderingWithSelectCallDueToSecondRangeVariable4()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input
let y = x
orderby x.Length
select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test]
public void DegenerateQuery()
{
string program = @"using System; using System.Linq;
class TestClass {
void Test(string[] input) {
$var$ r = from x in input select x;
}
}
";
TypeResolveResult rr = Resolve<TypeResolveResult>(program);
Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName);
}
[Test, Ignore("lots of bugs here.. not only parser bugs")]
public void GroupJoinWithCustomMethod()
{
string program = @"using System;
class TestClass { static void M(long [] args) {
var q = (from a in new XYZ() join b in args on a equals b into g select g);
}}
class XYZ {
public XYZ GroupJoin<T, K, R>(IEnumerable<T> f, Func<string, K> key1, Func<T, K> key2, Func<string, decimal, R> s) { return this; }
public int Select<U>(Func<string, U> f) { return 42; }
}";
var local = Resolve<LocalResolveResult>(program.Replace("into g", "into $g$"));
Assert.AreEqual("System.Decimal", local.Type.FullName);
local = Resolve<LocalResolveResult>(program.Replace("select g", "select $g$"));
Assert.AreEqual("System.Decimal", local.Type.FullName);
var trr = Resolve<TypeResolveResult>(program.Replace("var", "$var$"));
Assert.AreEqual("XYZ", trr.Type.FullName); // because 'Select' is done as part of GroupJoin()
}
} }
} }

4
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -391,11 +391,11 @@ class TestClass {
COL.ArrayList ff; COL.ArrayList ff;
} }
"; ";
TypeResolveResult type = Resolve<TypeResolveResult>(program, "COL.ArrayList"); TypeResolveResult type = Resolve<TypeResolveResult>(program.Replace("COL.ArrayList", "$COL.ArrayList$"));
Assert.IsNotNull(type, "COL.ArrayList should resolve to a type"); Assert.IsNotNull(type, "COL.ArrayList should resolve to a type");
Assert.AreEqual("System.Collections.ArrayList", type.Type.FullName, "TypeResolveResult"); Assert.AreEqual("System.Collections.ArrayList", type.Type.FullName, "TypeResolveResult");
MemberResolveResult member = Resolve<MemberResolveResult>(program, "ff"); MemberResolveResult member = Resolve<MemberResolveResult>(program.Replace("ff", "$ff$"));
Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved"); Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved");
} }

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

@ -132,13 +132,13 @@ class C : B {
{} {}
} }
"; ";
InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program, "base(b)"); InvocationResolveResult mrr = Resolve<InvocationResolveResult>(program.Replace("base(b)", "$base(b)$"));
Assert.AreEqual("A..ctor", mrr.Member.FullName); Assert.AreEqual("A..ctor", mrr.Member.FullName);
mrr = Resolve<InvocationResolveResult>(program, "base(c)"); mrr = Resolve<InvocationResolveResult>(program.Replace("base(c)", "$base(c)$"));
Assert.AreEqual("B..ctor", mrr.Member.FullName); Assert.AreEqual("B..ctor", mrr.Member.FullName);
mrr = Resolve<InvocationResolveResult>(program, "this(0)"); mrr = Resolve<InvocationResolveResult>(program.Replace("this(0)", "$this(0)$"));
Assert.AreEqual("C..ctor", mrr.Member.FullName); Assert.AreEqual("C..ctor", mrr.Member.FullName);
} }

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

@ -226,11 +226,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return (T)rr; return (T)rr;
} }
protected T Resolve<T>(string code, string exprToResolve) where T : ResolveResult
{
return Resolve<T>(code.Replace(exprToResolve, "$" + exprToResolve + "$"));
}
sealed class FindNodeVisitor : DepthFirstAstVisitor<object, object> sealed class FindNodeVisitor : DepthFirstAstVisitor<object, object>
{ {
readonly AstLocation start; readonly AstLocation start;

4
ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs

@ -312,6 +312,10 @@ namespace ICSharpCode.NRefactory.CSharp
} }
} }
public Identifier IntoIdentifierToken {
get { return GetChildByRole(IntoIdentifierRole); }
}
public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data) public override S AcceptVisitor<T, S> (IAstVisitor<T, S> visitor, T data)
{ {
return visitor.VisitQueryJoinClause (this, data); return visitor.VisitQueryJoinClause (this, data);

6
ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs

@ -2889,7 +2889,7 @@ namespace ICSharpCode.NRefactory.CSharp
var location = LocationsBag.GetLocations (join); var location = LocationsBag.GetLocations (join);
result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole);
result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), QueryJoinClause.JoinIdentifierRole);
if (location != null) if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole);
@ -2913,7 +2913,7 @@ namespace ICSharpCode.NRefactory.CSharp
var location = LocationsBag.GetLocations (join); var location = LocationsBag.GetLocations (join);
result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole);
result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), QueryJoinClause.JoinIdentifierRole);
if (location != null) if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole);
@ -2932,7 +2932,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (location != null) if (location != null)
result.AddChild (new CSharpTokenNode (Convert (location[3]), "into".Length), QueryJoinClause.IntoKeywordRole); result.AddChild (new CSharpTokenNode (Convert (location[3]), "into".Length), QueryJoinClause.IntoKeywordRole);
result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), QueryJoinClause.IntoIdentifierRole);
return result; return result;
} }

57
ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -161,13 +161,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// (anything is better than displaying a question mark) // (anything is better than displaying a question mark)
KnownTypeReference knownType = typeRef as KnownTypeReference; KnownTypeReference knownType = typeRef as KnownTypeReference;
if (knownType != null) { if (knownType != null) {
PrimitiveType primitiveType; string keyword = ReflectionHelper.GetCSharpNameByTypeCode(knownType.TypeCode);
if (knownType.TypeCode == TypeCode.Empty) if (keyword != null)
primitiveType = new PrimitiveType("void"); return new PrimitiveType(keyword);
else
primitiveType = ConvertPrimitiveType(knownType.TypeCode);
if (primitiveType != null)
return primitiveType;
} }
SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference; SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference;
if (str != null) { if (str != null) {
@ -187,50 +183,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
return new SimpleType("?"); return new SimpleType("?");
} }
PrimitiveType ConvertPrimitiveType(TypeCode typeCode)
{
switch (typeCode) {
case TypeCode.Object:
return new PrimitiveType("object");
case TypeCode.Boolean:
return new PrimitiveType("bool");
case TypeCode.Char:
return new PrimitiveType("char");
case TypeCode.SByte:
return new PrimitiveType("sbyte");
case TypeCode.Byte:
return new PrimitiveType("byte");
case TypeCode.Int16:
return new PrimitiveType("short");
case TypeCode.UInt16:
return new PrimitiveType("ushort");
case TypeCode.Int32:
return new PrimitiveType("int");
case TypeCode.UInt32:
return new PrimitiveType("uint");
case TypeCode.Int64:
return new PrimitiveType("long");
case TypeCode.UInt64:
return new PrimitiveType("ulong");
case TypeCode.Single:
return new PrimitiveType("float");
case TypeCode.Double:
return new PrimitiveType("double");
case TypeCode.Decimal:
return new PrimitiveType("decimal");
case TypeCode.String:
return new PrimitiveType("string");
default:
return null;
}
}
AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments) AstType ConvertTypeHelper(ITypeDefinition typeDef, IList<IType> typeArguments)
{ {
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
PrimitiveType primitiveType = ConvertPrimitiveType(ReflectionHelper.GetTypeCode(typeDef)); TypeCode typeCode = ReflectionHelper.GetTypeCode(typeDef);
if (primitiveType != null) if (typeCode != TypeCode.Empty) {
return primitiveType; string keyword = ReflectionHelper.GetCSharpNameByTypeCode(typeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
// There is no type code for System.Void // There is no type code for System.Void
if (typeDef.Kind == TypeKind.Void) if (typeDef.Kind == TypeKind.Void)
return new PrimitiveType("void"); return new PrimitiveType("void");

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 = false; const bool logEnabled = true;
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string text) internal static void WriteLine(string text)

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

File diff suppressed because it is too large Load Diff

5
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -150,5 +150,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
public string Name { public string Name {
get { return ReflectionHelper.GetShortNameByTypeCode(typeCode); } get { return ReflectionHelper.GetShortNameByTypeCode(typeCode); }
} }
public override string ToString()
{
return ReflectionHelper.GetCSharpNameByTypeCode(typeCode) ?? (this.Namespace + "." + this.Name);
}
} }
} }

11
ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -226,6 +226,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
"Single", "Double", "Decimal", "DateTime", null, "String" "Single", "Double", "Decimal", "DateTime", null, "String"
}; };
static readonly string[] csharpTypeNamesByTypeCode = {
"void", "object", null, "bool", "char",
"sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong",
"float", "double", "decimal", null, null, "string"
};
internal static int ByTypeCodeArraySize { internal static int ByTypeCodeArraySize {
get { return typeNamesByTypeCode.Length; } get { return typeNamesByTypeCode.Length; }
} }
@ -235,6 +241,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
return typeNamesByTypeCode[(int)typeCode]; return typeNamesByTypeCode[(int)typeCode];
} }
internal static string GetCSharpNameByTypeCode(TypeCode typeCode)
{
return csharpTypeNamesByTypeCode[(int)typeCode];
}
/// <summary> /// <summary>
/// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches. /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches.
/// </summary> /// </summary>

Loading…
Cancel
Save