Browse Source

Adjust resolver to object initializer AST changes.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
a5c93a38e4
  1. 13
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs
  2. 4
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs
  3. 38
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs
  4. 8
      ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs
  5. 6
      ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs
  6. 16
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  7. 15
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs
  8. 14
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs
  9. 6
      ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs
  10. 54
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  11. 12
      ICSharpCode.NRefactory/CSharp/Resolver/Log.cs
  12. 132
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  13. 2
      ICSharpCode.NRefactory/Properties/AssemblyInfo.cs

13
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs

@ -121,5 +121,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -121,5 +121,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
}
}});
}
[Test]
public void AssignmentInArrayInitializer()
{
ParseUtilCSharp.AssertExpression(
"new [] { a = 10 }",
new ArrayCreateExpression {
Initializer = new ArrayInitializerExpression {
Elements = {
new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(10))
}
}});
}
}
}

4
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs

@ -105,7 +105,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -105,7 +105,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
{
ParseUtilCSharp.AssertExpression(
"a = b = c",
new AssignmentExpression("a", new AssignmentExpression("b", new IdentifierExpression("c"))));
new AssignmentExpression(
new IdentifierExpression("a"),
new AssignmentExpression(new IdentifierExpression("b"), new IdentifierExpression("c"))));
}
}
}

38
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs

@ -163,9 +163,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -163,9 +163,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
Type = new SimpleType("List", new PrimitiveType("int")),
Initializer = new ArrayInitializerExpression {
Elements = {
new PrimitiveExpression(0),
new PrimitiveExpression(1),
new PrimitiveExpression(2)
new ArrayInitializerExpression(new PrimitiveExpression(0)),
new ArrayInitializerExpression(new PrimitiveExpression(1)),
new ArrayInitializerExpression(new PrimitiveExpression(2))
}}});
}
@ -204,17 +204,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -204,17 +204,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
}",
new ObjectCreateExpression {
Type = new SimpleType("List", new SimpleType("Contact")),
Initializer = new ArrayInitializerExpression {
Elements = {
Initializer = new ArrayInitializerExpression(
new ArrayInitializerExpression(
new ObjectCreateExpression {
Type = new SimpleType("Contact"),
Initializer = new ArrayInitializerExpression {
Elements = {
new NamedExpression("Name", new PrimitiveExpression("Chris")),
new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () {
Elements = { new PrimitiveExpression("206-555-0101") }
Elements = { new ArrayInitializerExpression(new PrimitiveExpression("206-555-0101")) }
})
}}},
}}}),
new ArrayInitializerExpression(
new ObjectCreateExpression {
Type = new SimpleType("Contact"),
Arguments = { new IdentifierExpression("additionalParameter") },
@ -223,11 +224,28 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -223,11 +224,28 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
new NamedExpression("Name", new PrimitiveExpression("Bob")),
new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () {
Elements = {
new PrimitiveExpression("650-555-0199"),
new PrimitiveExpression("425-882-8080")
new ArrayInitializerExpression(new PrimitiveExpression("650-555-0199")),
new ArrayInitializerExpression(new PrimitiveExpression("425-882-8080"))
}
})
}}}
}}})
)});
}
[Test]
public void AssignmentInCollectionInitializer()
{
ParseUtilCSharp.AssertExpression(
@"new List<int> { { a = 1 } }",
new ObjectCreateExpression {
Type = new SimpleType("List", new PrimitiveType("int")),
Initializer = new ArrayInitializerExpression {
Elements = {
new ArrayInitializerExpression {
Elements = {
new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(1))
}
}
}}});
}
}

8
ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs

@ -214,5 +214,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -214,5 +214,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression
CheckLiteral(@"'\x0041'", '\x0041');
CheckLiteral(@"'\U00000041'", '\U00000041');
}
[Test, Ignore(@"Parser includes \r in integer literal")]
public void TestPositionOfIntegerAtEndOfLine()
{
var pe = ParseUtilCSharp.ParseExpression<PrimitiveExpression>("0\r\n");
Assert.AreEqual(new AstLocation(1, 1), pe.StartLocation);
Assert.AreEqual(new AstLocation(1, 2), pe.EndLocation);
}
}
}

6
ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs

@ -154,7 +154,7 @@ public class Form1 { @@ -154,7 +154,7 @@ public class Form1 {
// TODO: Tests for other contexts where attributes can appear
[Test, Ignore("Parser doesn't support named arguments in attributes")]
[Test, Ignore("Parser does not support NamedArgumentExpression in attributes")]
public void AttributeWithNamedArguments()
{
ParseUtilCSharp.AssertTypeMember(
@ -168,8 +168,8 @@ public class Form1 { @@ -168,8 +168,8 @@ public class Form1 {
Type = new SimpleType("A"),
Arguments = {
new PrimitiveExpression(0),
new NamedArgumentExpression { Identifier = "a", Expression = new PrimitiveExpression(1) },
new AssignmentExpression(new IdentifierExpression("b"), new PrimitiveExpression(2))
new NamedArgumentExpression("a", new PrimitiveExpression(1)),
new NamedExpression("b", new PrimitiveExpression(2))
}
}
}

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

@ -206,7 +206,7 @@ class TestClass { @@ -206,7 +206,7 @@ class TestClass {
}
#endregion
[Test, Ignore("Parser doesn't support object initializers yet")]
[Test]
public void LambdaInObjectInitializerTest()
{
string program = @"using System;
@ -238,6 +238,20 @@ static class TestClass { @@ -238,6 +238,20 @@ static class TestClass {
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
}
[Test]
public void LambdaExpressionInDelegateCreateExpression()
{
string program = @"using System;
static class TestClass {
static void Main(string[] args) {
var f = new Func<int, string>( i => $i$ );
}
public delegate R Func<T, R>(T arg);
}";
var lrr = Resolve<LocalResolveResult>(program);
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
}
[Test]
public void LambdaExpressionInReturnStatement()
{

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

@ -141,5 +141,20 @@ class C : B { @@ -141,5 +141,20 @@ class C : B {
mrr = Resolve<InvocationResolveResult>(program, "this(0)");
Assert.AreEqual("C..ctor", mrr.Member.FullName);
}
[Test]
public void FieldReferenceInObjectInitializer()
{
string program = @"class A {
public int Property;
}
class B {
void Method() {
var x = new A() { $Property = 0$ };
}
}";
MemberResolveResult result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("A.Property", result.Member.FullName);
}
}
}

14
ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs

@ -33,6 +33,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -33,6 +33,20 @@ namespace ICSharpCode.NRefactory.CSharp
/// </summary>
public class ArrayInitializerExpression : Expression
{
public ArrayInitializerExpression()
{
}
public ArrayInitializerExpression(IEnumerable<Expression> elements)
{
this.Elements.AddRange(elements);
}
public ArrayInitializerExpression(params Expression[] elements)
{
this.Elements.AddRange(elements);
}
#region Null
public new static readonly ArrayInitializerExpression Null = new NullArrayInitializerExpression ();

6
ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs

@ -48,12 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -48,12 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp
this.Right = right;
}
public AssignmentExpression(string left, Expression right)
{
this.Left = new IdentifierExpression(left);
this.Right = right;
}
public AssignmentExpression(Expression left, AssignmentOperatorType op, Expression right)
{
this.Left = left;

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

@ -269,6 +269,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -269,6 +269,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region Object Initializer Context
sealed class ObjectInitializerContext
{
internal readonly IType type;
internal readonly ObjectInitializerContext prev;
public ObjectInitializerContext(IType type, CSharpResolver.ObjectInitializerContext prev)
{
this.type = type;
this.prev = prev;
}
}
ObjectInitializerContext objectInitializerStack;
/// <summary>
/// Pushes the type of the object that is currently being initialized.
/// </summary>
public void PushInitializerType(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
objectInitializerStack = new ObjectInitializerContext(type, objectInitializerStack);
}
public void PopInitializerType()
{
if (objectInitializerStack == null)
throw new InvalidOperationException();
objectInitializerStack = objectInitializerStack.prev;
}
/// <summary>
/// Gets the type of the object currently being initialized.
/// Returns SharedTypes.Unknown if no object initializer is currently open (or if the object initializer
/// has unknown type).
/// </summary>
public IType CurrentObjectInitializerType {
get { return objectInitializerStack != null ? objectInitializerStack.type : SharedTypes.UnknownType; }
}
#endregion
#region Clone
/// <summary>
/// Creates a copy of this CSharp resolver.
@ -2073,6 +2115,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2073,6 +2115,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region ResolveIdentifierInObjectInitializer
public ResolveResult ResolveIdentifierInObjectInitializer(string identifier)
{
MemberLookup memberLookup = CreateMemberLookup();
ResolveResult target = new ResolveResult(this.CurrentObjectInitializerType);
return memberLookup.Lookup(target, identifier, EmptyList<IType>.Instance, false);
}
#endregion
#region GetExtensionMethods
/// <summary>
/// Gets the extension methods that are called 'name'
@ -2377,6 +2428,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2377,6 +2428,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
cancellationToken.ThrowIfCancellationRequested();
if (type.Kind == TypeKind.Delegate && arguments.Length == 1) {
return Convert(arguments[0], type);
}
OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]);
MemberLookup lookup = CreateMemberLookup();
bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(type);

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

@ -35,19 +35,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -35,19 +35,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
static class Log
{
[Conditional("DEBUG")]
const bool logEnabled = false;
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string text)
{
Debug.WriteLine(text);
}
[Conditional("DEBUG")]
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteLine(string format, params object[] args)
{
Debug.WriteLine(format, args);
}
[Conditional("DEBUG")]
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
internal static void WriteCollection<T>(string text, IEnumerable<T> lines)
{
#if DEBUG
@ -63,13 +65,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -63,13 +65,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endif
}
[Conditional("DEBUG")]
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
public static void Indent()
{
Debug.Indent();
}
[Conditional("DEBUG")]
[Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")]
public static void Unindent()
{
Debug.Unindent();

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

@ -221,6 +221,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -221,6 +221,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
protected override ResolveResult VisitChildren(AstNode node, object data)
{
Log.WriteLine("ResolveVisitor: unhandled node " + node.GetType().Name);
ScanChildren(node);
return null;
}
@ -369,7 +370,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -369,7 +370,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.UsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation);
}
ScanChildren(namespaceDeclaration);
return new NamespaceResolveResult(resolver.UsingScope.NamespaceName);
if (resolver.UsingScope != null)
return new NamespaceResolveResult(resolver.UsingScope.NamespaceName);
else
return null;
} finally {
resolver.UsingScope = previousUsingScope;
}
@ -751,8 +755,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -751,8 +755,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr)
{
if (expr is NamedArgumentExpression) {
var namedArgExpr = (NamedArgumentExpression)expr;
if (expr is NamedExpression) {
var namedArgExpr = (NamedExpression)expr;
resolveExpr = namedArgExpr.Expression;
return namedArgExpr.Identifier;
}
@ -771,29 +775,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -771,29 +775,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data)
{
ScanChildren(anonymousTypeCreateExpression);
// 7.6.10.6 Anonymous object creation expressions
var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$");
if (resolver.UsingScope == null) {
ScanChildren(anonymousTypeCreateExpression);
return errorResult;
}
var anonymousType = new DefaultTypeDefinition(resolver.UsingScope.ProjectContent, string.Empty, "$Anonymous$");
anonymousType.IsSynthetic = true;
resolver.PushInitializerType(anonymousType);
foreach (var expr in anonymousTypeCreateExpression.Initializers) {
Expression resolveExpr;
var name = GetAnonymousTypePropertyName(expr, out resolveExpr);
if (string.IsNullOrEmpty(name))
continue;
var property = new DefaultProperty(anonymousType, name) {
Accessibility = Accessibility.Public,
ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false)
};
anonymousType.Properties.Add(property);
if (!string.IsNullOrEmpty(name)) {
var property = new DefaultProperty(anonymousType, name) {
Accessibility = Accessibility.Public,
ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false)
};
anonymousType.Properties.Add(property);
}
Scan(expr);
}
ScanChildren(anonymousTypeCreateExpression);
resolver.PopInitializerType();
return new ResolveResult(anonymousType);
}
public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
{
ScanChildren(arrayCreateExpression);
if (!resolverEnabled) {
ScanChildren(arrayCreateExpression);
return null;
}
@ -973,15 +983,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -973,15 +983,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
}
// NamedArgumentExpression is "identifier: Expression"
public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data)
{
// Usually, the parent expression takes care of handling NamedArgumentExpressions
// The parent expression takes care of handling NamedArgumentExpressions
// by calling GetArguments().
if (resolverEnabled) {
return Resolve(namedArgumentExpression.Expression);
// This method gets called only when scanning, or when the named argument is used
// in an invalid context.
Scan(namedArgumentExpression.Expression);
return errorResult;
}
// NamedExpression is "identifier = Expression" in object initializers and attributes
public override ResolveResult VisitNamedExpression(NamedExpression namedExpression, object data)
{
Expression rhs = namedExpression.Expression;
if (rhs is ArrayInitializerExpression) {
throw new NotImplementedException();
} else {
Scan(namedArgumentExpression.Expression);
return null;
if (resolverEnabled) {
ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier);
ResolveAndProcessConversion(rhs, result.Type);
return result;
} else {
ScanChildren(namedExpression);
return null;
}
}
}
@ -996,14 +1023,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -996,14 +1023,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
{
if (resolverEnabled) {
if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) {
IType type = ResolveType(objectCreateExpression.Type);
string[] argumentNames;
ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames);
Scan(objectCreateExpression.Initializer); // TODO
var initializer = objectCreateExpression.Initializer;
if (!initializer.IsNull) {
resolver.PushInitializerType(type);
foreach (Expression element in initializer.Elements) {
if (element is NamedExpression) {
// assignment in object initializer
Scan(element);
} else if (element is ArrayInitializerExpression) {
// constructor argument list in collection initializer
throw new NotImplementedException();
} else {
// element in collection initializer
throw new NotImplementedException();
}
}
resolver.PopInitializerType();
}
return resolver.ResolveObjectCreation(type, arguments, argumentNames);
if (resolverEnabled) {
string[] argumentNames;
ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames);
return resolver.ResolveObjectCreation(type, arguments, argumentNames);
} else {
foreach (AstNode node in objectCreateExpression.Arguments) {
Scan(node);
}
return null;
}
} else {
ScanChildren(objectCreateExpression);
return null;
@ -2096,6 +2147,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2096,6 +2147,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region Other statements
public override ResolveResult VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
{
ScanChildren(expressionStatement);
return voidResult;
}
#endregion
#region Local Variable Type Inference
/// <summary>
/// Creates a type reference for the specified type node.
@ -2221,23 +2280,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2221,23 +2280,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region Attributes
public override ResolveResult VisitAttribute(Attribute attribute, object data)
{
var type = ResolveType(attribute.Type);
// Separate arguments into ctor arguments and non-ctor arguments:
var constructorArguments = attribute.Arguments.Where(a => !(a is NamedExpression));
var nonConstructorArguments = attribute.Arguments.Where(a => a is NamedExpression);
// Scan the non-constructor arguments
resolver.PushInitializerType(type);
foreach (var arg in nonConstructorArguments)
Scan(arg);
resolver.PopInitializerType();
if (resolverEnabled) {
var type = ResolveType(attribute.Type);
// Separate arguments into ctor arguments and non-ctor arguments:
var constructorArguments = attribute.Arguments.Where(a => !(a is AssignmentExpression));
var nonConstructorArguments = attribute.Arguments.Where(a => a is AssignmentExpression);
// Scan the non-constructor arguments
foreach (var arg in nonConstructorArguments)
Scan(arg); // TODO: handle these like object initializers
// Resolve the ctor arguments and find the matching ctor overload
string[] argumentNames;
ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames);
return resolver.ResolveObjectCreation(type, arguments, argumentNames);
} else {
ScanChildren(attribute);
foreach (var node in constructorArguments)
Scan(node);
return null;
}
}

2
ICSharpCode.NRefactory/Properties/AssemblyInfo.cs

@ -28,4 +28,4 @@ using System.Runtime.InteropServices; @@ -28,4 +28,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("5.0.0.0")]

Loading…
Cancel
Save