Browse Source

Change IConstantValue API to use ResolveResult.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
611c310eb2
  1. 72
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  2. 8
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  3. 32
      ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs
  4. 47
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs
  5. 6
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  6. 120
      ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs
  7. 2
      ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs
  8. 51
      ICSharpCode.NRefactory/CSharp/Resolver/OperatorResolveResult.cs
  9. 27
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  10. 44
      ICSharpCode.NRefactory/CSharp/Resolver/TypeOfResolveResult.cs
  11. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj
  12. 5
      ICSharpCode.NRefactory/TypeSystem/IAttribute.cs
  13. 32
      ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs
  14. 9
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs
  15. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs
  16. 17
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs

72
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -20,6 +20,7 @@ using System;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.TypeSystem.TestCase; using ICSharpCode.NRefactory.TypeSystem.TestCase;
using NUnit.Framework; using NUnit.Framework;
@ -132,14 +133,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
var posArgs = typeTest.GetPositionalArguments(ctx); var posArgs = typeTest.GetPositionalArguments(ctx);
Assert.AreEqual(3, posArgs.Count); Assert.AreEqual(3, posArgs.Count);
// first argument is (int)42 // first argument is (int)42
Assert.AreEqual(42, (int)posArgs[0].GetValue(ctx)); Assert.AreEqual(42, (int)posArgs[0].ConstantValue);
// second argument is typeof(System.Action<>) // second argument is typeof(System.Action<>)
IType rt = (IType)posArgs[1].GetValue(ctx); TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[1];
Assert.IsFalse(rt is ParameterizedType); // rt must not be constructed - it's just an unbound type Assert.IsFalse(rt.ReferencedType is ParameterizedType); // rt must not be constructed - it's just an unbound type
Assert.AreEqual("System.Action", rt.FullName); Assert.AreEqual("System.Action", rt.ReferencedType.FullName);
Assert.AreEqual(1, rt.TypeParameterCount); Assert.AreEqual(1, rt.ReferencedType.TypeParameterCount);
// third argument is typeof(IDictionary<string, IList<TestAttribute>>) // third argument is typeof(IDictionary<string, IList<TestAttribute>>)
ParameterizedType crt = (ParameterizedType)posArgs[2].GetValue(ctx); rt = (TypeOfResolveResult)posArgs[2];
ParameterizedType crt = (ParameterizedType)rt.ReferencedType;
Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName);
Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName);
// ? for NUnit.TestAttribute (because that assembly isn't in ctx) // ? for NUnit.TestAttribute (because that assembly isn't in ctx)
@ -153,8 +155,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
var forwardAttribute = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeForwardedToAttribute).FullName); var forwardAttribute = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeForwardedToAttribute).FullName);
var posArgs = forwardAttribute.GetPositionalArguments(ctx); var posArgs = forwardAttribute.GetPositionalArguments(ctx);
Assert.AreEqual(1, posArgs.Count); Assert.AreEqual(1, posArgs.Count);
IType rt = (IType)posArgs[0].GetValue(ctx); TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[0];
Assert.AreEqual("System.Func`2", rt.ReflectionName); Assert.AreEqual("System.Func`2", rt.ReferencedType.ReflectionName);
} }
[Test] [Test]
@ -254,33 +256,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.IsTrue(f.IsStatic); Assert.IsTrue(f.IsStatic);
Assert.IsTrue(f.IsConst); Assert.IsTrue(f.IsConst);
Assert.AreEqual(Accessibility.Public, f.Accessibility); Assert.AreEqual(Accessibility.Public, f.Accessibility);
Assert.AreSame(e, f.ConstantValue.GetValueType(ctx)); Assert.AreSame(e, f.ConstantValue.Resolve(ctx).Type);
Assert.AreEqual(typeof(short), f.ConstantValue.GetValue(ctx).GetType()); Assert.AreEqual(typeof(short), f.ConstantValue.Resolve(ctx).ConstantValue.GetType());
} }
Assert.AreEqual("First", e.Fields[0].Name); Assert.AreEqual("First", e.Fields[0].Name);
Assert.AreEqual(0, e.Fields[0].ConstantValue.GetValue(ctx)); Assert.AreEqual(0, e.Fields[0].ConstantValue.Resolve(ctx).ConstantValue);
Assert.AreEqual("Second", e.Fields[1].Name); Assert.AreEqual("Second", e.Fields[1].Name);
Assert.AreSame(e, e.Fields[1].ConstantValue.GetValueType(ctx)); Assert.AreSame(e, e.Fields[1].ConstantValue.Resolve(ctx).Type);
Assert.AreEqual(1, e.Fields[1].ConstantValue.GetValue(ctx)); Assert.AreEqual(1, e.Fields[1].ConstantValue.Resolve(ctx).ConstantValue);
Assert.AreEqual("Flag1", e.Fields[2].Name); Assert.AreEqual("Flag1", e.Fields[2].Name);
Assert.AreEqual(0x10, e.Fields[2].ConstantValue.GetValue(ctx)); Assert.AreEqual(0x10, e.Fields[2].ConstantValue.Resolve(ctx).ConstantValue);
Assert.AreEqual("Flag2", e.Fields[3].Name); Assert.AreEqual("Flag2", e.Fields[3].Name);
Assert.AreEqual(0x20, e.Fields[3].ConstantValue.GetValue(ctx)); Assert.AreEqual(0x20, e.Fields[3].ConstantValue.Resolve(ctx).ConstantValue);
Assert.AreEqual("CombinedFlags", e.Fields[4].Name); Assert.AreEqual("CombinedFlags", e.Fields[4].Name);
Assert.AreEqual(0x30, e.Fields[4].ConstantValue.GetValue(ctx)); Assert.AreEqual(0x30, e.Fields[4].ConstantValue.Resolve(ctx).ConstantValue);
}
[Test]
public void GetNestedTypesFromGenericClassTest()
{
ITypeDefinition b = ctx.GetTypeDefinition(typeof(Base<>));
// Base.GetNestedTypes() = { Base`1+Nested`1[`0, unbound] }
} }
[Test] [Test]
@ -336,20 +330,20 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName);
IConstantValue arg1 = attr.GetPositionalArguments(ctx).Single(); ResolveResult arg1 = attr.GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.GetValueType(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName);
Assert.AreEqual((int)LayoutKind.Explicit, arg1.GetValue(ctx)); Assert.AreEqual((int)LayoutKind.Explicit, arg1.ConstantValue);
var namedArgs = attr.GetNamedArguments(ctx); var namedArgs = attr.GetNamedArguments(ctx);
var arg2 = namedArgs[0]; var arg2 = namedArgs[0];
Assert.AreEqual("CharSet", arg2.Key); Assert.AreEqual("CharSet", arg2.Key);
Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.GetValueType(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.Type.FullName);
Assert.AreEqual((int)CharSet.Unicode, arg2.Value.GetValue(ctx)); Assert.AreEqual((int)CharSet.Unicode, arg2.Value.ConstantValue);
var arg3 = namedArgs[1]; var arg3 = namedArgs[1];
Assert.AreEqual("Pack", arg3.Key); Assert.AreEqual("Pack", arg3.Key);
Assert.AreEqual("System.Int32", arg3.Value.GetValueType(ctx).FullName); Assert.AreEqual("System.Int32", arg3.Value.Type.FullName);
Assert.AreEqual(8, arg3.Value.GetValue(ctx)); Assert.AreEqual(8, arg3.Value.ConstantValue);
} }
[Test] [Test]
@ -357,15 +351,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
IConstantValue arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); ResolveResult arg = field.Attributes.Single().GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(0, arg.GetValue(ctx)); Assert.AreEqual(0, arg.ConstantValue);
field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName);
arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); arg = field.Attributes.Single().GetPositionalArguments(ctx).Single();
Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(100, arg.GetValue(ctx)); Assert.AreEqual(100, arg.ConstantValue);
} }
[Test] [Test]
@ -374,8 +368,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute dllImport = method.Attributes.Single(); IAttribute dllImport = method.Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName); Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName);
Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].GetValue(ctx)); Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].ConstantValue);
Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.GetValue(ctx)); Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.ConstantValue);
} }
[Test] [Test]
@ -394,7 +388,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
{ {
IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute marshalAs = method.ReturnTypeAttributes.Single(); IAttribute marshalAs = method.ReturnTypeAttributes.Single();
Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().GetValue(ctx)); Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().ConstantValue);
} }
[Test] [Test]

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

@ -765,12 +765,12 @@ namespace ICSharpCode.NRefactory.CSharp
namedCtorArguments = new List<KeyValuePair<string, IConstantValue>>(); namedCtorArguments = new List<KeyValuePair<string, IConstantValue>>();
namedCtorArguments.Add(new KeyValuePair<string, IConstantValue>(nae.Identifier, ConvertAttributeArgument(nae.Expression))); namedCtorArguments.Add(new KeyValuePair<string, IConstantValue>(nae.Identifier, ConvertAttributeArgument(nae.Expression)));
} else { } else {
AssignmentExpression ae = expr as AssignmentExpression; NamedExpression namedExpression = expr as NamedExpression;
if (ae != null && ae.Left is IdentifierExpression && ae.Operator == AssignmentOperatorType.Assign) { if (namedExpression != null) {
string name = ((IdentifierExpression)ae.Left).Identifier; string name = namedExpression.Identifier;
if (namedArguments == null) if (namedArguments == null)
namedArguments = new List<KeyValuePair<string, IConstantValue>>(); namedArguments = new List<KeyValuePair<string, IConstantValue>>();
namedArguments.Add(new KeyValuePair<string, IConstantValue>(name, ConvertAttributeArgument(ae.Right))); namedArguments.Add(new KeyValuePair<string, IConstantValue>(name, ConvertAttributeArgument(namedExpression.Expression)));
} else { } else {
if (positionalArguments == null) if (positionalArguments == null)
positionalArguments = new List<IConstantValue>(); positionalArguments = new List<IConstantValue>();

32
ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs

@ -335,17 +335,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring
{ {
if (constantValue == null) if (constantValue == null)
throw new ArgumentNullException("constantValue"); throw new ArgumentNullException("constantValue");
IType type = constantValue.GetValueType(context); return ConvertConstantValue(constantValue.Resolve(context));
object val = constantValue.GetValue(context); }
if (val == null) {
if (type.IsReferenceType(context) == true) Expression ConvertConstantValue(ResolveResult rr)
return new NullReferenceExpression(); {
else if (rr is TypeOfResolveResult) {
return new DefaultValueExpression(ConvertType(type)); return new TypeOfExpression(ConvertType(((TypeOfResolveResult)rr).Type));
} else if (type.Kind == TypeKind.Enum) { } else if (rr is ArrayCreateResolveResult) {
ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr;
AstType type = ConvertType(acrr.Type);
throw new NotImplementedException(); throw new NotImplementedException();
} else if (rr.IsCompileTimeConstant) {
object val = rr.ConstantValue;
if (val == null) {
if (rr.Type.IsReferenceType(context) == true)
return new NullReferenceExpression();
else
return new DefaultValueExpression(ConvertType(rr.Type));
} else if (rr.Type.Kind == TypeKind.Enum) {
throw new NotImplementedException();
} else {
return new PrimitiveExpression(val);
}
} else { } else {
return new PrimitiveExpression(val); return new EmptyExpression();
} }
} }
#endregion #endregion

47
ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs

@ -19,6 +19,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -70,14 +72,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (positionalArguments != null) { if (positionalArguments != null) {
while (i < positionalArguments.Count) { while (i < positionalArguments.Count) {
IConstantValue cv = positionalArguments[i]; IConstantValue cv = positionalArguments[i];
arguments[i] = new ConstantResolveResult(cv.GetValueType(context), cv.GetValue(context)); arguments[i] = cv.Resolve(context);
i++; i++;
} }
} }
if (namedCtorArguments != null) { if (namedCtorArguments != null) {
foreach (var pair in namedCtorArguments) { foreach (var pair in namedCtorArguments) {
argumentNames[i] = pair.Key; argumentNames[i] = pair.Key;
arguments[i] = new ConstantResolveResult(pair.Value.GetValueType(context), pair.Value.GetValue(context)); arguments[i] = pair.Value.Resolve(context);
i++; i++;
} }
} }
@ -85,17 +87,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return mrr != null ? mrr.Member as IMethod : null; return mrr != null ? mrr.Member as IMethod : null;
} }
public IList<IConstantValue> GetPositionalArguments(ITypeResolveContext context) public IList<ResolveResult> GetPositionalArguments(ITypeResolveContext context)
{ {
List<ResolveResult> result = new List<ResolveResult>();
if (positionalArguments != null) {
foreach (var arg in positionalArguments) {
result.Add(Resolve(arg, context));
}
}
if (namedCtorArguments == null || namedCtorArguments.Count == 0) { if (namedCtorArguments == null || namedCtorArguments.Count == 0) {
// no namedCtorArguments: just return the positionalArguments // no namedCtorArguments: just return the positionalArguments
if (positionalArguments != null) return result.AsReadOnly();
return new ReadOnlyCollection<IConstantValue>(positionalArguments);
else
return EmptyList<IConstantValue>.Instance;
} }
// we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments // we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments
List<IConstantValue> result = new List<IConstantValue>(this.positionalArguments);
IMethod method = ResolveConstructor(context); IMethod method = ResolveConstructor(context);
if (method != null) { if (method != null) {
for (int i = result.Count; i < method.Parameters.Count; i++) { for (int i = result.Count; i < method.Parameters.Count; i++) {
@ -103,25 +107,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool found = false; bool found = false;
foreach (var pair in namedCtorArguments) { foreach (var pair in namedCtorArguments) {
if (pair.Key == p.Name) { if (pair.Key == p.Name) {
result.Add(pair.Value); result.Add(Resolve(pair.Value, context));
found = true; found = true;
} }
} }
if (!found) { if (!found) {
// add the parameter's default value: // add the parameter's default value:
result.Add(p.DefaultValue ?? new SimpleConstantValue(p.Type, CSharpResolver.GetDefaultValue(p.Type.Resolve(context)))); if (p.DefaultValue != null) {
result.Add(Resolve(p.DefaultValue, context));
} else {
IType type = p.Type.Resolve(context);
result.Add(new ConstantResolveResult(type, CSharpResolver.GetDefaultValue(type)));
}
} }
} }
} }
return result.AsReadOnly(); return result.AsReadOnly();
} }
public IList<KeyValuePair<string, IConstantValue>> GetNamedArguments(ITypeResolveContext context) ResolveResult Resolve(IConstantValue constantValue, ITypeResolveContext context)
{ {
if (namedArguments != null) if (constantValue != null)
return new ReadOnlyCollection<KeyValuePair<string, IConstantValue>>(namedArguments); return constantValue.Resolve(context);
else else
return EmptyList<KeyValuePair<string, IConstantValue>>.Instance; return new ErrorResolveResult(SharedTypes.UnknownType);
}
public IList<KeyValuePair<string, ResolveResult>> GetNamedArguments(ITypeResolveContext context)
{
if (namedArguments != null) {
return namedArguments.Select(p => new KeyValuePair<string, ResolveResult>(p.Key, p.Value.Resolve(context)))
.ToList().AsReadOnly();
} else {
return EmptyList<KeyValuePair<string, ResolveResult>>.Instance;
}
} }
} }

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

@ -1960,7 +1960,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Look in local variables // Look in local variables
foreach (IVariable v in this.LocalVariables) { foreach (IVariable v in this.LocalVariables) {
if (v.Name == identifier) { if (v.Name == identifier) {
object constantValue = v.IsConst ? v.ConstantValue.GetValue(context) : null; object constantValue = v.IsConst ? v.ConstantValue.Resolve(context).ConstantValue : null;
return new LocalResolveResult(v, v.Type.Resolve(context), constantValue); return new LocalResolveResult(v, v.Type.Resolve(context), constantValue);
} }
} }
@ -2788,7 +2788,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Specifies whether to allow treating single-dimensional arrays like compile-time constants. /// Specifies whether to allow treating single-dimensional arrays like compile-time constants.
/// This is used for attribute arguments. /// This is used for attribute arguments.
/// </param> /// </param>
public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int dimensions = 1, ResolveResult[] sizeArguments = null, ResolveResult[] initializerElements = null, bool allowArrayConstants = false) public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int dimensions = 1, ResolveResult[] sizeArguments = null, ResolveResult[] initializerElements = null)
{ {
if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length)) if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length))
throw new ArgumentException("dimensions and sizeArguments.Length don't match"); throw new ArgumentException("dimensions and sizeArguments.Length don't match");
@ -2807,7 +2807,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
initializerElements[i] = Convert(initializerElements[i], elementType); initializerElements[i] = Convert(initializerElements[i], elementType);
} }
} }
return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements, allowArrayConstants); return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements);
} }
#endregion #endregion
} }

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

@ -57,72 +57,56 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
}; };
} }
sealed class ConstantValueResult public ResolveResult Resolve(ITypeResolveContext context)
{
public readonly IType ValueType;
public readonly object Value;
public ConstantValueResult(IType valueType, object value)
{
this.ValueType = valueType;
this.Value = value;
}
}
ConstantValueResult DoResolve(ITypeResolveContext context)
{ {
CacheManager cache = context.CacheManager; CacheManager cache = context.CacheManager;
if (cache != null) { if (cache != null) {
ConstantValueResult cachedResult = cache.GetShared(this) as ConstantValueResult; ResolveResult cachedResult = cache.GetShared(this) as ResolveResult;
if (cachedResult != null) if (cachedResult != null)
return cachedResult; return cachedResult;
} }
CSharpResolver resolver = CreateResolver(context); CSharpResolver resolver = CreateResolver(context);
ResolveResult rr = expression.Resolve(resolver); ResolveResult rr = expression.Resolve(resolver);
IType type = rr.Type; // Retrieve the equivalent type in the new resolve context.
object val = rr.ConstantValue; // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0.
if (resolver.Context != context) { // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0.
// Retrieve the equivalent type in the new resolve context. rr = MapToNewContext(rr, new MapTypeIntoNewContext(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.
type = type.AcceptVisitor(new MapTypeIntoNewContext(context));
// If 'val' is a type or an array containing types, we need to map it to the new context.
val = MapToNewContext(val, context);
}
ConstantValueResult result = new ConstantValueResult(type, val);
if (cache != null) if (cache != null)
cache.SetShared(this, result); cache.SetShared(this, rr);
return result; return rr;
} }
public IType GetValueType(ITypeResolveContext context) static ResolveResult MapToNewContext(ResolveResult rr, MapTypeIntoNewContext mapping)
{ {
return DoResolve(context).ValueType; if (rr is TypeOfResolveResult) {
} return new TypeOfResolveResult(
rr.Type.AcceptVisitor(mapping),
public object GetValue(ITypeResolveContext context) ((TypeOfResolveResult)rr).ReferencedType.AcceptVisitor(mapping));
{ } else if (rr is ArrayCreateResolveResult) {
return DoResolve(context).Value; ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr;
return new ArrayCreateResolveResult(
acrr.Type.AcceptVisitor(mapping),
MapToNewContext(acrr.SizeArguments, mapping),
MapToNewContext(acrr.InitializerElements, mapping));
} else if (rr.IsCompileTimeConstant) {
return new ConstantResolveResult(
rr.Type.AcceptVisitor(mapping),
rr.ConstantValue
);
} else {
return new ErrorResolveResult(rr.Type.AcceptVisitor(mapping));
}
} }
static object MapToNewContext(object val, ITypeResolveContext context) static ResolveResult[] MapToNewContext(ResolveResult[] input, MapTypeIntoNewContext mapping)
{ {
IType type = val as IType; if (input == null)
if (type != null) { return null;
return type.AcceptVisitor(new MapTypeIntoNewContext(context)); ResolveResult[] output = new ResolveResult[input.Length];
} for (int i = 0; i < input.Length; i++) {
object[] arr = val as object[]; output[i] = MapToNewContext(input[i], mapping);
if (arr != null) {
object[] newArr = new object[arr.Length];
bool modified = false;
for (int i = 0; i < arr.Length; i++) {
newArr[i] = MapToNewContext(arr[i], context);
modified |= arr[i] != newArr[i];
}
if (modified)
return newArr;
} }
return val; return output;
} }
void ISupportsInterning.PrepareForInterning(IInterningProvider provider) void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
@ -170,21 +154,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
} }
} }
public IType GetValueType(ITypeResolveContext context) public ResolveResult Resolve(ITypeResolveContext context)
{ {
return baseValue.GetValueType(context); ResolveResult rr = baseValue.Resolve(context);
} if (rr.IsCompileTimeConstant && rr.ConstantValue != null) {
object val = rr.ConstantValue;
public object GetValue(ITypeResolveContext context) TypeCode typeCode = Type.GetTypeCode(val.GetType());
{ if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64) {
object val = baseValue.GetValue(context); long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false);
if (val == null) object newVal = CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false);
return null; return new ConstantResolveResult(rr.Type, newVal);
TypeCode typeCode = Type.GetTypeCode(val.GetType()); }
if (!(typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64)) }
return null; return new ErrorResolveResult(rr.Type);
long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false);
return CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false);
} }
void ISupportsInterning.PrepareForInterning(IInterningProvider provider) void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
@ -672,9 +654,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
elements[i] = arrayElements[i].Resolve(resolver); elements[i] = arrayElements[i].Resolve(resolver);
} }
if (elementType != null) { if (elementType != null) {
return resolver.ResolveArrayCreation(elementType.Resolve(resolver.Context), 1, null, elements, true); return resolver.ResolveArrayCreation(elementType.Resolve(resolver.Context), 1, null, elements);
} else { } else {
return resolver.ResolveArrayCreation(null, 1, null, elements, true); return resolver.ResolveArrayCreation(null, 1, null, elements);
} }
} }

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

@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (field != null) { if (field != null) {
isConstant = field.IsConst; isConstant = field.IsConst;
if (isConstant) if (isConstant)
constantValue = field.ConstantValue.GetValue(context); constantValue = field.ConstantValue.Resolve(context).ConstantValue;
} }
} }

51
ICSharpCode.NRefactory/CSharp/Resolver/OperatorResolveResult.cs

@ -147,60 +147,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly object[] constantArray; readonly object[] constantArray;
public ArrayCreateResolveResult(IType arrayType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements, public ArrayCreateResolveResult(IType arrayType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements)
bool allowArrayConstants)
: base(arrayType) : base(arrayType)
{ {
this.SizeArguments = sizeArguments; this.SizeArguments = sizeArguments;
this.InitializerElements = initializerElements; this.InitializerElements = initializerElements;
if (allowArrayConstants) {
this.constantArray = MakeConstantArray(sizeArguments, initializerElements);
}
}
static object[] MakeConstantArray(ResolveResult[] sizeArguments, ResolveResult[] initializerElements)
{
if (initializerElements == null)
return null;
for (int i = 0; i < initializerElements.Length; i++) {
if (!initializerElements[i].IsCompileTimeConstant)
return null;
}
if (sizeArguments != null && sizeArguments.Length > 0) {
if (sizeArguments.Length > 1) {
// 2D-arrays can't be constant
return null;
}
if (!sizeArguments[0].IsCompileTimeConstant)
return null;
int expectedSize;
try {
expectedSize = (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, sizeArguments[0].ConstantValue, true);
} catch (InvalidCastException) {
return null;
} catch (OverflowException) {
return null;
}
if (expectedSize != initializerElements.Length)
return null;
}
object[] constants = new object[initializerElements.Length];
for (int i = 0; i < initializerElements.Length; i++) {
constants[i] = initializerElements[i].ConstantValue;
}
return constants;
}
public override object ConstantValue {
get { return constantArray; }
}
public override bool IsCompileTimeConstant {
get { return constantArray != null; }
} }
public override IEnumerable<ResolveResult> GetChildResults() public override IEnumerable<ResolveResult> GetChildResults()

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

@ -607,7 +607,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
string identifier = variableInitializer.Name; string identifier = variableInitializer.Name;
foreach (IVariable v in resolver.LocalVariables) { foreach (IVariable v in resolver.LocalVariables) {
if (v.Name == identifier) { if (v.Name == identifier) {
object constantValue = v.IsConst ? v.ConstantValue.GetValue(resolver.Context) : null; object constantValue = v.IsConst ? v.ConstantValue.Resolve(resolver.Context).ConstantValue : null;
result = new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue); result = new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue);
break; break;
} }
@ -936,18 +936,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
int dimensions = arrayCreateExpression.Arguments.Count; int dimensions = arrayCreateExpression.Arguments.Count;
ResolveResult[] sizeArguments; ResolveResult[] sizeArguments;
IEnumerable<ArraySpecifier> additionalArraySpecifiers;
if (dimensions == 0) { if (dimensions == 0) {
dimensions = 1; var firstSpecifier = arrayCreateExpression.AdditionalArraySpecifiers.FirstOrDefault();
sizeArguments = null; if (firstSpecifier != null) {
} else { dimensions = firstSpecifier.Dimensions;
if (arrayCreateExpression.Arguments.All(e => e is EmptyExpression)) { additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers.Skip(1);
sizeArguments = null;
} else { } else {
sizeArguments = new ResolveResult[dimensions]; dimensions = 0;
int pos = 0; additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
foreach (var node in arrayCreateExpression.Arguments)
sizeArguments[pos++] = Resolve(node);
} }
sizeArguments = null;
} else {
sizeArguments = new ResolveResult[dimensions];
int pos = 0;
foreach (var node in arrayCreateExpression.Arguments)
sizeArguments[pos++] = Resolve(node);
additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
} }
List<Expression> initializerElements; List<Expression> initializerElements;
@ -971,7 +976,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
acrr = resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElementResults); acrr = resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElementResults);
} else { } else {
IType elementType = ResolveType(arrayCreateExpression.Type); IType elementType = ResolveType(arrayCreateExpression.Type);
foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) { foreach (var spec in additionalArraySpecifiers.Reverse()) {
elementType = new ArrayType(elementType, spec.Dimensions); elementType = new ArrayType(elementType, spec.Dimensions);
} }
acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults); acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults);

44
ICSharpCode.NRefactory/CSharp/Resolver/TypeOfResolveResult.cs

@ -0,0 +1,44 @@
// 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 ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Represents the 'typeof'.
/// </summary>
public class TypeOfResolveResult : ResolveResult
{
readonly IType referencedType;
public TypeOfResolveResult(IType systemType, IType referencedType)
: base(systemType)
{
this.referencedType = referencedType;
}
/// <summary>
/// The type referenced by the 'typeof'.
/// </summary>
public IType ReferencedType {
get { return referencedType; }
}
}
}

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -115,6 +115,7 @@
<Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" /> <Compile Include="CSharp\Resolver\MapTypeIntoNewContext.cs" />
<Compile Include="CSharp\Resolver\ResolveAtLocation.cs" /> <Compile Include="CSharp\Resolver\ResolveAtLocation.cs" />
<Compile Include="CSharp\Resolver\SimpleNameLookupMode.cs" /> <Compile Include="CSharp\Resolver\SimpleNameLookupMode.cs" />
<Compile Include="CSharp\Resolver\TypeOfResolveResult.cs" />
<Compile Include="Documentation\IDStringProvider.cs" /> <Compile Include="Documentation\IDStringProvider.cs" />
<Compile Include="PatternMatching\BacktrackingInfo.cs" /> <Compile Include="PatternMatching\BacktrackingInfo.cs" />
<Compile Include="PatternMatching\Choice.cs" /> <Compile Include="PatternMatching\Choice.cs" />

5
ICSharpCode.NRefactory/TypeSystem/IAttribute.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.TypeSystem namespace ICSharpCode.NRefactory.TypeSystem
{ {
@ -44,12 +45,12 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Gets the positional arguments passed to the attribute. /// Gets the positional arguments passed to the attribute.
/// </summary> /// </summary>
IList<IConstantValue> GetPositionalArguments(ITypeResolveContext context); IList<ResolveResult> GetPositionalArguments(ITypeResolveContext context);
/// <summary> /// <summary>
/// Gets the named arguments passed to the attribute. /// Gets the named arguments passed to the attribute.
/// </summary> /// </summary>
IList<KeyValuePair<string, IConstantValue>> GetNamedArguments(ITypeResolveContext context); IList<KeyValuePair<string, ResolveResult>> GetNamedArguments(ITypeResolveContext context);
/// <summary> /// <summary>
/// Resolves the constructor method used for this attribute invocation. /// Resolves the constructor method used for this attribute invocation.

32
ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.TypeSystem namespace ICSharpCode.NRefactory.TypeSystem
{ {
@ -27,40 +28,21 @@ namespace ICSharpCode.NRefactory.TypeSystem
public interface IConstantValue : IFreezable public interface IConstantValue : IFreezable
{ {
/// <summary> /// <summary>
/// Gets the type of the constant value. /// Resolves the value of this constant.
/// </summary> /// </summary>
IType GetValueType(ITypeResolveContext context); /// <param name="context">Type resolve context where the constant value will be used.</param>
/// <returns>Resolve result representing the constant value.</returns>
/// <summary> ResolveResult Resolve(ITypeResolveContext context);
/// Gets the .NET value of the constant value.
/// Possible return values are:
/// - null
/// - primitive integers
/// - float/double
/// - bool
/// - string
/// - IType (for typeof-expressions)
/// and arrays of these values. Enum values are returned using the underlying primitive integer.
///
/// TODO: how do we represent errors (value not available?)
/// </summary>
object GetValue(ITypeResolveContext context);
} }
#if WITH_CONTRACTS #if WITH_CONTRACTS
[ContractClassFor(typeof(IConstantValue))] [ContractClassFor(typeof(IConstantValue))]
abstract class IConstantValueContract : IFreezableContract, IConstantValue abstract class IConstantValueContract : IFreezableContract, IConstantValue
{ {
IType IConstantValue.GetValueType(ITypeResolveContext context) ResolveResult IConstantValue.Resolve(ITypeResolveContext context)
{
Contract.Requires(context != null);
Contract.Ensures(Contract.Result<IType>() != null);
return null;
}
object IConstantValue.GetValue(ITypeResolveContext context)
{ {
Contract.Requires(context != null); Contract.Requires(context != null);
Contract.Ensures(Contract.Result<ResolveResult>() != null);
return null; return null;
} }
} }

9
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
@ -84,9 +85,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
IList<IConstantValue> IAttribute.GetPositionalArguments(ITypeResolveContext context) public IList<ResolveResult> GetPositionalArguments(ITypeResolveContext context)
{ {
return this.PositionalArguments; return this.PositionalArguments.Select(a => a.Resolve(context)).ToList();
} }
public IList<KeyValuePair<string, IConstantValue>> NamedArguments { public IList<KeyValuePair<string, IConstantValue>> NamedArguments {
@ -97,9 +98,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
IList<KeyValuePair<string, IConstantValue>> IAttribute.GetNamedArguments(ITypeResolveContext context) public IList<KeyValuePair<string, ResolveResult>> GetNamedArguments(ITypeResolveContext context)
{ {
return this.NamedArguments; return this.NamedArguments.Select(p => new KeyValuePair<string, ResolveResult>(p.Key, p.Value.Resolve(context))).ToList();
} }
public IMethod ResolveConstructor(ITypeResolveContext context) public IMethod ResolveConstructor(ITypeResolveContext context)

8
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs

@ -105,14 +105,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
} }
} }
public object GetDefaultValue(ITypeResolveContext context)
{
if (defaultValue == null)
throw new InvalidOperationException();
else
return defaultValue.GetValue(context);
}
public DomRegion Region { public DomRegion Region {
get { return region; } get { return region; }
set { set {

17
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using ICSharpCode.NRefactory.CSharp.Resolver;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
@ -37,17 +38,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.value = value; this.value = value;
} }
public IType GetValueType(ITypeResolveContext context) public ResolveResult Resolve(ITypeResolveContext context)
{ {
return type.Resolve(context); if (value is ITypeReference) {
} return new TypeOfResolveResult(type.Resolve(context), ((ITypeReference)value).Resolve(context));
} else {
public object GetValue(ITypeResolveContext context) return new ConstantResolveResult(type.Resolve(context), value);
{ }
if (value is ITypeReference)
return ((ITypeReference)value).Resolve(context);
else
return value;
} }
public override string ToString() public override string ToString()

Loading…
Cancel
Save