Browse Source

Evaluate constant expressions in the correct context.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
a917b1cfb1
  1. 6
      ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs
  2. 107
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  3. 240
      ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs
  4. 49
      ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs
  5. 2
      ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs
  6. 2
      ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs
  7. 3
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  8. 2
      ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs

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

@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.CSharp
readonly string fileName;
readonly UsingScope rootUsingScope;
IList<ITypeDefinition> topLevelTypeDefinitions = new List<ITypeDefinition>();
IList<IAttribute> assemblyAttributes = new List<IAttribute>();
IList<UsingScope> usingScopes = new List<UsingScope>();
protected override void FreezeInternal()
@ -24,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -24,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp
base.FreezeInternal();
rootUsingScope.Freeze();
topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions);
assemblyAttributes = FreezeList(assemblyAttributes);
usingScopes = FreezeList(usingScopes);
}
@ -53,6 +55,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -53,6 +55,10 @@ namespace ICSharpCode.NRefactory.CSharp
get { return topLevelTypeDefinitions; }
}
public IList<IAttribute> AssemblyAttributes {
get { return assemblyAttributes; }
}
public UsingScope GetUsingScope(AstLocation location)
{
foreach (UsingScope scope in usingScopes) {

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

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues;
using ICSharpCode.NRefactory.TypeSystem;
@ -80,7 +81,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,7 +81,11 @@ namespace ICSharpCode.NRefactory.CSharp
}
#region Using Declarations
// TODO: extern aliases
public override IEntity VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data)
{
usingScope.ExternAliases.Add(externAliasDeclaration.Name);
return null;
}
public override IEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data)
{
@ -115,8 +120,6 @@ namespace ICSharpCode.NRefactory.CSharp @@ -115,8 +120,6 @@ namespace ICSharpCode.NRefactory.CSharp
}
#endregion
// TODO: assembly attributes
#region Type Definitions
DefaultTypeDefinition CreateTypeDefinition(string name)
{
@ -566,6 +569,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -566,6 +569,15 @@ namespace ICSharpCode.NRefactory.CSharp
#endregion
#region Attributes
public override IEntity VisitAttributeSection(AttributeSection attributeSection, object data)
{
// non-assembly attributes are handled by their parent entity
if (attributeSection.AttributeTarget == "assembly") {
ConvertAttributes(parsedFile.AssemblyAttributes, attributeSection);
}
return null;
}
void ConvertAttributes(IList<IAttribute> outputList, IEnumerable<AttributeSection> attributes)
{
foreach (AttributeSection section in attributes) {
@ -730,12 +742,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -730,12 +742,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
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;
ConstantExpression c = expression.AcceptVisitor(b, null);
if (c == null)
return null;
// cast to the desired type
c = new ConstantCast(targetType, c);
if (c.DependsOnContext()) {
return new CSharpConstantValue(c, usingScope, currentTypeDefinition);
} else {
// If the expression does not depend on the context,
// we can resolve it immediately and store the value only.
return new SimpleConstantValue(targetType, c.Resolve(new CSharpResolver(MinimalResolveContext.Instance)).ConstantValue);
}
}
IConstantValue ConvertAttributeArgument(Expression expression)
@ -743,25 +761,24 @@ namespace ICSharpCode.NRefactory.CSharp @@ -743,25 +761,24 @@ namespace ICSharpCode.NRefactory.CSharp
throw new NotImplementedException();
}
sealed class ConstantValueBuilder : DepthFirstAstVisitor<object, IConstantValue>
sealed class ConstantValueBuilder : DepthFirstAstVisitor<object, ConstantExpression>
{
internal TypeSystemConvertVisitor convertVisitor;
internal bool checkForOverflow;
protected override IConstantValue VisitChildren(AstNode node, object data)
protected override ConstantExpression VisitChildren(AstNode node, object data)
{
return null;
}
public override IConstantValue VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data)
public override ConstantExpression VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data)
{
return new SimpleConstantValue(KnownTypeReference.Object, null);
return new PrimitiveConstantExpression(KnownTypeReference.Object, null);
}
public override IConstantValue VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
public override ConstantExpression VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
TypeCode typeCode = Type.GetTypeCode(primitiveExpression.Value.GetType());
return new SimpleConstantValue(typeCode.ToTypeReference(), primitiveExpression.Value);
return new PrimitiveConstantExpression(typeCode.ToTypeReference(), primitiveExpression.Value);
}
IList<ITypeReference> ConvertTypeArguments(AstNodeCollection<AstType> types)
@ -777,12 +794,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -777,12 +794,12 @@ namespace ICSharpCode.NRefactory.CSharp
return result;
}
public override IConstantValue VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
public override ConstantExpression VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
return new ConstantIdentifierReference(identifierExpression.Identifier, ConvertTypeArguments(identifierExpression.TypeArguments));
}
public override IConstantValue VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
public override ConstantExpression VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
TypeReferenceExpression tre = memberReferenceExpression.Target as TypeReferenceExpression;
if (tre != null) {
@ -792,7 +809,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -792,7 +809,7 @@ namespace ICSharpCode.NRefactory.CSharp
memberReferenceExpression.MemberName,
ConvertTypeArguments(memberReferenceExpression.TypeArguments));
}
IConstantValue v = memberReferenceExpression.Target.AcceptVisitor(this, data);
ConstantExpression v = memberReferenceExpression.Target.AcceptVisitor(this, data);
if (v == null)
return null;
return new ConstantMemberReference(
@ -800,49 +817,45 @@ namespace ICSharpCode.NRefactory.CSharp @@ -800,49 +817,45 @@ namespace ICSharpCode.NRefactory.CSharp
ConvertTypeArguments(memberReferenceExpression.TypeArguments));
}
public override IConstantValue VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
public override ConstantExpression VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
return parenthesizedExpression.Expression.AcceptVisitor(this, data);
}
public override IConstantValue VisitCastExpression(CastExpression castExpression, object data)
public override ConstantExpression VisitCastExpression(CastExpression castExpression, object data)
{
IConstantValue v = castExpression.Expression.AcceptVisitor(this, data);
ConstantExpression v = castExpression.Expression.AcceptVisitor(this, data);
if (v == null)
return null;
return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v, checkForOverflow);
return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v);
}
public override IConstantValue VisitCheckedExpression(CheckedExpression checkedExpression, object data)
public override ConstantExpression VisitCheckedExpression(CheckedExpression checkedExpression, object data)
{
bool oldCheckForOverflow = checkForOverflow;
try {
checkForOverflow = true;
return checkedExpression.Expression.AcceptVisitor(this, data);
} finally {
checkForOverflow = oldCheckForOverflow;
}
ConstantExpression v = checkedExpression.Expression.AcceptVisitor(this, data);
if (v != null)
return new ConstantCheckedExpression(true, v);
else
return null;
}
public override IConstantValue VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data)
public override ConstantExpression VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data)
{
bool oldCheckForOverflow = checkForOverflow;
try {
checkForOverflow = false;
return uncheckedExpression.Expression.AcceptVisitor(this, data);
} finally {
checkForOverflow = oldCheckForOverflow;
}
ConstantExpression v = uncheckedExpression.Expression.AcceptVisitor(this, data);
if (v != null)
return new ConstantCheckedExpression(false, v);
else
return null;
}
public override IConstantValue VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
public override ConstantExpression VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
{
return new ConstantDefaultValue(convertVisitor.ConvertType(defaultValueExpression.Type));
}
public override IConstantValue VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
public override ConstantExpression VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
{
IConstantValue v = unaryOperatorExpression.Expression.AcceptVisitor(this, data);
ConstantExpression v = unaryOperatorExpression.Expression.AcceptVisitor(this, data);
if (v == null)
return null;
switch (unaryOperatorExpression.Operator) {
@ -850,19 +863,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -850,19 +863,19 @@ namespace ICSharpCode.NRefactory.CSharp
case UnaryOperatorType.BitNot:
case UnaryOperatorType.Minus:
case UnaryOperatorType.Plus:
return new ConstantUnaryOperator(unaryOperatorExpression.Operator, v, checkForOverflow);
return new ConstantUnaryOperator(unaryOperatorExpression.Operator, v);
default:
return null;
}
}
public override IConstantValue VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
public override ConstantExpression VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
IConstantValue left = binaryOperatorExpression.Left.AcceptVisitor(this, data);
IConstantValue right = binaryOperatorExpression.Right.AcceptVisitor(this, data);
ConstantExpression left = binaryOperatorExpression.Left.AcceptVisitor(this, data);
ConstantExpression right = binaryOperatorExpression.Right.AcceptVisitor(this, data);
if (left == null || right == null)
return null;
return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right, checkForOverflow);
return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right);
}
}
#endregion

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

@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Analysis;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
@ -12,39 +14,138 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -12,39 +14,138 @@ 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 class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning
{
public abstract ResolveResult Resolve(CSharpResolver resolver);
ConstantExpression expression;
UsingScope parentUsingScope;
ITypeDefinition parentTypeDefinition;
public static ResolveResult Resolve(IConstantValue constantValue, CSharpResolver resolver)
public CSharpConstantValue(ConstantExpression expression, UsingScope parentUsingScope, ITypeDefinition parentTypeDefinition)
{
ConstantExpression expr = constantValue as ConstantExpression;
if (expr != null)
return expr.Resolve(resolver);
else
return new ConstantResolveResult(constantValue.GetValueType(resolver.Context), constantValue.GetValue(resolver.Context));
if (expression == null)
throw new ArgumentNullException("expression");
this.expression = expression;
this.parentUsingScope = parentUsingScope;
this.parentTypeDefinition = parentTypeDefinition;
}
CSharpResolver CreateResolver(ITypeResolveContext context)
{
// Because constants are evaluated by the compiler, we need to evaluate them in the resolve context
// of the project where they are defined, not in that where the constant value is used.
// TODO: how do we get the correct resolve context?
return new CSharpResolver(context) {
CheckForOverflow = false, // TODO: get project-wide overflow setting
CurrentTypeDefinition = parentTypeDefinition,
UsingScope = parentUsingScope
};
}
public IType GetValueType(ITypeResolveContext context)
{
return Resolve(new CSharpResolver(context)).Type;
CSharpResolver resolver = CreateResolver(context);
IType type = expression.Resolve(resolver).Type;
if (resolver.Context != context) {
// Retrieve the equivalent type in the new resolve context.
// E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0.
// However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0.
return type.AcceptVisitor(new MapTypeIntoNewContext(context));
}
return type;
}
public object GetValue(ITypeResolveContext context)
{
return Resolve(new CSharpResolver(context)).ConstantValue;
return expression.Resolve(CreateResolver(context)).ConstantValue;
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
expression = provider.Intern(expression);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return expression.GetHashCode()
^ (parentUsingScope != null ? parentUsingScope.GetHashCode() : 0)
^ (parentTypeDefinition != null ? parentTypeDefinition.GetHashCode() : 0);
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
CSharpConstantValue cv = other as CSharpConstantValue;
return cv != null
&& expression == cv.expression
&& parentUsingScope == cv.parentUsingScope
&& parentTypeDefinition == cv.parentTypeDefinition;
}
}
public abstract class ConstantExpression
{
public abstract ResolveResult Resolve(CSharpResolver resolver);
/// <summary>
/// Gets whether the returned value depends on the expression's context.
/// </summary>
public virtual bool DependsOnContext()
{
return true;
}
}
public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning
{
ITypeReference type;
object value;
public PrimitiveConstantExpression(ITypeReference type, object value)
{
if (type == null)
throw new ArgumentNullException("type");
this.type = type;
this.value = value;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return new ConstantResolveResult(type.Resolve(resolver.Context), value);
}
public override bool DependsOnContext()
{
// Depends on context unless the type is a known primitive type.
foreach (var knownTypeRef in KnownTypeReference.AllKnownTypeReferences) {
if (knownTypeRef == type)
return false;
}
return true;
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
type = provider.Intern(type);
value = provider.Intern(value);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0);
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
PrimitiveConstantExpression scv = other as PrimitiveConstantExpression;
return scv != null && type == scv.type && value == scv.value;
}
}
public sealed class ConstantCast : ConstantExpression, ISupportsInterning
{
ITypeReference targetType;
IConstantValue expression;
readonly bool checkForOverflow;
ConstantExpression expression;
public ConstantCast(ITypeReference targetType, IConstantValue expression, bool checkForOverflow)
public ConstantCast(ITypeReference targetType, ConstantExpression expression)
{
if (targetType == null)
throw new ArgumentNullException("targetType");
@ -52,14 +153,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -52,14 +153,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
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);
return resolver.ResolveCast(targetType.Resolve(resolver.Context), expression.Resolve(resolver));
}
public override bool DependsOnContext()
{
return expression.DependsOnContext();
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
@ -71,7 +174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -71,7 +174,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return targetType.GetHashCode() + expression.GetHashCode() * 1018829 + (checkForOverflow ? 614811 : 7125912);
return targetType.GetHashCode() + expression.GetHashCode() * 1018829;
}
}
@ -79,8 +182,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -79,8 +182,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
{
ConstantCast cast = other as ConstantCast;
return cast != null
&& this.targetType == cast.targetType && this.expression == cast.expression
&& this.checkForOverflow == cast.checkForOverflow;
&& this.targetType == cast.targetType && this.expression == cast.expression;
}
}
@ -97,7 +199,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -97,7 +199,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
this.typeArguments = typeArguments;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveSimpleName(identifier, ResolveTypes(resolver, typeArguments));
@ -141,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -141,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning
{
ITypeReference targetType;
IConstantValue targetExpression;
ConstantExpression targetExpression;
string memberName;
IList<ITypeReference> typeArguments;
@ -156,7 +257,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -156,7 +257,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
this.typeArguments = typeArguments;
}
public ConstantMemberReference(IConstantValue targetExpression, string memberName, IList<ITypeReference> typeArguments = null)
public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList<ITypeReference> typeArguments = null)
{
if (targetExpression == null)
throw new ArgumentNullException("targetExpression");
@ -173,7 +274,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -173,7 +274,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
if (targetType != null)
rr = new TypeResolveResult(targetType.Resolve(resolver.Context));
else
rr = Resolve(targetExpression, resolver);
rr = targetExpression.Resolve(resolver);
return resolver.ResolveMemberAccess(rr, memberName, ConstantIdentifierReference.ResolveTypes(resolver, typeArguments));
}
@ -209,6 +310,49 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -209,6 +310,49 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
}
}
public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning
{
bool checkForOverflow;
ConstantExpression expression;
public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression)
{
if (expression == null)
throw new ArgumentNullException("expression");
this.checkForOverflow = checkForOverflow;
this.expression = expression;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
bool oldCheckForOverflow = resolver.CheckForOverflow;
try {
resolver.CheckForOverflow = this.checkForOverflow;
return expression.Resolve(resolver);
} finally {
resolver.CheckForOverflow = oldCheckForOverflow;
}
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
expression = provider.Intern(expression);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return expression.GetHashCode() ^ (checkForOverflow ? 161851612 : 75163517);
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantCheckedExpression cce = other as ConstantCheckedExpression;
return cce != null
&& this.expression == cce.expression
&& this.checkForOverflow == cce.checkForOverflow;
}
}
public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning
{
ITypeReference type;
@ -245,23 +389,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -245,23 +389,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning
{
UnaryOperatorType operatorType;
IConstantValue expression;
bool checkForOverflow;
ConstantExpression expression;
public ConstantUnaryOperator(UnaryOperatorType operatorType, IConstantValue expression, bool checkForOverflow)
public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression)
{
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);
return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver));
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
@ -272,7 +412,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -272,7 +412,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return expression.GetHashCode() * 811 + operatorType.GetHashCode() + (checkForOverflow ? 1717211 : 12751265);
return expression.GetHashCode() * 811 + operatorType.GetHashCode();
}
}
@ -281,19 +421,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -281,19 +421,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
ConstantUnaryOperator uop = other as ConstantUnaryOperator;
return uop != null
&& this.operatorType == uop.operatorType
&& this.expression == uop.expression
&& this.checkForOverflow == uop.checkForOverflow;
&& this.expression == uop.expression;
}
}
public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning
{
IConstantValue left;
ConstantExpression left;
BinaryOperatorType operatorType;
IConstantValue right;
bool checkForOverflow;
ConstantExpression right;
public ConstantBinaryOperator(IConstantValue left, BinaryOperatorType operatorType, IConstantValue right, bool checkForOverflow)
public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right)
{
if (left == null)
throw new ArgumentNullException("left");
@ -302,14 +440,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -302,14 +440,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
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;
ResolveResult lhs = left.Resolve(resolver);
ResolveResult rhs = right.Resolve(resolver);
return resolver.ResolveBinaryOperator(operatorType, lhs, rhs);
}
@ -322,8 +458,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -322,8 +458,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
return left.GetHashCode() * 811 + operatorType.GetHashCode()
+ right.GetHashCode() * 91781 + (checkForOverflow ? 1261561 : 174811);
return left.GetHashCode() * 811 + operatorType.GetHashCode() + right.GetHashCode() * 91781;
}
}
@ -332,16 +467,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -332,16 +467,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
ConstantBinaryOperator bop = other as ConstantBinaryOperator;
return bop != null
&& this.operatorType == bop.operatorType
&& this.left == bop.left && this.right == bop.right
&& this.checkForOverflow == bop.checkForOverflow;
&& this.left == bop.left && this.right == bop.right;
}
}
public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning
{
IConstantValue condition, trueExpr, falseExpr;
ConstantExpression condition, trueExpr, falseExpr;
public ConstantConditionalOperator(IConstantValue condition, IConstantValue trueExpr, IConstantValue falseExpr)
public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr)
{
if (condition == null)
throw new ArgumentNullException("condition");
@ -357,9 +491,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -357,9 +491,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
public override ResolveResult Resolve(CSharpResolver resolver)
{
return resolver.ResolveConditional(
Resolve(condition, resolver),
Resolve(trueExpr, resolver),
Resolve(falseExpr, resolver)
condition.Resolve(resolver),
trueExpr.Resolve(resolver),
falseExpr.Resolve(resolver)
);
}

49
ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// 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 ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Converts a type by replacing all type definitions with the equivalent definitions in the new context.
/// </summary>
sealed class MapTypeIntoNewContext : TypeVisitor
{
readonly ITypeResolveContext context;
public MapTypeIntoNewContext(ITypeResolveContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
if (type.DeclaringTypeDefinition != null) {
ITypeDefinition decl = type.DeclaringTypeDefinition.AcceptVisitor(this) as ITypeDefinition;
if (decl != null) {
foreach (ITypeDefinition c in decl.InnerClasses) {
if (c.Name == type.Name && c.TypeParameterCount == type.TypeParameterCount)
return c;
}
}
return type;
} else {
return context.GetClass(type.Namespace, type.Name, type.TypeParameterCount, StringComparer.Ordinal) ?? type;
}
}
public override IType VisitTypeParameter(ITypeParameter type)
{
// TODO: how to map type parameters?
// It might have constraints, and those constraints might be mutually recursive.
// Maybe reintroduce ITypeParameter.Owner?
throw new NotImplementedException();
}
}
}

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

@ -57,11 +57,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -57,11 +57,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context)
{
// TODO: use resolve context for original project, if possible
return DoResolve(context) as NamespaceResolveResult;
}
public IType Resolve(ITypeResolveContext context)
{
// TODO: use resolve context for original project, if possible; then map the result type into the new context
TypeResolveResult rr = DoResolve(context) as TypeResolveResult;
return rr != null ? rr.Type : SharedTypes.UnknownType;
}

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

@ -52,11 +52,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -52,11 +52,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context)
{
// TODO: use resolve context for original project, if possible
return DoResolve(context) as NamespaceResolveResult;
}
public IType Resolve(ITypeResolveContext context)
{
// TODO: use resolve context for original project, if possible; then map the result type into the new context
TypeResolveResult rr = DoResolve(context) as TypeResolveResult;
return rr != null ? rr.Type : SharedTypes.UnknownType;
}

3
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
<Optimize>False</Optimize>
<DefineConstants>DEBUG;TRACE;FULL_AST</DefineConstants>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<OutputPath>bin\Release\</OutputPath>
@ -41,7 +42,6 @@ @@ -41,7 +42,6 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<WarningLevel>4</WarningLevel>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<WarningLevel>4</WarningLevel>
@ -99,6 +99,7 @@ @@ -99,6 +99,7 @@
<Compile Include="CSharp\Ast\MemberType.cs" />
<Compile Include="CSharp\Resolver\CSharpAttribute.cs" />
<Compile Include="CSharp\Resolver\ConstantValues.cs" />
<Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" />
<Compile Include="PatternMatching\BacktrackingInfo.cs" />
<Compile Include="PatternMatching\Choice.cs" />
<Compile Include="PatternMatching\AnyNode.cs" />

2
ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
IList<IAttribute> Attributes { get; }
/// <summary>
/// Gets the contraints of this type parameter.
/// Gets the constraints of this type parameter.
/// </summary>
IList<ITypeReference> Constraints { get; }

Loading…
Cancel
Save