diff --git a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs index fd9bfab206..0fe039f8c1 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs @@ -17,6 +17,7 @@ namespace ICSharpCode.NRefactory.CSharp readonly string fileName; readonly UsingScope rootUsingScope; IList topLevelTypeDefinitions = new List(); + IList assemblyAttributes = new List(); IList usingScopes = new List(); protected override void FreezeInternal() @@ -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 get { return topLevelTypeDefinitions; } } + public IList AssemblyAttributes { + get { return assemblyAttributes; } + } + public UsingScope GetUsingScope(AstLocation location) { foreach (UsingScope scope in usingScopes) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs index d650180769..c632197124 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs @@ -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 } #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 } #endregion - // TODO: assembly attributes - #region Type Definitions DefaultTypeDefinition CreateTypeDefinition(string name) { @@ -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 outputList, IEnumerable attributes) { foreach (AttributeSection section in attributes) { @@ -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 throw new NotImplementedException(); } - sealed class ConstantValueBuilder : DepthFirstAstVisitor + sealed class ConstantValueBuilder : DepthFirstAstVisitor { 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 ConvertTypeArguments(AstNodeCollection types) @@ -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 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 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 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 diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs index 3e4e91b0ab..87f732c222 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs @@ -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 // 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); + + /// + /// Gets whether the returned value depends on the expression's context. + /// + 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 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 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 { 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 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 public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning { ITypeReference targetType; - IConstantValue targetExpression; + ConstantExpression targetExpression; string memberName; IList typeArguments; @@ -156,7 +257,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues this.typeArguments = typeArguments; } - public ConstantMemberReference(IConstantValue targetExpression, string memberName, IList typeArguments = null) + public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList typeArguments = null) { if (targetExpression == null) throw new ArgumentNullException("targetExpression"); @@ -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 } } + 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 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 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 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 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 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 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 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) ); } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs new file mode 100644 index 0000000000..026ff6bf99 --- /dev/null +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs @@ -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 +{ + /// + /// Converts a type by replacing all type definitions with the equivalent definitions in the new context. + /// + 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(); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs index 39c094f6ca..c6c9e00a43 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -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; } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs index 899266e131..12699dd1c0 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -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; } diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index e8c03d52ba..4ca65e7f72 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -31,6 +31,7 @@ False DEBUG;TRACE;FULL_AST False + true bin\Release\ @@ -41,7 +42,6 @@ 4 - true 4 @@ -99,6 +99,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index 301eb27f27..f9a0cc3cd5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IList Attributes { get; } /// - /// Gets the contraints of this type parameter. + /// Gets the constraints of this type parameter. /// IList Constraints { get; }