Browse Source

Always set ArrayCreateResolveResult.SizeArguments. Closes #111.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
80ba1b3dba
  1. 8
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs
  2. 42
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  3. 55
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  4. 5
      ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs
  5. 100
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs
  6. 2
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  7. 6
      ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs
  8. 4
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

8
ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs

@ -107,8 +107,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -107,8 +107,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
}
if (IsExpandedForm)
results[results.Length - 1] = new ArrayCreateResolveResult(Member.Parameters.Last().Type, null, paramsArguments.ToArray());
if (IsExpandedForm){
IType arrayType = Member.Parameters.Last().Type;
IType int32 = Member.Compilation.FindType(KnownTypeCode.Int32);
ResolveResult[] sizeArguments = { new ConstantResolveResult(int32, paramsArguments.Count) };
results[results.Length - 1] = new ArrayCreateResolveResult(arrayType, sizeArguments, paramsArguments);
}
for (int i = 0; i < results.Length; i++) {
if (results[i] == null) {

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

@ -2433,21 +2433,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2433,21 +2433,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// The array element type.
/// Pass null to resolve an implicitly-typed array creation.
/// </param>
/// <param name="dimensions">
/// The number of array dimensions.
/// <param name="sizeArguments">
/// The size arguments.
/// The length of this array will be used as the number of dimensions of the array type.
/// Negative values will be treated as errors.
/// </param>
/// <param name="initializerElements">
/// The initializer elements. May be null if no array initializer was specified.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int[] sizeArguments, ResolveResult[] initializerElements = null)
{
ResolveResult[] sizeArgResults = new ResolveResult[sizeArguments.Length];
for (int i = 0; i < sizeArguments.Length; i++) {
if (sizeArguments[i] < 0)
sizeArgResults[i] = ErrorResolveResult.UnknownError;
else
sizeArgResults[i] = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), sizeArguments[i]);
}
return ResolveArrayCreation(elementType, sizeArgResults, initializerElements);
}
/// <summary>
/// Resolves an array creation.
/// </summary>
/// <param name="elementType">
/// The array element type.
/// Pass null to resolve an implicitly-typed array creation.
/// </param>
/// <param name="sizeArguments">
/// The size arguments. May be null if no explicit size was given.
/// The size arguments.
/// The length of this array will be used as the number of dimensions of the array type.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
/// <param name="initializerElements">
/// The initializer elements. May be null if no array initializer was specified.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int dimensions = 1, ResolveResult[] sizeArguments = null, ResolveResult[] initializerElements = null)
public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements = null)
{
if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length))
throw new ArgumentException("dimensions and sizeArguments.Length don't match");
int dimensions = sizeArguments.Length;
if (dimensions == 0)
throw new ArgumentException("sizeArguments.Length must not be 0");
if (elementType == null) {
TypeInference typeInference = new TypeInference(compilation, conversions);
bool success;
@ -2455,8 +2482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2455,8 +2482,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
IType arrayType = new ArrayType(compilation, elementType, dimensions);
if (sizeArguments != null)
AdjustArrayAccessArguments(sizeArguments);
AdjustArrayAccessArguments(sizeArguments);
if (initializerElements != null) {
for (int i = 0; i < initializerElements.Length; i++) {

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

@ -735,12 +735,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -735,12 +735,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (aie != null && arrayType != null) {
StoreCurrentState(aie);
List<Expression> initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions, true);
int[] sizes = new int[arrayType.Dimensions];
UnpackArrayInitializer(initializerElements, sizes, aie, 0, true);
ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]);
}
var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, arrayType.Dimensions, null, initializerElementResults);
var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, sizes, initializerElementResults);
StoreResult(aie, arrayCreation);
ProcessConversionResults(initializerElements, arrayCreation.InitializerElements);
} else if (variableInitializer.Parent is FixedStatement) {
@ -1201,6 +1202,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1201,6 +1202,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult IAstVisitor<ResolveResult>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
{
int dimensions = arrayCreateExpression.Arguments.Count;
IEnumerable<Expression> sizeArgumentExpressions;
ResolveResult[] sizeArguments;
IEnumerable<ArraySpecifier> additionalArraySpecifiers;
if (dimensions == 0) {
@ -1213,24 +1215,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1213,24 +1215,29 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
}
sizeArguments = null;
sizeArgumentExpressions = null;
} else {
sizeArgumentExpressions = arrayCreateExpression.Arguments;
sizeArguments = new ResolveResult[dimensions];
int pos = 0;
foreach (var node in arrayCreateExpression.Arguments)
foreach (var node in sizeArgumentExpressions)
sizeArguments[pos++] = Resolve(node);
additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
}
int[] sizes;
List<Expression> initializerElements;
ResolveResult[] initializerElementResults;
if (arrayCreateExpression.Initializer.IsNull) {
sizes = null;
initializerElements = null;
initializerElementResults = null;
} else {
StoreCurrentState(arrayCreateExpression.Initializer);
initializerElements = new List<Expression>();
UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions, true);
sizes = new int[dimensions];
UnpackArrayInitializer(initializerElements, sizes, arrayCreateExpression.Initializer, 0, true);
initializerElementResults = new ResolveResult[initializerElements.Count];
for (int i = 0; i < initializerElementResults.Length; i++) {
initializerElementResults[i] = Resolve(initializerElements[i]);
@ -1238,39 +1245,59 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1238,39 +1245,59 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
StoreResult(arrayCreateExpression.Initializer, voidResult);
}
ArrayCreateResolveResult acrr;
IType elementType;
if (arrayCreateExpression.Type.IsNull) {
acrr = resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElementResults);
elementType = null;
} else {
IType elementType = ResolveType(arrayCreateExpression.Type);
elementType = ResolveType(arrayCreateExpression.Type);
foreach (var spec in additionalArraySpecifiers.Reverse()) {
elementType = new ArrayType(resolver.Compilation, elementType, spec.Dimensions);
}
acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults);
}
ArrayCreateResolveResult acrr;
if (sizeArguments != null) {
acrr = resolver.ResolveArrayCreation(elementType, sizeArguments, initializerElementResults);
} else if (sizes != null) {
acrr = resolver.ResolveArrayCreation(elementType, sizes, initializerElementResults);
} else {
// neither size arguments nor an initializer exist -> error
return new ErrorResolveResult(new ArrayType(resolver.Compilation, elementType ?? SpecialType.UnknownType, dimensions));
}
if (sizeArgumentExpressions != null)
ProcessConversionResults(sizeArgumentExpressions, acrr.SizeArguments);
if (acrr.InitializerElements != null)
ProcessConversionResults(initializerElements, acrr.InitializerElements);
return acrr;
}
void UnpackArrayInitializer(List<Expression> elementList, ArrayInitializerExpression initializer, int dimensions, bool resolveNestedInitializesToVoid)
void UnpackArrayInitializer(List<Expression> elementList, int[] sizes, ArrayInitializerExpression initializer, int dimension, bool resolveNestedInitializersToVoid)
{
Debug.Assert(dimensions >= 1);
if (dimensions > 1) {
Debug.Assert(dimension < sizes.Length);
int elementCount = 0;
if (dimension + 1 < sizes.Length) {
foreach (var node in initializer.Elements) {
ArrayInitializerExpression aie = node as ArrayInitializerExpression;
if (aie != null) {
if (resolveNestedInitializesToVoid) {
if (resolveNestedInitializersToVoid) {
StoreCurrentState(aie);
StoreResult(aie, voidResult);
}
UnpackArrayInitializer(elementList, aie, dimensions - 1, resolveNestedInitializesToVoid);
UnpackArrayInitializer(elementList, sizes, aie, dimension + 1, resolveNestedInitializersToVoid);
} else {
elementList.Add(node);
}
elementCount++;
}
} else {
foreach (var expr in initializer.Elements)
foreach (var expr in initializer.Elements) {
elementList.Add(expr);
elementCount++;
}
}
if (sizes[dimension] == 0) // 0 = uninitialized
sizes[dimension] = elementCount;
else if (sizes[dimension] != elementCount)
sizes[dimension] = -1; // -1 = error
}
ResolveResult IAstVisitor<ResolveResult>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)

5
ICSharpCode.NRefactory.CSharp/TypeSystem/ConstantValues.cs

@ -480,10 +480,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues @@ -480,10 +480,11 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem.ConstantValues
for (int i = 0; i < elements.Length; i++) {
elements[i] = arrayElements[i].Resolve(resolver);
}
int[] sizeArguments = { elements.Length };
if (elementType != null) {
return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), 1, null, elements);
return resolver.ResolveArrayCreation(elementType.Resolve(resolver.CurrentTypeResolveContext), sizeArguments, elements);
} else {
return resolver.ResolveArrayCreation(null, 1, null, elements);
return resolver.ResolveArrayCreation(null, sizeArguments, elements);
}
}
}

100
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using NUnit.Framework;
@ -111,5 +112,104 @@ class A { @@ -111,5 +112,104 @@ class A {
var result = Resolve(program);
Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName);
}
[Test]
public void SizeArguments2x3()
{
string program = @"using System.Collections.Generic;
class A {
int[,] a = ${ { 1, 2, 3 }, { 4, 5, 6 } }$;
}
";
var result = Resolve<ArrayCreateResolveResult>(program);
Assert.AreEqual(6, result.InitializerElements.Count);
Assert.AreEqual(2, result.SizeArguments.Count);
Assert.AreEqual(2, result.SizeArguments[0].ConstantValue);
Assert.AreEqual(3, result.SizeArguments[1].ConstantValue);
}
[Test]
public void SizeArguments3x2()
{
string program = @"using System.Collections.Generic;
class A {
int[,] a = $new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } }$;
}
";
var result = Resolve<ArrayCreateResolveResult>(program);
Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName);
Assert.AreEqual(6, result.InitializerElements.Count);
Assert.AreEqual(2, result.SizeArguments.Count);
Assert.AreEqual(3, result.SizeArguments[0].ConstantValue);
Assert.AreEqual(2, result.SizeArguments[1].ConstantValue);
}
[Test]
public void SizeArguments2xInvalid()
{
string program = @"using System.Collections.Generic;
class A {
int[,] a = ${ { 1, 2, 3 }, { 4, 5 } }$;
}
";
var result = Resolve<ArrayCreateResolveResult>(program);
Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName);
Assert.AreEqual(5, result.InitializerElements.Count);
Assert.AreEqual(2, result.SizeArguments.Count);
Assert.AreEqual(2, result.SizeArguments[0].ConstantValue);
Assert.IsTrue(result.SizeArguments[1].IsError);
}
[Test]
public void SizeArgumentsExplicitSizeInconsistentWithActualSize()
{
string program = @"using System.Collections.Generic;
class A {
int[,] a = $new int[5,6] { { 1, 2, 3 }, { 4, 5, 6 } }$;
}
";
var result = Resolve<ArrayCreateResolveResult>(program);
Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName);
Assert.AreEqual(6, result.InitializerElements.Count);
Assert.AreEqual(2, result.SizeArguments.Count);
Assert.AreEqual(5, result.SizeArguments[0].ConstantValue);
Assert.AreEqual(6, result.SizeArguments[1].ConstantValue);
}
[Test]
public void ArraySizeArgumentConversion()
{
string program = @"using System.Collections.Generic;
class A {
static byte b = 5;
int[] a = new int[$b$];
}
";
Assert.AreEqual(Conversion.ImplicitNumericConversion, GetConversion(program));
}
[Test]
public void ArrayInitializerConversion()
{
string program = @"using System.Collections.Generic;
class A {
static byte b = 5;
int[] a = new int[] { $b$ };
}
";
Assert.AreEqual(Conversion.ImplicitNumericConversion, GetConversion(program));
}
[Test]
public void ArrayInitializerConversion2()
{
string program = @"using System.Collections.Generic;
class A {
static byte b = 5;
int[] a = { $b$ };
}
";
Assert.AreEqual(Conversion.ImplicitNumericConversion, GetConversion(program));
}
}
}

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

@ -794,6 +794,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -794,6 +794,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute));
var arr = (ArrayCreateResolveResult)type.Attributes.Single().PositionalArguments.Single();
Assert.AreEqual(5, arr.InitializerElements.Count);
Assert.AreEqual(1, arr.SizeArguments.Count);
Assert.AreEqual(5, arr.SizeArguments[0].ConstantValue);
return arr.InitializerElements[index];
}

6
ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs

@ -43,16 +43,18 @@ namespace ICSharpCode.NRefactory.Semantics @@ -43,16 +43,18 @@ namespace ICSharpCode.NRefactory.Semantics
public ArrayCreateResolveResult(IType arrayType, IList<ResolveResult> sizeArguments, IList<ResolveResult> initializerElements)
: base(arrayType)
{
if (sizeArguments == null)
throw new ArgumentNullException("sizeArguments");
this.SizeArguments = sizeArguments;
this.InitializerElements = initializerElements;
}
public override IEnumerable<ResolveResult> GetChildResults()
{
if (SizeArguments != null && InitializerElements != null)
if (InitializerElements != null)
return SizeArguments.Concat(InitializerElements);
else
return SizeArguments ?? InitializerElements ?? EmptyList<ResolveResult>.Instance;
return SizeArguments;
}
}
}

4
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -1169,7 +1169,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1169,7 +1169,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (elements[i].IsError)
return ErrorResolveResult.UnknownError;
}
return new ArrayCreateResolveResult(argType, null, elements);
IType int32 = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Int32);
ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) };
return new ArrayCreateResolveResult(argType, sizeArgs, elements);
}
} else {
return ReadElem(argType);

Loading…
Cancel
Save