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 }", @@ -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 { @@ -216,10 +216,10 @@ class Program {
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);
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);
}

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

@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public class LinqTests : ResolverTestBase
{
[Test]
public void SimpleLinqTest()
public void SimpleLinq()
{
string program = @"using System; using System.Linq;
class TestClass {
@ -51,7 +51,7 @@ class TestClass { @@ -51,7 +51,7 @@ class TestClass {
}
[Test]
public void LinqGroupTest()
public void Group()
{
string program = @"using System; using System.Linq;
class TestClass {
@ -71,7 +71,7 @@ class TestClass { @@ -71,7 +71,7 @@ class TestClass {
}
[Test]
public void LinqQueryableGroupTest()
public void QueryableGroup()
{
string program = @"using System; using System.Linq;
class TestClass {
@ -91,7 +91,7 @@ class TestClass { @@ -91,7 +91,7 @@ class TestClass {
}
[Test]
public void ParenthesizedLinqTest()
public void Parenthesized()
{
string program = @"using System; using System.Linq;
class TestClass {
@ -100,13 +100,14 @@ 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.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName);
}
[Test]
public void LinqSelectReturnTypeTest()
public void SelectReturnType()
{
string program = @"using System;
class TestClass { static void M() {
@ -115,12 +116,13 @@ class TestClass { static void M() { @@ -115,12 +116,13 @@ class TestClass { static void M() {
class XYZ {
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);
}
[Test]
public void LinqQueryContinuationTest()
public void Continuation()
{
string program = @"using System; using System.Linq;
class TestClass {
@ -147,5 +149,140 @@ class TestClass { @@ -147,5 +149,140 @@ class TestClass {
lrr = Resolve<LocalResolveResult>(program.Replace("r.ToString", "$r$.ToString"));
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 { @@ -391,11 +391,11 @@ class TestClass {
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.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");
}

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

@ -132,13 +132,13 @@ class C : B { @@ -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);
mrr = Resolve<InvocationResolveResult>(program, "base(c)");
mrr = Resolve<InvocationResolveResult>(program.Replace("base(c)", "$base(c)$"));
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);
}

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

@ -226,11 +226,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -226,11 +226,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
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>
{
readonly AstLocation start;

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

@ -312,6 +312,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -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)
{
return visitor.VisitQueryJoinClause (this, data);

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

@ -2889,7 +2889,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2889,7 +2889,7 @@ namespace ICSharpCode.NRefactory.CSharp
var location = LocationsBag.GetLocations (join);
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)
result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole);
@ -2913,7 +2913,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2913,7 +2913,7 @@ namespace ICSharpCode.NRefactory.CSharp
var location = LocationsBag.GetLocations (join);
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)
result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole);
@ -2932,7 +2932,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2932,7 +2932,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (location != null)
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;
}

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

@ -161,13 +161,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -161,13 +161,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
// (anything is better than displaying a question mark)
KnownTypeReference knownType = typeRef as KnownTypeReference;
if (knownType != null) {
PrimitiveType primitiveType;
if (knownType.TypeCode == TypeCode.Empty)
primitiveType = new PrimitiveType("void");
else
primitiveType = ConvertPrimitiveType(knownType.TypeCode);
if (primitiveType != null)
return primitiveType;
string keyword = ReflectionHelper.GetCSharpNameByTypeCode(knownType.TypeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference;
if (str != null) {
@ -187,50 +183,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring @@ -187,50 +183,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
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)
{
Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount);
PrimitiveType primitiveType = ConvertPrimitiveType(ReflectionHelper.GetTypeCode(typeDef));
if (primitiveType != null)
return primitiveType;
TypeCode typeCode = ReflectionHelper.GetTypeCode(typeDef);
if (typeCode != TypeCode.Empty) {
string keyword = ReflectionHelper.GetCSharpNameByTypeCode(typeCode);
if (keyword != null)
return new PrimitiveType(keyword);
}
// There is no type code for System.Void
if (typeDef.Kind == TypeKind.Void)
return new PrimitiveType("void");

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

@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
static class Log
{
const bool logEnabled = false;
const bool logEnabled = true;
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
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 @@ -150,5 +150,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
public string Name {
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 @@ -226,6 +226,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
"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 {
get { return typeNamesByTypeCode.Length; }
}
@ -235,6 +241,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -235,6 +241,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
return typeNamesByTypeCode[(int)typeCode];
}
internal static string GetCSharpNameByTypeCode(TypeCode typeCode)
{
return csharpTypeNamesByTypeCode[(int)typeCode];
}
/// <summary>
/// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches.
/// </summary>

Loading…
Cancel
Save