Browse Source

ResolveResults for dynamic expressions

newNRvisualizers
Erik Källén 13 years ago
parent
commit
0bf9891a8e
  1. 2
      ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj
  2. 7
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  3. 73
      ICSharpCode.NRefactory.CSharp/Resolver/DynamicInvocationResolveResult.cs
  4. 57
      ICSharpCode.NRefactory.CSharp/Resolver/DynamicMemberResolveResult.cs
  5. 103
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/DynamicTests.cs
  6. 3
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

2
ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj

@ -249,6 +249,8 @@ @@ -249,6 +249,8 @@
<Compile Include="Refactoring\Script.cs" />
<Compile Include="Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="Resolver\CompositeResolveVisitorNavigator.cs" />
<Compile Include="Resolver\DynamicInvocationResolveResult.cs" />
<Compile Include="Resolver\DynamicMemberResolveResult.cs" />
<Compile Include="Resolver\CSharpConversions.cs" />
<Compile Include="Resolver\CSharpAstResolver.cs" />
<Compile Include="Resolver\CSharpInvocationResolveResult.cs" />

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

@ -1596,7 +1596,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1596,7 +1596,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
if (target.Type.Kind == TypeKind.Dynamic)
return new ResolveResult(SpecialType.Dynamic);
return new DynamicMemberResolveResult(target, identifier);
MemberLookup lookup = CreateMemberLookup(lookupMode);
ResolveResult result;
@ -1893,8 +1893,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1893,8 +1893,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// C# 4.0 spec: §7.6.5
if (target.Type.Kind == TypeKind.Dynamic)
return new ResolveResult(SpecialType.Dynamic);
if (target.Type.Kind == TypeKind.Dynamic) {
return new DynamicInvocationResolveResult(target, arguments.Select((a, i) => new DynamicInvocationArgument(argumentNames != null ? argumentNames[i] : null, a)).ToList().AsReadOnly());
}
MethodGroupResolveResult mgrr = target as MethodGroupResolveResult;
if (mgrr != null) {

73
ICSharpCode.NRefactory.CSharp/Resolver/DynamicInvocationResolveResult.cs

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
// 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 System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Represents a single argument in a dynamic invocation.
/// </summary>
public class DynamicInvocationArgument {
/// <summary>
/// Parameter name, if the argument is named. Null otherwise.
/// </summary>
public readonly string Name;
/// <summary>
/// Value of the argument.
/// </summary>
public readonly ResolveResult Value;
public DynamicInvocationArgument(string name, ResolveResult value) {
Name = name;
Value = value;
}
}
/// <summary>
/// Represents the result of an invocation of a member of a dynamic object.
/// </summary>
public class DynamicInvocationResolveResult : ResolveResult
{
/// <summary>
/// Target of the invocation (a dynamic object).
/// </summary>
public readonly ResolveResult Target;
/// <summary>
/// Arguments for the call.
/// </summary>
public readonly IList<DynamicInvocationArgument> Arguments;
public DynamicInvocationResolveResult(ResolveResult target, IList<DynamicInvocationArgument> arguments) : base(SpecialType.Dynamic) {
this.Target = target;
this.Arguments = arguments ?? EmptyList<DynamicInvocationArgument>.Instance;
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[Dynamic invocation ]");
}
}
}

57
ICSharpCode.NRefactory.CSharp/Resolver/DynamicMemberResolveResult.cs

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
// 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 System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Represents the result of an access to a member of a dynamic object.
/// </summary>
public class DynamicMemberResolveResult : ResolveResult
{
/// <summary>
/// Target of the member access (a dynamic object).
/// </summary>
public readonly ResolveResult Target;
/// <summary>
/// Name of the accessed member.
/// </summary>
public readonly string Member;
public DynamicMemberResolveResult(ResolveResult target, string member) : base(SpecialType.Dynamic) {
this.Target = target;
this.Member = member;
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "[Dynamic member '{0}']", Member);
}
public override IEnumerable<ResolveResult> GetChildResults() {
return new[] { Target };
}
}
}

103
ICSharpCode.NRefactory.Tests/CSharp/Resolver/DynamicTests.cs

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver {
[TestFixture]
public class DynamicTests : ResolverTestBase {
[Test]
public void AccessToDynamicMember() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
$obj.SomeProperty$ = 10;
}
}";
var rr = Resolve<DynamicMemberResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Target is LocalResolveResult && ((LocalResolveResult)rr.Target).Variable.Name == "obj");
Assert.That(rr.Member, Is.EqualTo("SomeProperty"));
}
[Test]
public void DynamicInvocation() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0;
string b = null;
$obj.SomeMethod(a, b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.Arguments.Count, Is.EqualTo(2));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "a");
Assert.That(rr.Arguments[1].Name, Is.Null);
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "b");
}
[Test]
public void DynamicInvocationWithNamedArguments() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, x = 0;
string b = null;
$obj.SomeMethod(x, param1: a, param2: b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)rr.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(rr.Arguments.Count, Is.EqualTo(3));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "x");
Assert.That(rr.Arguments[1].Name, Is.EqualTo("param1"));
Assert.That(rr.Arguments[1].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[1].Value).Variable.Name == "a");
Assert.That(rr.Arguments[2].Name, Is.EqualTo("param2"));
Assert.That(rr.Arguments[2].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[2].Value).Variable.Name == "b");
}
[Test]
public void TwoDynamicInvocationsInARow() {
string program = @"using System;
class TestClass {
void F() {
dynamic obj = null;
int a = 0, b = 0;
$obj.SomeMethod(a)(b)$;
}
}";
var rr = Resolve<DynamicInvocationResolveResult>(program);
Assert.That(rr.Type.Kind, Is.EqualTo(TypeKind.Dynamic));
Assert.That(rr.Target, Is.InstanceOf<DynamicInvocationResolveResult>());
var innerInvocation = (DynamicInvocationResolveResult)rr.Target;
Assert.That(innerInvocation.Target, Is.InstanceOf<DynamicMemberResolveResult>());
var dynamicMember = (DynamicMemberResolveResult)innerInvocation.Target;
Assert.That(dynamicMember.Target is LocalResolveResult && ((LocalResolveResult)dynamicMember.Target).Variable.Name == "obj");
Assert.That(dynamicMember.Member, Is.EqualTo("SomeMethod"));
Assert.That(innerInvocation.Arguments.Count, Is.EqualTo(1));
Assert.That(innerInvocation.Arguments[0].Name, Is.Null);
Assert.That(innerInvocation.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)innerInvocation.Arguments[0].Value).Variable.Name == "a");
Assert.That(rr.Arguments.Count, Is.EqualTo(1));
Assert.That(rr.Arguments[0].Name, Is.Null);
Assert.That(rr.Arguments[0].Value is LocalResolveResult && ((LocalResolveResult)rr.Arguments[0].Value).Variable.Name == "b");
}
}
}

3
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<PropertyGroup>
<ProjectGuid>{63D3B27A-D966-4902-90B3-30290E1692F1}</ProjectGuid>
@ -159,6 +159,7 @@ @@ -159,6 +159,7 @@
<Compile Include="CSharp\Resolver\CastTests.cs" />
<Compile Include="CSharp\Resolver\ComTests.cs" />
<Compile Include="CSharp\Resolver\ConditionalOperatorTests.cs" />
<Compile Include="CSharp\Resolver\DynamicTests.cs" />
<Compile Include="CSharp\Resolver\ExtensionMethodTests.cs" />
<Compile Include="CSharp\Resolver\FindReferencesTest.cs" />
<Compile Include="CSharp\Resolver\InvocationTests.cs" />

Loading…
Cancel
Save