Browse Source

Resolver: array create expressions

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
f79b0a77f3
  1. 14
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs
  2. 67
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  3. 2
      ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj
  4. 4
      ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs
  5. 17
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  6. 162
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  7. 20
      ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs
  8. 78
      ICSharpCode.NRefactory/CSharp/Resolver/Log.cs
  9. 84
      ICSharpCode.NRefactory/CSharp/Resolver/OperatorResolveResult.cs
  10. 9
      ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs
  11. 80
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  12. 1
      ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

14
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreationTests.cs → ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture]
[Ignore("Parser produces incorrect positions")]
public class ArrayCreationTests : ResolverTestBase
public class ArrayCreateTests : ResolverTestBase
{
[Test]
public void SimpleArrayCreation()
@ -100,5 +100,17 @@ class A { @@ -100,5 +100,17 @@ class A {
var result = Resolve(program);
Assert.AreEqual("System.Int32[]", result.Type.ReflectionName);
}
[Test]
public void ArrayInitializerExpression2D()
{
string program = @"using System.Collections.Generic;
class A {
int[,] a = ${ { 1 }, { 2 } }$;
}
";
var result = Resolve(program);
Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName);
}
}
}

67
ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs

@ -74,7 +74,7 @@ class SomeClass<T> { @@ -74,7 +74,7 @@ class SomeClass<T> {
#region Lambda In Initializer
[Test]
public void LambdaInCollectionInitializerTest1()
public void LambdaInArrayInitializer1()
{
string program = @"using System;
class TestClass {
@ -90,12 +90,12 @@ class TestClass { @@ -90,12 +90,12 @@ class TestClass {
}
[Test]
public void LambdaInCollectionInitializerTest2()
public void LambdaInArrayInitializer2()
{
string program = @"using System; using System.Collections.Generic;
string program = @"using System;
class TestClass {
static void Main() {
a = new List<Converter<int, string>> {
a = new Converter<int, string>[] {
i => $i$.ToString()
};
}
@ -106,15 +106,13 @@ class TestClass { @@ -106,15 +106,13 @@ class TestClass {
}
[Test]
public void LambdaInCollectionInitializerTest3()
public void LambdaInArrayInitializer3()
{
string program = @"using System;
class TestClass {
static void Main() {
a = new Converter<int, string>[] {
i => $i$.ToString()
};
}
Converter<int, string>[] field = new Converter<int, string>[] {
i => $i$.ToString()
};
}
";
var lrr = Resolve<LocalResolveResult>(program);
@ -122,11 +120,11 @@ class TestClass { @@ -122,11 +120,11 @@ class TestClass {
}
[Test]
public void LambdaInCollectionInitializerTest4()
public void LambdaInArrayInitializer4()
{
string program = @"using System;
class TestClass {
Converter<int, string>[] field = new Converter<int, string>[] {
Converter<int, string>[] field = {
i => $i$.ToString()
};
}
@ -136,13 +134,48 @@ class TestClass { @@ -136,13 +134,48 @@ class TestClass {
}
[Test]
public void LambdaInCollectionInitializerTest5()
public void LambdaInCollectionInitializer1()
{
string program = @"using System;
string program = @"using System; using System.Collections.Generic;
class TestClass {
Converter<int, string>[] field = {
i => $i$.ToString()
};
static void Main() {
a = new List<Converter<int, string>> {
i => $i$.ToString()
};
}
}
";
var lrr = Resolve<LocalResolveResult>(program);
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
}
[Test]
public void LambdaInCollectionInitializer2()
{
string program = @"using System; using System.Collections.Generic;
class TestClass {
static void Main() {
a = new Dictionary<Func<char, string>, Converter<int, string>> {
{ i => $i$.ToString(), i => i.ToString() }
};
}
}
";
var lrr = Resolve<LocalResolveResult>(program);
Assert.AreEqual("System.Char", lrr.Type.ReflectionName);
}
[Test]
public void LambdaInCollectionInitializer3()
{
string program = @"using System; using System.Collections.Generic;
class TestClass {
static void Main() {
a = new Dictionary<Func<char, string>, Converter<int, string>> {
{ i => i.ToString(), $i$ => i.ToString() }
};
}
}
";
var lrr = Resolve<LocalResolveResult>(program);

2
ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj

@ -119,7 +119,7 @@ @@ -119,7 +119,7 @@
<Compile Include="CSharp\Parser\GeneralScope\AttributeSectionTests.cs" />
<Compile Include="CSharp\Parser\ParseUtil.cs" />
<Compile Include="CSharp\Refactoring\TypeSystemAstBuilderTests.cs" />
<Compile Include="CSharp\Resolver\ArrayCreationTests.cs" />
<Compile Include="CSharp\Resolver\ArrayCreateTests.cs" />
<Compile Include="CSharp\Resolver\AttributeTests.cs" />
<Compile Include="CSharp\Resolver\BinaryOperatorTests.cs" />
<Compile Include="CSharp\Resolver\CastTests.cs" />

4
ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs

@ -445,9 +445,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -445,9 +445,9 @@ namespace ICSharpCode.NRefactory.CSharp
return VisitChildren (anonymousTypeCreateExpression, data);
}
public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, T data)
public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, T data)
{
return VisitChildren (arrayObjectCreateExpression, data);
return VisitChildren (arrayCreateExpression, data);
}
public virtual S VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data)

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

@ -995,15 +995,20 @@ namespace ICSharpCode.NRefactory.CSharp @@ -995,15 +995,20 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression, object data)
public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
{
var initializer = arrayObjectCreateExpression.Initializer;
if (isAttributeArgument && !initializer.IsNull) {
var initializer = arrayCreateExpression.Initializer;
// Attributes only allow one-dimensional arrays
if (isAttributeArgument && !initializer.IsNull && arrayCreateExpression.Arguments.Count < 2) {
ITypeReference type;
if (arrayObjectCreateExpression.Type.IsNull)
if (arrayCreateExpression.Type.IsNull) {
type = null;
else
type = convertVisitor.ConvertType(arrayObjectCreateExpression.Type);
} else {
type = convertVisitor.ConvertType(arrayCreateExpression.Type);
foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) {
type = ArrayTypeReference.Create(type, spec.Dimensions);
}
}
ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count];
int pos = 0;
foreach (Expression expr in initializer.Elements) {

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

@ -726,8 +726,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -726,8 +726,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
cancellationToken.ThrowIfCancellationRequested();
if (SharedTypes.Dynamic.Equals(lhs.Type) || SharedTypes.Dynamic.Equals(rhs.Type)) {
lhs = Convert(lhs, SharedTypes.Dynamic, conversions.ImplicitConversion(lhs, SharedTypes.Dynamic));
rhs = Convert(rhs, SharedTypes.Dynamic, conversions.ImplicitConversion(rhs, SharedTypes.Dynamic));
lhs = Convert(lhs, SharedTypes.Dynamic);
rhs = Convert(rhs, SharedTypes.Dynamic);
return new BinaryOperatorResolveResult(SharedTypes.Dynamic, lhs, op, rhs);
}
@ -1744,6 +1744,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1744,6 +1744,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
ResolveResult Convert(ResolveResult rr, IType targetType)
{
return Convert(rr, targetType, conversions.ImplicitConversion(rr, targetType));
}
ResolveResult Convert(ResolveResult rr, ITypeReference targetType, Conversion c)
{
if (c == Conversion.IdentityConversion)
@ -2155,6 +2160,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2155,6 +2160,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region ResolveInvocation
/// <summary>
/// Resolves an invocation.
/// </summary>
/// <param name="target">The target of the invocation. Usually a MethodGroupResolveResult.</param>
/// <param name="arguments">
/// Arguments passed to the method.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
/// <param name="argumentNames">
/// The argument names. Pass the null string for positional arguments.
/// </param>
/// <returns>InvocationResolveResult or UnknownMethodResolveResult</returns>
public ResolveResult ResolveInvocation(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null)
{
// C# 4.0 spec: §7.6.5
@ -2274,6 +2291,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2274,6 +2291,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#endregion
#region ResolveIndexer
/// <summary>
/// Resolves an indexer access.
/// </summary>
/// <param name="target">Target expression.</param>
/// <param name="arguments">
/// Arguments passed to the indexer.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
/// <param name="argumentNames">
/// The argument names. Pass the null string for positional arguments.
/// </param>
/// <returns>ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult</returns>
public ResolveResult ResolveIndexer(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null)
{
cancellationToken.ThrowIfCancellationRequested();
@ -2281,24 +2310,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2281,24 +2310,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
switch (target.Type.Kind) {
case TypeKind.Dynamic:
for (int i = 0; i < arguments.Length; i++) {
arguments[i] = Convert(arguments[i], SharedTypes.Dynamic,
conversions.ImplicitConversion(arguments[i], SharedTypes.Dynamic));
arguments[i] = Convert(arguments[i], SharedTypes.Dynamic);
}
return new ArrayAccessResolveResult(SharedTypes.Dynamic, target, arguments);
case TypeKind.Array:
case TypeKind.Pointer:
// §7.6.6.1 Array access / §18.5.3 Pointer element access
for (int i = 0; i < arguments.Length; i++) {
if (!(TryConvert(ref arguments[i], KnownTypeReference.Int32.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.UInt32.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.Int64.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.UInt64.Resolve(context))))
{
// conversion failed
arguments[i] = Convert(arguments[i], KnownTypeReference.Int32, Conversion.None);
}
}
AdjustArrayAccessArguments(arguments);
return new ArrayAccessResolveResult(((TypeWithElementType)target.Type).ElementType, target, arguments);
}
@ -2318,9 +2337,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2318,9 +2337,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return ErrorResult;
}
}
/// <summary>
/// Converts all arguments to int,uint,long or ulong.
/// </summary>
void AdjustArrayAccessArguments(ResolveResult[] arguments)
{
for (int i = 0; i < arguments.Length; i++) {
if (!(TryConvert(ref arguments[i], KnownTypeReference.Int32.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.UInt32.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.Int64.Resolve(context)) ||
TryConvert(ref arguments[i], KnownTypeReference.UInt64.Resolve(context))))
{
// conversion failed
arguments[i] = Convert(arguments[i], KnownTypeReference.Int32, Conversion.None);
}
}
}
#endregion
#region ResolveObjectCreation
/// <summary>
/// Resolves an object creation.
/// </summary>
/// <param name="type">Type of the object to create.</param>
/// <param name="arguments">
/// Arguments passed to the constructor.
/// The resolver may mutate this array to wrap elements in <see cref="ConversionResolveResult"/>s!
/// </param>
/// <param name="argumentNames">
/// The argument names. Pass the null string for positional arguments.
/// </param>
/// <returns>InvocationResolveResult or ErrorResolveResult</returns>
public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null)
{
cancellationToken.ThrowIfCancellationRequested();
@ -2519,53 +2567,51 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2519,53 +2567,51 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
#endregion
}
/// <summary>
/// Resolver logging helper.
/// Wraps System.Diagnostics.Debug so that resolver-specific logging can be enabled/disabled on demand.
/// (it's a huge amount of debug spew and slows down the resolver quite a bit)
/// </summary>
static class Log
{
[Conditional("DEBUG")]
internal static void WriteLine(string text)
{
Debug.WriteLine(text);
}
[Conditional("DEBUG")]
internal static void WriteLine(string format, params object[] args)
{
Debug.WriteLine(format, args);
}
[Conditional("DEBUG")]
internal static void WriteCollection<T>(string text, IEnumerable<T> lines)
{
#if DEBUG
T[] arr = lines.ToArray();
if (arr.Length == 0) {
Debug.WriteLine(text + "<empty collection>");
} else {
Debug.WriteLine(text + (arr[0] != null ? arr[0].ToString() : "<null>"));
for (int i = 1; i < arr.Length; i++) {
Debug.WriteLine(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "<null>"));
#region ResolveArrayCreation
/// <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="dimensions">
/// The number of array dimensions.
/// </param>
/// <param name="sizeArguments">
/// The size arguments. May be null if no explicit size was given.
/// 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>
/// <param name="allowArrayConstants">
/// Specifies whether to allow treating single-dimensional arrays like compile-time constants.
/// This is used for attribute arguments.
/// </param>
public ResolveResult ResolveArrayCreation(IType elementType, int dimensions = 1, ResolveResult[] sizeArguments = null, ResolveResult[] initializerElements = null, bool allowArrayConstants = false)
{
if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length))
throw new ArgumentException("dimensions and sizeArguments.Length don't match");
if (elementType == null) {
TypeInference typeInference = new TypeInference(context, conversions);
bool success;
elementType = typeInference.GetBestCommonType(initializerElements, out success);
}
IType arrayType = new ArrayType(elementType, dimensions);
if (sizeArguments != null)
AdjustArrayAccessArguments(sizeArguments);
if (initializerElements != null) {
for (int i = 0; i < initializerElements.Length; i++) {
initializerElements[i] = Convert(initializerElements[i], elementType);
}
}
#endif
}
[Conditional("DEBUG")]
public static void Indent()
{
Debug.Indent();
}
[Conditional("DEBUG")]
public static void Unindent()
{
Debug.Unindent();
return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements, allowArrayConstants);
}
#endregion
}
}

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

@ -617,37 +617,45 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues @@ -617,37 +617,45 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues
public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning
{
// type may be null when the element is being inferred
ITypeReference type;
ITypeReference elementType;
IList<ConstantExpression> arrayElements;
public ConstantArrayCreation(ITypeReference type, IList<ConstantExpression> arrayElements)
{
if (arrayElements == null)
throw new ArgumentNullException("arrayElements");
this.type = type;
this.elementType = type;
this.arrayElements = arrayElements;
}
public override ResolveResult Resolve(CSharpResolver resolver)
{
throw new NotImplementedException();
ResolveResult[] elements = new ResolveResult[arrayElements.Count];
for (int i = 0; i < elements.Length; i++) {
elements[i] = arrayElements[i].Resolve(resolver);
}
if (elementType != null) {
return resolver.ResolveArrayCreation(elementType.Resolve(resolver.Context), 1, null, elements, true);
} else {
return resolver.ResolveArrayCreation(null, 1, null, elements, true);
}
}
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
type = provider.Intern(type);
elementType = provider.Intern(elementType);
arrayElements = provider.InternList(arrayElements);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return (type != null ? type.GetHashCode() : 0) ^ arrayElements.GetHashCode();
return (elementType != null ? elementType.GetHashCode() : 0) ^ arrayElements.GetHashCode();
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
ConstantArrayCreation cac = other as ConstantArrayCreation;
return cac != null && this.type == cac.type && this.arrayElements == cac.arrayElements;
return cac != null && this.elementType == cac.elementType && this.arrayElements == cac.arrayElements;
}
}
}

78
ICSharpCode.NRefactory/CSharp/Resolver/Log.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
// 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 System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
/// <summary>
/// Resolver logging helper.
/// Wraps System.Diagnostics.Debug so that resolver-specific logging can be enabled/disabled on demand.
/// (it's a huge amount of debug spew and slows down the resolver quite a bit)
/// </summary>
static class Log
{
[Conditional("DEBUG")]
internal static void WriteLine(string text)
{
Debug.WriteLine(text);
}
[Conditional("DEBUG")]
internal static void WriteLine(string format, params object[] args)
{
Debug.WriteLine(format, args);
}
[Conditional("DEBUG")]
internal static void WriteCollection<T>(string text, IEnumerable<T> lines)
{
#if DEBUG
T[] arr = lines.ToArray();
if (arr.Length == 0) {
Debug.WriteLine(text + "<empty collection>");
} else {
Debug.WriteLine(text + (arr[0] != null ? arr[0].ToString() : "<null>"));
for (int i = 1; i < arr.Length; i++) {
Debug.WriteLine(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "<null>"));
}
}
#endif
}
[Conditional("DEBUG")]
public static void Indent()
{
Debug.Indent();
}
[Conditional("DEBUG")]
public static void Unindent()
{
Debug.Unindent();
}
}
}

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

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
@ -127,4 +128,87 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -127,4 +128,87 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new [] { Array }.Concat(Indices);
}
}
/// <summary>
/// Resolve result representing an array creation.
/// </summary>
public class ArrayCreateResolveResult : ResolveResult
{
/// <summary>
/// Gets the size arguments.
/// </summary>
public readonly ResolveResult[] SizeArguments;
/// <summary>
/// Gets the initializer elements.
/// This field may be null if no initializer was specified.
/// </summary>
public readonly ResolveResult[] InitializerElements;
readonly object[] constantArray;
public ArrayCreateResolveResult(IType arrayType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements,
bool allowArrayConstants)
: base(arrayType)
{
this.SizeArguments = sizeArguments;
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()
{
if (SizeArguments != null && InitializerElements != null)
return SizeArguments.Concat(InitializerElements);
else
return SizeArguments ?? InitializerElements ?? Enumerable.Empty<ResolveResult>();
}
}
}

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

@ -89,7 +89,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -89,7 +89,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
this.Member = member;
this.IsExpandedForm = isExpanded;
this.Parameters = ((IParameterizedMember)member.MemberDefinition).Parameters;
if (this.IsGenericMethod) {
// For generic methods, go back to the original parameters
// (without any type parameter substitution, not even class type parameters)
// We'll re-substitute them as part of RunTypeInference().
this.Parameters = ((IParameterizedMember)member.MemberDefinition).Parameters;
} else {
this.Parameters = member.Parameters;
}
this.ParameterTypes = new IType[this.Parameters.Count];
}

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

@ -203,10 +203,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -203,10 +203,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return result;
}
ResolveResult[] Resolve(AstNodeCollection<Expression> expressions)
{
ResolveResult[] results = new ResolveResult[expressions.Count];
int pos = 0;
foreach (var node in expressions)
results[pos++] = Resolve(node);
return results;
}
void StoreState(AstNode node, CSharpResolver resolverState)
{
Debug.Assert(resolverState != null);
resolverBeforeDict.Add(node, resolverState);
// It's possible that we re-visit an expression that we scanned over earlier,
// so we might have to overwrite an existing state.
resolverBeforeDict[node] = resolverState;
}
void StoreResult(AstNode node, ResolveResult result)
@ -782,31 +793,34 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -782,31 +793,34 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (!resolverEnabled) {
return null;
}
IType arrType;
int dimensions = arrayCreateExpression.Arguments.Count;
ResolveResult[] sizeArguments;
if (dimensions == 0) {
dimensions = 1;
sizeArguments = null;
} else {
if (arrayCreateExpression.Arguments.All(e => e is EmptyExpression))
sizeArguments = null;
else
sizeArguments = Resolve(arrayCreateExpression.Arguments);
}
ResolveResult[] initializerElements;
if (arrayCreateExpression.Initializer.IsNull)
initializerElements = null;
else
initializerElements = Resolve(arrayCreateExpression.Initializer.Elements);
if (arrayCreateExpression.Type.IsNull) {
var elements = new List<ResolveResult>();
foreach (var init in arrayCreateExpression.Initializer.Elements) {
var rr = Resolve(init);
if (!rr.IsError)
elements.Add(rr);
}
TypeInference typeInference = new TypeInference(resolver.Context, new Conversions(resolver.Context));
bool success;
IType elementType = typeInference.GetBestCommonType(elements, out success);
arrType = new ArrayType(elementType, 1);
return resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElements);
} else {
arrType = ResolveType(arrayCreateExpression.Type);
IType elementType = ResolveType(arrayCreateExpression.Type);
foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) {
arrType = new ArrayType(arrType, spec.Dimensions);
}
// HACK: find a better way to represent this in the AST
if (arrayCreateExpression.Arguments.Count == 0) {
arrType = new ArrayType(arrType, 1);
} else {
arrType = new ArrayType(arrType, arrayCreateExpression.Arguments.Count);
elementType = new ArrayType(elementType, spec.Dimensions);
}
return resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElements);
}
return new ResolveResult (arrType);
}
public override ResolveResult VisitAsExpression(AsExpression asExpression, object data)
@ -925,6 +939,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -925,6 +939,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return null;
}
public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data)
{
// Usually, the parent expression takes care of handling NamedArgumentExpressions
// by calling GetArguments().
if (resolverEnabled) {
return Resolve(namedArgumentExpression.Expression);
} else {
Scan(namedArgumentExpression.Expression);
return null;
}
}
public override ResolveResult VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data)
{
if (resolverEnabled) {
@ -1728,7 +1754,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1728,7 +1754,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
while (undecidedLambdas.Count > 0) {
LambdaBase lambda = undecidedLambdas[0];
AstNode parent = lambda.LambdaExpression.Parent;
while (ActsAsParenthsizedExpression(parent))
while (ActsAsParenthesizedExpression(parent))
parent = parent.Parent;
CSharpResolver storedResolver;
if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
@ -1753,9 +1779,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1753,9 +1779,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets whether the node acts as a parenthesized expression,
/// that is, it directly returns
/// </summary>
static bool ActsAsParenthsizedExpression(AstNode node)
static bool ActsAsParenthesizedExpression(AstNode node)
{
return node is ParenthesizedExpression || node is CheckedExpression || node is UncheckedExpression;
return node is ParenthesizedExpression || node is CheckedExpression || node is UncheckedExpression
|| node is NamedArgumentExpression;
}
#endregion
@ -2314,11 +2341,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2314,11 +2341,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return errorResult;
}
public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data)
{
throw new NotImplementedException();
}
#region Token Nodes
public override ResolveResult VisitIdentifier(Identifier identifier, object data)
{

1
ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj

@ -103,6 +103,7 @@ @@ -103,6 +103,7 @@
<Compile Include="CSharp\Ast\MemberType.cs" />
<Compile Include="CSharp\Refactoring\TypeSystemAstBuilder.cs" />
<Compile Include="CSharp\Resolver\DetectSkippableNodesNavigator.cs" />
<Compile Include="CSharp\Resolver\Log.cs" />
<Compile Include="CSharp\Resolver\OperatorResolveResult.cs" />
<Compile Include="CSharp\Resolver\ConversionResolveResult.cs" />
<Compile Include="CSharp\Resolver\CSharpAttribute.cs" />

Loading…
Cancel
Save