Browse Source

Implemented IConstantValue for C#.

Fixed bugs when resolving conditional expressions.
newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
eb24135e41
  1. 85
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs
  2. 3
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  3. 2
      ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs
  4. 134
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  5. 68
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  6. 391
      ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs
  7. 9
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  8. 3
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

85
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// assign short name to the fake reflection type
using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic;
[TestFixture]
public class ConditionalOperatorTests : ResolverTestBase
{
[Test]
public void PickMoreGeneralOfTheTypes()
{
AssertType(typeof(object), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeResult(typeof(object))));
AssertType(typeof(long), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(int)), MakeResult(typeof(long))));
}
[Test]
public void Null()
{
AssertType(typeof(string), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeConstant(null)));
AssertType(typeof(string), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeConstant(null), MakeResult(typeof(string))));
}
[Test]
public void DynamicInArguments()
{
AssertType(typeof(dynamic), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(dynamic)), MakeResult(typeof(double))));
AssertType(typeof(dynamic), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(double)), MakeResult(typeof(dynamic))));
}
[Test]
public void DynamicInCondition()
{
AssertType(typeof(double), resolver.ResolveConditional(
MakeResult(typeof(dynamic)), MakeResult(typeof(float)), MakeResult(typeof(double))));
}
[Test]
public void AllDynamic()
{
AssertType(typeof(dynamic), resolver.ResolveConditional(
MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic))));
}
[Test]
public void ListOfDynamicAndListOfObject()
{
AssertError(typeof(List<dynamic>), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(List<object>)), MakeResult(typeof(List<dynamic>))));
AssertError(typeof(List<object>), resolver.ResolveConditional(
MakeResult(typeof(bool)), MakeResult(typeof(List<dynamic>)), MakeResult(typeof(List<object>))));
}
[Test]
public void Constant()
{
AssertConstant(1L, resolver.ResolveConditional(
MakeConstant(true), MakeConstant(1), MakeConstant(2L)));
AssertConstant(2L, resolver.ResolveConditional(
MakeConstant(false), MakeConstant(1), MakeConstant(2L)));
}
[Test]
public void NotConstantIfFalsePortionNotConstant()
{
AssertType(typeof(long), resolver.ResolveConditional(
MakeConstant(true), MakeConstant(1), MakeResult(typeof(long))));
}
}
}

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>
@ -120,6 +120,7 @@ @@ -120,6 +120,7 @@
<Compile Include="CSharp\Resolver\AttributeTests.cs" />
<Compile Include="CSharp\Resolver\BinaryOperatorTests.cs" />
<Compile Include="CSharp\Resolver\CastTests.cs" />
<Compile Include="CSharp\Resolver\ConditionalOperatorTests.cs" />
<Compile Include="CSharp\Resolver\ExtensionMethodTests.cs" />
<Compile Include="CSharp\Resolver\InvocationTests.cs" />
<Compile Include="CSharp\Resolver\LambdaTests.cs" />

2
ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs

@ -1085,7 +1085,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -1085,7 +1085,9 @@ namespace ICSharpCode.NRefactory.CSharp
queryFromClause.Type.AcceptVisitor(this, data);
Space();
WriteIdentifier(queryFromClause.Identifier);
Space();
WriteKeyword("in", QueryFromClause.InKeywordRole);
Space();
queryFromClause.Expression.AcceptVisitor(this, data);
return EndNode(queryFromClause);
}

134
ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
@ -652,8 +653,137 @@ namespace ICSharpCode.NRefactory.CSharp @@ -652,8 +653,137 @@ namespace ICSharpCode.NRefactory.CSharp
#region Constant Values
IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression)
{
// TODO: implement ConvertConstantValue
return new SimpleConstantValue(targetType, null);
ConstantValueBuilder b = new ConstantValueBuilder();
b.convertVisitor = this;
// TODO: initialize b.checkForOverflow based on the project's overflow setting
IConstantValue c = expression.AcceptVisitor(b, null);
if (c != null)
return new ConstantCast(targetType, c, b.checkForOverflow);
else
return c;
}
sealed class ConstantValueBuilder : DepthFirstAstVisitor<object, IConstantValue>
{
internal TypeSystemConvertVisitor convertVisitor;
internal bool checkForOverflow;
protected override IConstantValue VisitChildren(AstNode node, object data)
{
return null;
}
public override IConstantValue VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data)
{
return new SimpleConstantValue(KnownTypeReference.Object, null);
}
public override IConstantValue VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
TypeCode typeCode = Type.GetTypeCode(primitiveExpression.Value.GetType());
return new SimpleConstantValue(typeCode.ToTypeReference(), primitiveExpression.Value);
}
IList<ITypeReference> ConvertTypeArguments(AstNodeCollection<AstType> types)
{
int count = types.Count;
if (count == 0)
return null;
ITypeReference[] result = new ITypeReference[count];
int pos = 0;
foreach (AstType type in types) {
result[pos++] = convertVisitor.ConvertType(type);
}
return result;
}
public override IConstantValue VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
return new ConstantIdentifierReference(identifierExpression.Identifier, ConvertTypeArguments(identifierExpression.TypeArguments));
}
public override IConstantValue VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
TypeReferenceExpression tre = memberReferenceExpression.Target as TypeReferenceExpression;
if (tre != null) {
// handle "int.MaxValue"
return new ConstantMemberReference(
convertVisitor.ConvertType(tre.Type),
memberReferenceExpression.MemberName,
ConvertTypeArguments(memberReferenceExpression.TypeArguments));
}
IConstantValue v = memberReferenceExpression.Target.AcceptVisitor(this, data);
if (v == null)
return null;
return new ConstantMemberReference(
v, memberReferenceExpression.MemberName,
ConvertTypeArguments(memberReferenceExpression.TypeArguments));
}
public override IConstantValue VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
return parenthesizedExpression.Expression.AcceptVisitor(this, data);
}
public override IConstantValue VisitCastExpression(CastExpression castExpression, object data)
{
IConstantValue v = castExpression.Expression.AcceptVisitor(this, data);
if (v == null)
return null;
return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v, checkForOverflow);
}
public override IConstantValue VisitCheckedExpression(CheckedExpression checkedExpression, object data)
{
bool oldCheckForOverflow = checkForOverflow;
try {
checkForOverflow = true;
return checkedExpression.Expression.AcceptVisitor(this, data);
} finally {
checkForOverflow = oldCheckForOverflow;
}
}
public override IConstantValue VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data)
{
bool oldCheckForOverflow = checkForOverflow;
try {
checkForOverflow = false;
return uncheckedExpression.Expression.AcceptVisitor(this, data);
} finally {
checkForOverflow = oldCheckForOverflow;
}
}
public override IConstantValue VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
{
return new ConstantDefaultValue(convertVisitor.ConvertType(defaultValueExpression.Type));
}
public override IConstantValue VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
{
IConstantValue v = unaryOperatorExpression.Expression.AcceptVisitor(this, data);
if (v == null)
return null;
switch (unaryOperatorExpression.Operator) {
case UnaryOperatorType.Not:
case UnaryOperatorType.BitNot:
case UnaryOperatorType.Minus:
case UnaryOperatorType.Plus:
return new ConstantUnaryOperator(unaryOperatorExpression.Operator, v, checkForOverflow);
default:
return null;
}
}
public override IConstantValue VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
IConstantValue left = binaryOperatorExpression.Left.AcceptVisitor(this, data);
IConstantValue right = binaryOperatorExpression.Right.AcceptVisitor(this, data);
if (left == null || right == null)
return null;
return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right, checkForOverflow);
}
}
#endregion

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

@ -2043,7 +2043,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2043,7 +2043,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region ResolveConditional
public ResolveResult ResolveConditional(ResolveResult trueExpression, ResolveResult falseExpression)
public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression)
{
// C# 4.0 spec §7.14: Conditional operator
@ -2052,11 +2052,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2052,11 +2052,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Conversions c = new Conversions(context);
bool isValid;
IType resultType;
if (HasType(trueExpression) && HasType(falseExpression)) {
if (trueExpression.Type == SharedTypes.Dynamic || falseExpression.Type == SharedTypes.Dynamic) {
resultType = SharedTypes.Dynamic;
isValid = true;
} else if (HasType(trueExpression) && HasType(falseExpression)) {
bool t2f = c.ImplicitConversion(trueExpression.Type, falseExpression.Type);
bool f2t = c.ImplicitConversion(falseExpression.Type, trueExpression.Type);
resultType = (f2t && !t2f) ? falseExpression.Type : trueExpression.Type;
isValid = (t2f != f2t) || (t2f && f2t && c.IdentityConversion(trueExpression.Type, falseExpression.Type));
resultType = (f2t && !t2f) ? trueExpression.Type : falseExpression.Type;
// The operator is valid:
// a) if there's a conversion in one direction but not the other
// b) if there are conversions in both directions, and the types are equivalent
isValid = (t2f != f2t) || (t2f && f2t && trueExpression.Type.Equals(falseExpression.Type));
} else if (HasType(trueExpression)) {
resultType = trueExpression.Type;
isValid = c.ImplicitConversion(falseExpression, resultType);
@ -2066,7 +2072,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2066,7 +2072,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else {
return ErrorResult;
}
return isValid ? new ResolveResult(resultType) : new ErrorResolveResult(resultType);
if (isValid) {
if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) {
bool? val = condition.ConstantValue as bool?;
if (val == true)
return ResolveCast(resultType, trueExpression);
else if (val == false)
return ResolveCast(resultType, falseExpression);
}
return new ResolveResult(resultType);
} else {
return new ErrorResolveResult(resultType);
}
}
bool HasType(ResolveResult r)
@ -2087,5 +2104,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2087,5 +2104,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
#endregion
#region ResolveDefaultValue
public ResolveResult ResolveDefaultValue(IType type)
{
return new ConstantResolveResult(type, GetDefaultValue(type));
}
public static object GetDefaultValue(IType type)
{
switch (ReflectionHelper.GetTypeCode(type)) {
case TypeCode.Boolean:
return false;
case TypeCode.Char:
return '\0';
case TypeCode.SByte:
return (sbyte)0;
case TypeCode.Byte:
return (byte)0;
case TypeCode.Int16:
return (short)0;
case TypeCode.UInt16:
return (ushort)0;
case TypeCode.Int32:
return 0;
case TypeCode.UInt32:
return 0U;
case TypeCode.Int64:
return 0L;
case TypeCode.UInt64:
return 0UL;
case TypeCode.Single:
return 0f;
case TypeCode.Double:
return 0.0;
case TypeCode.Decimal:
return 0m;
default:
return null;
}
}
#endregion
}
}

391
ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs

@ -0,0 +1,391 @@ @@ -0,0 +1,391 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
{
// Contains representations for constant C# expressions.
// We use these instead of storing the full AST to reduce the memory usage.
// The type system's SimpleConstantValue is used to represent PrimitiveExpressions.
public abstract class ConstantExpression : Immutable, IConstantValue
{
public abstract ResolveResult Resolve(CSharpResolver resolver);
public static ResolveResult Resolve(IConstantValue constantValue, CSharpResolver resolver)
{
ConstantExpression expr = constantValue as ConstantExpression;
if (expr != null)
return expr.Resolve(resolver);
else
return new ConstantResolveResult(constantValue.GetValueType(resolver.Context), constantValue.GetValue(resolver.Context));
}
public IType GetValueType(ITypeResolveContext context)
{
return Resolve(new CSharpResolver(context)).Type;
}
public object GetValue(ITypeResolveContext context)
{
return Resolve(new CSharpResolver(context)).ConstantValue;
}
}
public class ConstantCast : ConstantExpression, ISupportsInterning
{
ITypeReference targetType;
IConstantValue expression;
readonly bool checkForOverflow;
public ConstantCast(ITypeReference targetType, IConstantValue expression, bool checkForOverflow)
{
if (targetType == null)
throw new ArgumentNullException("targetType");
if (expression == null)
throw new ArgumentNullException("expression");
this.targetType = targetType;
this.expression = expression;
this.checkForOverflow = checkForOverflow;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
ResolveResult rr = Resolve(expression, resolver);
resolver.CheckForOverflow = checkForOverflow;
return resolver.ResolveCast(targetType.Resolve(resolver.Context), rr);
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
targetType = provider.Intern(targetType);
expression = provider.Intern(expression);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return targetType.GetHashCode() + expression.GetHashCode() * 1018829 + (checkForOverflow ? 614811 : 7125912);
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantCast cast = other as ConstantCast;
return cast != null
&& this.targetType == cast.targetType && this.expression == cast.expression
&& this.checkForOverflow == cast.checkForOverflow;
}
}
public class ConstantIdentifierReference : ConstantExpression, ISupportsInterning
{
string identifier;
IList<ITypeReference> typeArguments;
public ConstantIdentifierReference(string identifier, IList<ITypeReference> typeArguments = null)
{
if (identifier == null)
throw new ArgumentNullException("identifier");
this.identifier = identifier;
this.typeArguments = typeArguments;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveSimpleName(identifier, ResolveTypes(resolver, typeArguments));
}
internal static IList<IType> ResolveTypes(CSharpResolver resolver, IList<ITypeReference> typeArguments)
{
if (typeArguments == null)
return EmptyList<IType>.Instance;
IType[] types = new IType[typeArguments.Count];
for (int i = 0; i < types.Length; i++) {
types[i] = typeArguments[i].Resolve(resolver.Context);
}
return types;
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
identifier = provider.Intern(identifier);
typeArguments = provider.InternList(typeArguments);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
int hashCode = identifier.GetHashCode();
if (typeArguments != null)
hashCode ^= typeArguments.GetHashCode();
return hashCode;
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantIdentifierReference cir = other as ConstantIdentifierReference;
return cir != null &&
this.identifier == cir.identifier && this.typeArguments == cir.typeArguments;
}
}
public class ConstantMemberReference : ConstantExpression, ISupportsInterning
{
ITypeReference targetType;
IConstantValue targetExpression;
string memberName;
IList<ITypeReference> typeArguments;
public ConstantMemberReference(ITypeReference targetType, string memberName, IList<ITypeReference> typeArguments = null)
{
if (targetType == null)
throw new ArgumentNullException("targetType");
if (memberName == null)
throw new ArgumentNullException("memberName");
this.targetType = targetType;
this.memberName = memberName;
this.typeArguments = typeArguments;
}
public ConstantMemberReference(IConstantValue targetExpression, string memberName, IList<ITypeReference> typeArguments = null)
{
if (targetExpression == null)
throw new ArgumentNullException("targetExpression");
if (memberName == null)
throw new ArgumentNullException("memberName");
this.targetExpression = targetExpression;
this.memberName = memberName;
this.typeArguments = typeArguments;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
ResolveResult rr;
if (targetType != null)
rr = new TypeResolveResult(targetType.Resolve(resolver.Context));
else
rr = Resolve(targetExpression, resolver);
return resolver.ResolveMemberAccess(rr, memberName, ConstantIdentifierReference.ResolveTypes(resolver, typeArguments));
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
targetType = provider.Intern(targetType);
targetExpression = provider.Intern(targetExpression);
memberName = provider.Intern(memberName);
typeArguments = provider.InternList(typeArguments);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
int hashCode;
if (targetType != null)
hashCode = targetType.GetHashCode();
else
hashCode = targetExpression.GetHashCode();
hashCode ^= memberName.GetHashCode();
if (typeArguments != null)
hashCode ^= typeArguments.GetHashCode();
return hashCode;
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantMemberReference cmr = other as ConstantMemberReference;
return cmr != null
&& this.targetType == cmr.targetType && this.targetExpression == cmr.targetExpression
&& this.memberName == cmr.memberName && this.typeArguments == cmr.typeArguments;
}
}
public class ConstantDefaultValue : ConstantExpression, ISupportsInterning
{
ITypeReference type;
public ConstantDefaultValue(ITypeReference type)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveDefaultValue(type.Resolve(resolver.Context));
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
type = provider.Intern(type);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return type.GetHashCode();
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantDefaultValue o = other as ConstantDefaultValue;
return o != null && this.type == o.type;
}
}
public class ConstantUnaryOperator : ConstantExpression, ISupportsInterning
{
UnaryOperatorType operatorType;
IConstantValue expression;
bool checkForOverflow;
public ConstantUnaryOperator(UnaryOperatorType operatorType, IConstantValue expression, bool checkForOverflow)
{
if (expression == null)
throw new ArgumentNullException("expression");
this.operatorType = operatorType;
this.expression = expression;
this.checkForOverflow = checkForOverflow;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
ResolveResult rr = Resolve(expression, resolver);
resolver.CheckForOverflow = checkForOverflow;
return resolver.ResolveUnaryOperator(operatorType, rr);
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
expression = provider.Intern(expression);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return expression.GetHashCode() * 811 + operatorType.GetHashCode() + (checkForOverflow ? 1717211 : 12751265);
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantUnaryOperator uop = other as ConstantUnaryOperator;
return uop != null
&& this.operatorType == uop.operatorType
&& this.expression == uop.expression
&& this.checkForOverflow == uop.checkForOverflow;
}
}
public class ConstantBinaryOperator : ConstantExpression, ISupportsInterning
{
IConstantValue left;
BinaryOperatorType operatorType;
IConstantValue right;
bool checkForOverflow;
public ConstantBinaryOperator(IConstantValue left, BinaryOperatorType operatorType, IConstantValue right, bool checkForOverflow)
{
if (left == null)
throw new ArgumentNullException("left");
if (right == null)
throw new ArgumentNullException("right");
this.left = left;
this.operatorType = operatorType;
this.right = right;
this.checkForOverflow = checkForOverflow;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
ResolveResult lhs = Resolve(left, resolver);
ResolveResult rhs = Resolve(right, resolver);
resolver.CheckForOverflow = checkForOverflow;
return resolver.ResolveBinaryOperator(operatorType, lhs, rhs);
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
left = provider.Intern(left);
right = provider.Intern(right);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return left.GetHashCode() * 811 + operatorType.GetHashCode()
+ right.GetHashCode() * 91781 + (checkForOverflow ? 1261561 : 174811);
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantBinaryOperator bop = other as ConstantBinaryOperator;
return bop != null
&& this.operatorType == bop.operatorType
&& this.left == bop.left && this.right == bop.right
&& this.checkForOverflow == bop.checkForOverflow;
}
}
public class ConstantConditionalOperator : ConstantExpression, ISupportsInterning
{
IConstantValue condition, trueExpr, falseExpr;
public ConstantConditionalOperator(IConstantValue condition, IConstantValue trueExpr, IConstantValue falseExpr)
{
if (condition == null)
throw new ArgumentNullException("condition");
if (trueExpr == null)
throw new ArgumentNullException("trueExpr");
if (falseExpr == null)
throw new ArgumentNullException("falseExpr");
this.condition = condition;
this.trueExpr = trueExpr;
this.falseExpr = falseExpr;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveConditional(
Resolve(condition, resolver),
Resolve(trueExpr, resolver),
Resolve(falseExpr, resolver)
);
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
condition = provider.Intern(condition);
trueExpr = provider.Intern(trueExpr);
falseExpr = provider.Intern(falseExpr);
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return condition.GetHashCode() * 182981713
+ trueExpr.GetHashCode() * 917517169
+ falseExpr.GetHashCode() * 611651;
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantConditionalOperator coo = other as ConstantConditionalOperator;
return coo != null
&& this.condition == coo.condition
&& this.trueExpr == coo.trueExpr
&& this.falseExpr == coo.falseExpr;
}
}
}

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

@ -567,9 +567,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -567,9 +567,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
{
if (resolverEnabled) {
Scan(conditionalExpression.Condition);
return resolver.ResolveConditional(Resolve(conditionalExpression.TrueExpression),
Resolve(conditionalExpression.FalseExpression));
return resolver.ResolveConditional(
Resolve(conditionalExpression.Condition),
Resolve(conditionalExpression.TrueExpression),
Resolve(conditionalExpression.FalseExpression));
} else {
ScanChildren(conditionalExpression);
return null;
@ -579,7 +580,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -579,7 +580,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
{
if (resolverEnabled) {
return new ConstantResolveResult(ResolveType(defaultValueExpression.Type), null);
return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type));
} else {
ScanChildren(defaultValueExpression);
return null;

3
ICSharpCode.NRefactory/ICSharpCode.NRefactory.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>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</ProjectGuid>
@ -97,6 +97,7 @@ @@ -97,6 +97,7 @@
<Compile Include="CSharp\Ast\Expressions\UncheckedExpression.cs" />
<Compile Include="CSharp\Ast\GeneralScope\TypeParameterDeclaration.cs" />
<Compile Include="CSharp\Ast\MemberType.cs" />
<Compile Include="CSharp\Resolver\ConstantValues.cs" />
<Compile Include="PatternMatching\BacktrackingInfo.cs" />
<Compile Include="PatternMatching\Choice.cs" />
<Compile Include="PatternMatching\AnyNode.cs" />

Loading…
Cancel
Save