Browse Source

More work on lambda expressions.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
b52a348373
  1. 4
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs
  2. 6
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  3. 28
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  4. 8
      ICSharpCode.NRefactory/CSharp/Resolver/ConversionResolveResult.cs
  5. 68
      ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs
  6. 2
      ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs
  7. 497
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

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

@ -6,7 +6,7 @@ using NUnit.Framework; @@ -6,7 +6,7 @@ using NUnit.Framework;
namespace ICSharpCode.NRefactory.CSharp.Resolver
{
[TestFixture, Ignore("Lambdas not supported by resolver")]
[TestFixture]
public class LambdaTests : ResolverTestBase
{
[Test]
@ -176,7 +176,7 @@ static class TestClass { @@ -176,7 +176,7 @@ static class TestClass {
return i => $i$.ToString();
}
}";
var lrr = Resolve<LocalResolveResult>(program, "i");
var lrr = Resolve<LocalResolveResult>(program);
Assert.AreEqual("System.Int32", lrr.Type.ReflectionName);
}

6
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using ICSharpCode.NRefactory.CSharp.Parser;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -190,6 +190,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -190,6 +190,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
cu.AcceptVisitor(fnv, null);
Assert.IsNotNull(fnv.ResultNode, "Did not find DOM node at the specified location");
Debug.WriteLine(new string('=', 70));
Debug.WriteLine("Starting new resolver for " + fnv.ResultNode);
var navigator = new NodeListResolveVisitorNavigator(new[] { fnv.ResultNode });
ResolveResult rr;
using (var context = this.context.Synchronize()) {
@ -198,6 +201,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -198,6 +201,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
rr = rv.GetResolveResult(fnv.ResultNode);
}
Assert.IsNotNull(rr, "ResolveResult is null - did something go wrong while navigating to the target node?");
Debug.WriteLine("ResolveResult is " + rr);
return rr;
}

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

@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
static readonly ResolveResult NullResult = new ResolveResult(SharedTypes.Null);
readonly ITypeResolveContext context;
readonly Conversions conversions;
internal readonly Conversions conversions;
internal readonly CancellationToken cancellationToken;
#region Constructor
@ -195,6 +195,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -195,6 +195,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
localVariableStack = new LocalVariable(localVariableStack, null, DomRegion.Empty, null, null);
}
/// <summary>
/// Opens a new scope for local variables.
/// </summary>
public void PushLambdaBlock()
{
localVariableStack = new LambdaParameter(localVariableStack, null, DomRegion.Empty, null, false, false);
}
/// <summary>
/// Closes the current scope for local variables; removing all variables in that scope.
/// </summary>
@ -246,6 +254,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -246,6 +254,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
}
/// <summary>
/// Gets whether the resolver is currently within a lambda expression.
/// </summary>
public bool IsWithinLambdaExpression {
get {
for (LocalVariable v = localVariableStack; v != null; v = v.prev) {
if (v.name == null && v is LambdaParameter)
return true;
}
return false;
}
}
#endregion
#region Clone
@ -1764,10 +1785,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1764,10 +1785,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
Conversion c = conversions.ExplicitConversion(expression, targetType);
if (c)
if (c) {
return new ConversionResolveResult(targetType, expression, c);
else
} else {
return new ErrorResolveResult(targetType);
}
}
object CSharpPrimitiveCast(TypeCode targetType, object input)

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

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.NRefactory.CSharp.Resolver
@ -29,6 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -29,6 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion)
: base(targetType)
{
if (input == null)
throw new ArgumentNullException("input");
this.Input = input;
this.Conversion = conversion;
}
@ -36,5 +39,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -36,5 +39,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override bool IsError {
get { return !Conversion.IsValid; }
}
public override IEnumerable<ResolveResult> GetChildResults()
{
return new [] { Input };
}
}
}

68
ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs

@ -41,17 +41,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -41,17 +41,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public static readonly Conversion ImplicitDynamicConversion = new Conversion(8);
public static readonly Conversion ImplicitConstantExpressionConversion = new Conversion(9);
const int userDefinedImplicitConversionKind = 10;
public static readonly Conversion ImplicitPointerConversion = new Conversion(11);
const int anonymousFunctionConversionKind = 12;
const int methodGroupConversionKind = 13;
public static readonly Conversion ExplicitNumericConversion = new Conversion(14);
public static readonly Conversion ExplicitEnumerationConversion = new Conversion(15);
public static readonly Conversion ExplicitNullableConversion = new Conversion(16);
public static readonly Conversion ExplicitReferenceConversion = new Conversion(17);
public static readonly Conversion UnboxingConversion = new Conversion(18);
public static readonly Conversion ExplicitDynamicConversion = new Conversion(19);
public static readonly Conversion ExplicitPointerConversion = new Conversion(20);
const int userDefinedExplicitConversionKind = 21;
const int liftedUserDefinedImplicitConversionKind = 11;
public static readonly Conversion ImplicitPointerConversion = new Conversion(12);
const int anonymousFunctionConversionKind = 13;
const int methodGroupConversionKind = 14;
public static readonly Conversion ExplicitNumericConversion = new Conversion(15);
public static readonly Conversion ExplicitEnumerationConversion = new Conversion(16);
public static readonly Conversion ExplicitNullableConversion = new Conversion(17);
public static readonly Conversion ExplicitReferenceConversion = new Conversion(18);
public static readonly Conversion UnboxingConversion = new Conversion(19);
public static readonly Conversion ExplicitDynamicConversion = new Conversion(20);
public static readonly Conversion ExplicitPointerConversion = new Conversion(21);
const int userDefinedExplicitConversionKind = 22;
const int liftedUserDefinedExplicitConversionKind = 23;
const int lastImplicitConversion = methodGroupConversionKind;
static readonly string[] conversionNames = {
"None",
@ -65,6 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -65,6 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
"Implicit dynamic conversion",
"Implicit constant expression conversion",
"User-defined implicit conversion",
"Lifted user-defined implicit conversion",
"Implicit pointer conversion",
"Anonymous function conversion",
"Method group conversion",
@ -75,17 +80,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -75,17 +80,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
"Unboxing conversion",
"Explicit dynamic conversion",
"Explicit pointer conversion",
"User-defined explicit conversion"
"User-defined explicit conversion",
"Lifted user-defined explicit conversion"
};
public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod)
public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, bool isLifted)
{
return new Conversion(userDefinedImplicitConversionKind, operatorMethod);
return new Conversion(isLifted ? liftedUserDefinedImplicitConversionKind : userDefinedImplicitConversionKind, operatorMethod);
}
public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod)
public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, bool isLifted)
{
return new Conversion(userDefinedExplicitConversionKind, operatorMethod);
return new Conversion(isLifted ? liftedUserDefinedExplicitConversionKind : userDefinedExplicitConversionKind, operatorMethod);
}
public static Conversion MethodGroupConversion(IMethod chosenMethod)
@ -115,21 +121,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -115,21 +121,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// Gets whether this conversion is an implicit conversion.
/// </summary>
public bool IsImplicitConversion {
get { return kind >= IdentityConversion.kind && kind <= methodGroupConversionKind; }
get { return kind > 0 && kind <= lastImplicitConversion; }
}
/// <summary>
/// Gets whether this conversion is an explicit conversion.
/// </summary>
public bool IsExplicitConversion {
get { return kind > methodGroupConversionKind; }
get { return kind > lastImplicitConversion; }
}
/// <summary>
/// Gets whether this conversion is user-defined.
/// </summary>
public bool IsUserDefined {
get { return kind == userDefinedImplicitConversionKind || kind == userDefinedExplicitConversionKind; }
get {
switch (kind) {
case userDefinedImplicitConversionKind:
case liftedUserDefinedImplicitConversionKind:
case userDefinedExplicitConversionKind:
case liftedUserDefinedExplicitConversionKind:
return true;
default:
return false;
}
}
}
/// <summary>
/// Gets whether this conversion is a lifted version of a user-defined conversion operator.
/// </summary>
/// <remarks>Lifted versions of builtin conversion operators are classified as nullable-conversion</remarks>
public bool IsLifted {
get {
return kind == liftedUserDefinedImplicitConversionKind || kind == liftedUserDefinedExplicitConversionKind;
}
}
/// <summary>
@ -713,7 +739,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -713,7 +739,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var operators = GetApplicableConversionOperators(fromType, toType, false);
// TODO: Find most specific conversion
if (operators.Count > 0)
return Conversion.UserDefinedImplicitConversion(operators[0].Method);
return Conversion.UserDefinedImplicitConversion(operators[0].Method, operators[0].IsLifted);
else
return Conversion.None;
}
@ -724,7 +750,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -724,7 +750,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
var operators = GetApplicableConversionOperators(fromType, toType, true);
// TODO: Find most specific conversion
if (operators.Count > 0)
return Conversion.UserDefinedExplicitConversion(operators[0].Method);
return Conversion.UserDefinedExplicitConversion(operators[0].Method, operators[0].IsLifted);
else
return Conversion.None;
}

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

@ -650,7 +650,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -650,7 +650,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
parameterType = bestCandidate.ParameterTypes[parameterIndex];
else
parameterType = SharedTypes.UnknownType;
args[i] = new ConversionResolveResult(parameterType, args[i], conversions[i]);
args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]);
}
}
return args;

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

@ -52,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -52,7 +52,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </remarks>
public sealed class ResolveVisitor : DepthFirstAstVisitor<object, ResolveResult>
{
// The ResolveVisitor is also responsible for handling lambda expressions.
static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType);
readonly ResolveResult voidResult;
CSharpResolver resolver;
SimpleNameLookupMode currentTypeLookupMode = SimpleNameLookupMode.Type;
readonly ParsedFile parsedFile;
@ -61,7 +65,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -61,7 +65,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly IResolveVisitorNavigator navigator;
ResolveVisitorNavigationMode mode = ResolveVisitorNavigationMode.Scan;
List<ImplicitlyTypedLambda> outstandingLambdas;
List<LambdaBase> undecidedLambdas;
#region Constructor
/// <summary>
@ -88,11 +92,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -88,11 +92,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.resolver = resolver;
this.parsedFile = parsedFile;
this.navigator = navigator;
this.voidResult = new ResolveResult(KnownTypeReference.Void.Resolve(resolver.Context));
if (navigator == null)
mode = ResolveVisitorNavigationMode.ResolveAll;
}
#endregion
#region Properties
/// <summary>
/// Gets the TypeResolveContext used by this ResolveVisitor.
/// </summary>
@ -106,7 +112,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -106,7 +112,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public CancellationToken CancellationToken {
get { return resolver.cancellationToken; }
}
#endregion
#region ResetContext
/// <summary>
/// Resets the visitor to the stored position, runs the action, and then reverts the visitor to the previous position.
/// </summary>
@ -127,6 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -127,6 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.currentTypeLookupMode = oldTypeLookupMode;
}
}
#endregion
#region Scan / Resolve
bool resolverEnabled {
@ -150,6 +159,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -150,6 +159,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
break;
case ResolveVisitorNavigationMode.Scan:
if (node is LambdaExpression) {
// lambdas must be resolved so that they get stored in the resolver cache
goto case ResolveVisitorNavigationMode.Resolve;
}
resolverBeforeDict[node] = resolver.Clone();
node.AcceptVisitor(this, null);
break;
@ -176,6 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -176,6 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.cancellationToken.ThrowIfCancellationRequested();
resolverBeforeDict[node] = resolver.Clone();
result = resolveResultCache[node] = node.AcceptVisitor(this, null) ?? errorResult;
ProcessConversionsInResult(result);
}
if (wasScan)
mode = ResolveVisitorNavigationMode.Scan;
@ -196,6 +210,86 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -196,6 +210,86 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region Process Conversions
/// <summary>
/// Processes conversions within this resolve result.
/// </summary>
void ProcessConversionsInResult(ResolveResult result)
{
ConversionResolveResult crr = result as ConversionResolveResult;
if (crr != null) {
ProcessConversion(crr.Input, crr.Conversion, crr.Type);
} else {
foreach (ResolveResult argumentResult in result.GetChildResults()) {
crr = argumentResult as ConversionResolveResult;
if (crr != null)
ProcessConversion(crr.Input, crr.Conversion, crr.Type);
}
}
}
/// <summary>
/// Convert 'rr' to the target type.
/// </summary>
void ProcessConversion(ResolveResult rr, IType targetType)
{
ProcessConversion(rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType);
}
sealed class AnonymousFunctionConversionData
{
public readonly IType ReturnType;
public readonly ExplicitlyTypedLambda ExplicitlyTypedLambda;
public readonly LambdaTypeHypothesis Hypothesis;
public AnonymousFunctionConversionData(IType returnType, LambdaTypeHypothesis hypothesis)
{
if (returnType == null)
throw new ArgumentNullException("returnType");
this.ReturnType = returnType;
this.Hypothesis = hypothesis;
}
public AnonymousFunctionConversionData(IType returnType, ExplicitlyTypedLambda explicitlyTypedLambda)
{
if (returnType == null)
throw new ArgumentNullException("returnType");
this.ReturnType = returnType;
this.ExplicitlyTypedLambda = explicitlyTypedLambda;
}
}
/// <summary>
/// Convert 'rr' to the target type using the specified conversion.
/// </summary>
void ProcessConversion(ResolveResult rr, Conversion conversion, IType targetType)
{
if (conversion.IsAnonymousFunctionConversion) {
Debug.WriteLine("Processing conversion of anonymous function to " + targetType);
AnonymousFunctionConversionData data = conversion.data as AnonymousFunctionConversionData;
if (data != null) {
if (data.Hypothesis != null)
data.Hypothesis.MergeInto(this, data.ReturnType);
if (data.ExplicitlyTypedLambda != null)
data.ExplicitlyTypedLambda.ApplyReturnType(this, data.ReturnType);
}
}
}
/// <summary>
/// Resolves the specified expression and processes the conversion to targetType.
/// </summary>
void ResolveAndProcessConversion(Expression expr, IType targetType)
{
if (targetType.Kind == TypeKind.Unknown) {
// no need to resolve the expression right now
Scan(expr);
} else {
ProcessConversion(Resolve(expr), targetType);
}
}
#endregion
#region GetResolveResult
/// <summary>
/// Gets the cached resolve result for the specified node.
@ -203,7 +297,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -203,7 +297,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public ResolveResult GetResolveResult(AstNode node)
{
MergeOutstandingLambdas();
MergeUndecidedLambdas();
ResolveResult result;
if (resolveResultCache.TryGetValue(node, out result))
return result;
@ -217,7 +311,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -217,7 +311,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public CSharpResolver GetResolverStateBefore(AstNode node)
{
MergeOutstandingLambdas();
MergeUndecidedLambdas();
CSharpResolver r;
if (resolverBeforeDict.TryGetValue(node, out r))
return r;
@ -234,7 +328,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -234,7 +328,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (parsedFile != null)
resolver.UsingScope = parsedFile.RootUsingScope;
ScanChildren(unit);
return null;
return voidResult;
} finally {
resolver.UsingScope = previousUsingScope;
}
@ -343,35 +437,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -343,35 +437,41 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitVariableInitializer(VariableInitializer variableInitializer, object data)
{
ScanChildren(variableInitializer);
if (resolverEnabled) {
ResolveResult result = errorResult;
if (variableInitializer.Parent is FieldDeclaration) {
if (resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
if (resolver.CurrentMember != null) {
result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
}
} else {
string identifier = variableInitializer.Name;
foreach (IVariable v in resolver.LocalVariables) {
if (v.Name == identifier) {
object constantValue = v.IsConst ? v.ConstantValue.GetValue(resolver.Context) : null;
return new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue);
result = new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue);
break;
}
}
}
return errorResult;
ResolveAndProcessConversion(variableInitializer.Initializer, result.Type);
return result;
} else {
ScanChildren(variableInitializer);
return null;
}
}
public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data)
{
ScanChildren(fixedVariableInitializer);
if (resolverEnabled) {
if (resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
else
return errorResult;
ResolveResult result = errorResult;
if (resolver.CurrentMember != null) {
result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
}
ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context));
return result;
} else {
ScanChildren(fixedVariableInitializer);
return null;
}
}
@ -585,7 +685,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -585,7 +685,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
try {
resolver.CheckForOverflow = true;
ScanChildren(checkedStatement);
return null;
return voidResult;
} finally {
resolver.CheckForOverflow = oldCheckForOverflow;
}
@ -597,7 +697,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -597,7 +697,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
try {
resolver.CheckForOverflow = false;
ScanChildren(uncheckedStatement);
return null;
return voidResult;
} finally {
resolver.CheckForOverflow = oldCheckForOverflow;
}
@ -632,6 +732,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -632,6 +732,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data)
{
ScanChildren(anonymousTypeCreateExpression);
// 7.6.10.6 Anonymous object creation expressions
var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$");
anonymousType.IsSynthetic = true;
@ -647,7 +748,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -647,7 +748,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
};
anonymousType.Properties.Add(property);
}
return new TypeResolveResult(anonymousType);
return new ResolveResult(anonymousType);
}
public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
@ -698,7 +799,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -698,7 +799,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
if (resolverEnabled) {
ResolveResult left = Resolve(assignmentExpression.Left);
Scan(assignmentExpression.Right);
ResolveAndProcessConversion(assignmentExpression.Right, left.Type);
return new ResolveResult(left.Type);
} else {
ScanChildren(assignmentExpression);
@ -814,6 +915,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -814,6 +915,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
IType type = ResolveType(objectCreateExpression.Type);
string[] argumentNames;
ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames);
Scan(objectCreateExpression.Initializer); // TODO
return resolver.ResolveObjectCreation(type, arguments, argumentNames);
} else {
ScanChildren(objectCreateExpression);
@ -871,7 +975,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -871,7 +975,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data)
{
if (resolverEnabled) {
Scan(stackAllocExpression.CountExpression);
ResolveAndProcessConversion(stackAllocExpression.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context));
return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type)));
} else {
ScanChildren(stackAllocExpression);
@ -881,7 +985,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -881,7 +985,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
{
return resolver.ResolveThisReference();
if (resolverEnabled)
return resolver.ResolveThisReference();
else
return null;
}
public override ResolveResult VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data)
@ -1139,11 +1246,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1139,11 +1246,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override ResolveResult VisitLambdaExpression(LambdaExpression lambdaExpression, object data)
{
Debug.Assert(resolverEnabled);
bool isExplicitlyTyped = false;
bool isImplicitlyTyped = false;
foreach (var p in lambdaExpression.Parameters) {
isImplicitlyTyped |= p.Type.IsNull;
isExplicitlyTyped |= !p.Type.IsNull;
}
if (isExplicitlyTyped) {
if (isExplicitlyTyped || !isImplicitlyTyped) {
return HandleExplicitlyTypedLambda(
lambdaExpression.Parameters, lambdaExpression.Body,
isAnonymousMethod: false, hasParameterList: true);
@ -1158,7 +1268,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1158,7 +1268,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
AstNode body, bool isAnonymousMethod, bool hasParameterList)
{
List<IParameter> parameters = new List<IParameter>();
resolver.PushBlock();
resolver.PushLambdaBlock();
foreach (var pd in parameterDeclarations) {
ITypeReference type = MakeTypeReference(pd.Type);
if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out)
@ -1184,7 +1294,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1184,7 +1294,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return new DomRegion(parsedFile.FileName, node.StartLocation, node.EndLocation);
}
sealed class ExplicitlyTypedLambda : LambdaResolveResult
sealed class ExplicitlyTypedLambda : LambdaBase
{
readonly IList<IParameter> parameters;
readonly bool isAnonymousMethod;
@ -1198,6 +1308,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1198,6 +1308,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool isValidAsVoidMethod;
bool success;
// The actual return type is set when the lambda is applied by the conversion.
IType actualReturnType;
internal override bool IsUndecided {
get { return actualReturnType == null; }
}
internal override AstNode LambdaExpression {
get { return body.Parent; }
}
public ExplicitlyTypedLambda(IList<IParameter> parameters, bool isAnonymousMethod, CSharpResolver storedContext, ResolveVisitor visitor, AstNode body)
{
this.parameters = parameters;
@ -1205,6 +1326,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1205,6 +1326,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.storedContext = storedContext;
this.visitor = visitor;
this.body = body;
if (visitor.undecidedLambdas == null)
visitor.undecidedLambdas = new List<LambdaBase>();
visitor.undecidedLambdas.Add(lambda);
Debug.WriteLine("Added undecided explicitly-typed lambda: " + this.LambdaExpression);
}
public override IList<IParameter> Parameters {
@ -1216,15 +1342,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1216,15 +1342,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool Analyze()
{
// If it's not already analyzed
if (storedContext != null) {
if (inferredReturnType == null) {
Debug.WriteLine("Analyzing " + this.LambdaExpression);
Debug.Indent();
visitor.ResetContext(
storedContext,
delegate {
visitor.AnalyzeLambda(body, out success, out isValidAsVoidMethod, out inferredReturnType, out returnValues);
});
storedContext = null;
visitor = null;
body = null;
Debug.Unindent();
Debug.WriteLine("Finished analyzing " + this.LambdaExpression);
if (inferredReturnType == null)
throw new InvalidOperationException("AnalyzeLambda() didn't set inferredReturnType");
}
return success;
}
@ -1232,7 +1363,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1232,7 +1363,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions)
{
if (Analyze() && IsValidLambda(isValidAsVoidMethod, returnValues, returnType, conversions))
return Conversion.AnonymousFunctionConversion(null);
return Conversion.AnonymousFunctionConversion(new AnonymousFunctionConversionData(returnType, this));
else
return Conversion.None;
}
@ -1257,13 +1388,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1257,13 +1388,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public override string ToString()
{
return "[ExplicitlyTypedLambda " + body.Parent + "]";
return "[ExplicitlyTypedLambda " + this.LambdaExpression + "]";
}
public void ApplyReturnType(ResolveVisitor parentVisitor, IType returnType)
{
if (returnType == null)
throw new ArgumentNullException("returnType");
if (parentVisitor != visitor) {
// Explicitly typed lambdas do not use a nested visitor
throw new InvalidOperationException();
}
if (actualReturnType != null) {
if (actualReturnType.Equals(returnType))
return; // return type already set
throw new InvalidOperationException("inconsistent return types for explicitly-typed lambda");
}
actualReturnType = returnType;
visitor.undecidedLambdas.Remove(this);
Analyze();
Debug.WriteLine("Applying return type {0} to explicitly-typed lambda {1}", returnType, this.LambdaExpression);
foreach (var returnValue in returnValues) {
visitor.ProcessConversion(returnValue, returnType);
}
}
internal override void EnforceMerge(ResolveVisitor parentVisitor)
{
ApplyReturnType(parentVisitor, SharedTypes.UnknownType);
}
}
#endregion
#region Implicitly typed
sealed class ImplicitlyTypedLambda : LambdaResolveResult
sealed class ImplicitlyTypedLambda : LambdaBase
{
internal readonly LambdaExpression lambda;
readonly CSharpResolver storedContext;
@ -1271,19 +1429,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1271,19 +1429,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
readonly List<LambdaTypeHypothesis> hypotheses = new List<LambdaTypeHypothesis>();
readonly List<IParameter> parameters = new List<IParameter>();
public ImplicitlyTypedLambda(LambdaExpression lambda, ResolveVisitor visitor)
internal LambdaTypeHypothesis winningHypothesis;
internal readonly ResolveVisitor parentVisitor;
internal override bool IsUndecided {
get { return winningHypothesis == null; }
}
internal override AstNode LambdaExpression {
get { return lambda; }
}
public ImplicitlyTypedLambda(LambdaExpression lambda, ResolveVisitor parentVisitor)
{
this.lambda = lambda;
this.storedContext = visitor.resolver.Clone();
this.parsedFile = visitor.parsedFile;
this.parentVisitor = parentVisitor;
this.storedContext = parentVisitor.resolver.Clone();
this.parsedFile = parentVisitor.parsedFile;
foreach (var pd in lambda.Parameters) {
parameters.Add(new DefaultParameter(SharedTypes.UnknownType, pd.Name) {
Region = visitor.MakeRegion(pd)
Region = parentVisitor.MakeRegion(pd)
});
}
if (visitor.outstandingLambdas == null)
visitor.outstandingLambdas = new List<ImplicitlyTypedLambda>();
visitor.outstandingLambdas.Add(this);
if (parentVisitor.undecidedLambdas == null)
parentVisitor.undecidedLambdas = new List<LambdaBase>();
parentVisitor.undecidedLambdas.Add(this);
Debug.WriteLine("Added undecided implicitly-typed lambda: " + lambda);
}
public override IList<IParameter> Parameters {
@ -1351,6 +1522,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1351,6 +1522,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
internal override void EnforceMerge(ResolveVisitor parentVisitor)
{
GetAnyHypothesis().MergeInto(parentVisitor, SharedTypes.UnknownType);
}
public override bool IsImplicitlyTyped {
get { return true; }
}
@ -1396,7 +1572,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1396,7 +1572,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
this.parameterTypes = parameterTypes;
this.visitor = visitor;
visitor.resolver.PushBlock();
Debug.WriteLine("Analyzing " + ToString());
Debug.Indent();
visitor.resolver.PushLambdaBlock();
int i = 0;
foreach (var pd in lambda.lambda.Parameters) {
visitor.resolver.AddLambdaParameter(parameterTypes[i], visitor.MakeRegion(pd), pd.Name, false, false);
@ -1406,6 +1584,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1406,6 +1584,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
visitor.AnalyzeLambda(lambda.lambda.Body, out success, out isValidAsVoidMethod, out inferredReturnType, out returnValues);
visitor.resolver.PopBlock();
Debug.Unindent();
Debug.WriteLine("Finished analyzing " + ToString() + ".");
}
internal int CountUnknownParameters()
@ -1421,43 +1601,94 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1421,43 +1601,94 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
public Conversion IsValid(IType returnType, Conversions conversions)
{
if (success && IsValidLambda(isValidAsVoidMethod, returnValues, returnType, conversions))
return Conversion.AnonymousFunctionConversion(this);
return Conversion.AnonymousFunctionConversion(new AnonymousFunctionConversionData(returnType, this));
else
return Conversion.None;
}
public void MergeInto(ResolveVisitor parentVisitor)
public void MergeInto(ResolveVisitor parentVisitor, IType returnType)
{
visitor.MergeOutstandingLambdas();
if (returnType == null)
throw new ArgumentNullException("returnType");
if (parentVisitor != lambda.parentVisitor)
throw new InvalidOperationException("parent visitor mismatch");
if (lambda.winningHypothesis == this)
return;
else if (lambda.winningHypothesis != null)
throw new InvalidOperationException("Trying to merge conflicting hypotheses");
lambda.winningHypothesis = this;
foreach (var returnValue in returnValues) {
visitor.ProcessConversion(returnValue, returnType);
}
visitor.MergeUndecidedLambdas();
Debug.WriteLine("Merging " + ToString());
foreach (var pair in visitor.resolveResultCache) {
parentVisitor.resolveResultCache.Add(pair.Key, pair.Value);
}
foreach (var pair in visitor.resolverBeforeDict) {
parentVisitor.resolverBeforeDict.Add(pair.Key, pair.Value);
}
parentVisitor.outstandingLambdas.Remove(lambda);
parentVisitor.undecidedLambdas.Remove(lambda);
}
public override string ToString()
{
return "[LambdaTypeHypothesis for '" + lambda.lambda + "': " + string.Join<IType>(", ", parameterTypes) + "]";
}
}
#endregion
#region MergeUndecidedLambdas
abstract class LambdaBase : LambdaResolveResult
{
internal abstract bool IsUndecided { get; }
internal abstract AstNode LambdaExpression { get; }
internal abstract void EnforceMerge(ResolveVisitor parentVisitor);
}
void MergeOutstandingLambdas()
void MergeUndecidedLambdas()
{
if (outstandingLambdas == null)
if (undecidedLambdas == null)
return;
while (outstandingLambdas.Count > 0) {
ImplicitlyTypedLambda implicitlyTypedLambda = outstandingLambdas[0];
LambdaExpression lambdaExpr = implicitlyTypedLambda.lambda;
AstNode parent = lambdaExpr.Parent;
while (parent is ParenthesizedExpression)
Debug.WriteLine("MergeUndecidedLambdas()");
Debug.Indent();
while (undecidedLambdas.Count > 0) {
LambdaBase lambda = undecidedLambdas[0];
AstNode parent = lambda.LambdaExpression.Parent;
while (ActsAsParenthsizedExpression(parent))
parent = parent.Parent;
CSharpResolver storedResolver;
if (resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
Debug.WriteLine("Trying to resolve '" + parent + "' in order to merge the lambda");
Debug.Indent();
ResetContext(storedResolver, delegate { Resolve(parent); });
Debug.Unindent();
} else {
Debug.WriteLine("Could not find a suitable parent for '" + lambda);
}
if (outstandingLambdas.Count > 0 && outstandingLambdas[0] == implicitlyTypedLambda) {
if (lambda.IsUndecided) {
// Lambda wasn't merged by resolving its parent -> enforce merging
implicitlyTypedLambda.GetAnyHypothesis().MergeInto(this);
Debug.WriteLine("Lambda wasn't merged by conversion - enforce merging");
lambda.EnforceMerge(this);
}
}
Debug.Unindent();
Debug.WriteLine("MergeUndecidedLambdas() finished.");
}
/// <summary>
/// Gets whether the node acts as a parenthesized expression,
/// that is, it directly returns
/// </summary>
static bool ActsAsParenthsizedExpression(AstNode node)
{
return node is ParenthesizedExpression || node is CheckedExpression || node is UncheckedExpression;
}
#endregion
@ -1490,6 +1721,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1490,6 +1721,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
inferredReturnType = ti.GetBestCommonType(returnValues, out success);
}
}
Debug.WriteLine("Lambda return type was inferred to: " + inferredReturnType);
// TODO: check for compiler errors within the lambda body
// success &= ..;
}
@ -1565,15 +1797,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1565,15 +1797,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.PushBlock();
ScanChildren(blockStatement);
resolver.PopBlock();
return null;
return voidResult;
}
public override ResolveResult VisitUsingStatement(UsingStatement usingStatement, object data)
{
resolver.PushBlock();
ScanChildren(usingStatement);
if (resolverEnabled) {
for (AstNode child = usingStatement.FirstChild; child != null; child = child.NextSibling) {
if (child.Role == UsingStatement.ResourceAcquisitionRole && child is Expression) {
ITypeDefinition disposable = resolver.Context.GetTypeDefinition(
"System", "IDisposable", 0, StringComparer.Ordinal);
ResolveAndProcessConversion((Expression)child, disposable ?? SharedTypes.UnknownType);
}
Scan(child);
}
} else {
ScanChildren(usingStatement);
}
resolver.PopBlock();
return null;
return voidResult;
}
public override ResolveResult VisitFixedStatement(FixedStatement fixedStatement, object data)
@ -1593,18 +1836,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1593,18 +1836,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Scan(node);
}
resolver.PopBlock();
return null;
return voidResult;
}
public override ResolveResult VisitForStatement(ForStatement forStatement, object data)
{
resolver.PushBlock();
ScanChildren(forStatement);
resolver.PopBlock();
return null;
}
public override ResolveResult VisitForeachStatement(ForeachStatement foreachStatement, object data)
{
resolver.PushBlock();
@ -1612,18 +1846,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1612,18 +1846,23 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resolver.AddVariable(type, MakeRegion(foreachStatement.VariableNameToken), foreachStatement.VariableName);
ScanChildren(foreachStatement);
resolver.PopBlock();
return null;
return voidResult;
}
public override ResolveResult VisitCatchClause(CatchClause catchClause, object data)
{
resolver.PushBlock();
IVariable v = null;
if (catchClause.VariableName != null) {
resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), MakeRegion(catchClause.VariableNameToken), catchClause.VariableName);
v = resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), MakeRegion(catchClause.VariableNameToken), catchClause.VariableName);
}
ScanChildren(catchClause);
resolver.PopBlock();
return null;
if (resolverEnabled && v != null) {
return new LocalResolveResult(v, v.Type.Resolve(resolver.Context));
} else {
return null;
}
}
#endregion
@ -1660,6 +1899,78 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1660,6 +1899,78 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
#region Condition Statements
public override ResolveResult VisitForStatement(ForStatement forStatement, object data)
{
resolver.PushBlock();
HandleConditionStatement(forStatement);
resolver.PopBlock();
return voidResult;
}
public override ResolveResult VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
{
HandleConditionStatement(ifElseStatement);
return voidResult;
}
public override ResolveResult VisitWhileStatement(WhileStatement whileStatement, object data)
{
HandleConditionStatement(whileStatement);
return voidResult;
}
public override ResolveResult VisitDoWhileStatement(DoWhileStatement doWhileStatement, object data)
{
HandleConditionStatement(doWhileStatement);
return voidResult;
}
void HandleConditionStatement(Statement conditionStatement)
{
if (resolverEnabled) {
for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) {
if (child.Role == AstNode.Roles.Condition) {
ResolveAndProcessConversion((Expression)child, KnownTypeReference.Boolean.Resolve(resolver.Context));
} else {
Scan(child);
}
}
} else {
ScanChildren(conditionStatement);
}
}
#endregion
#region Return Statements
public override ResolveResult VisitReturnStatement(ReturnStatement returnStatement, object data)
{
if (resolverEnabled && !resolver.IsWithinLambdaExpression && resolver.CurrentMember != null) {
ResolveAndProcessConversion(returnStatement.Expression, resolver.CurrentMember.ReturnType.Resolve(resolver.Context));
} else {
Scan(returnStatement.Expression);
}
return voidResult;
}
public override ResolveResult VisitYieldStatement(YieldStatement yieldStatement, object data)
{
if (resolverEnabled && resolver.CurrentMember != null) {
IType returnType = resolver.CurrentMember.ReturnType.Resolve(resolver.Context);
IType elementType = GetElementType(returnType, resolver.Context, true);
ResolveAndProcessConversion(yieldStatement.Expression, elementType);
} else {
Scan(yieldStatement.Expression);
}
return voidResult;
}
public override ResolveResult VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, object data)
{
return voidResult;
}
#endregion
#region Local Variable Type Inference
/// <summary>
/// Creates a type reference for the specified type node.
@ -1739,7 +2050,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1739,7 +2050,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
result = visitor.Resolve(initializerExpression).Type;
if (isForEach) {
result = GetElementType(result);
result = GetElementType(result, storedContext.Context, false);
}
});
visitor = null;
@ -1748,28 +2059,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1748,28 +2059,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return result;
}
IType GetElementType(IType result)
{
bool foundSimpleIEnumerable = false;
foreach (IType baseType in result.GetAllBaseTypes(storedContext.Context)) {
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && baseTypeDef.Name == "IEnumerable") {
if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) {
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
return pt.TypeArguments[0];
}
} else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) {
foundSimpleIEnumerable = true;
}
}
}
// System.Collections.IEnumerable found in type hierarchy -> Object is element type.
if (foundSimpleIEnumerable)
return KnownTypeReference.Object.Resolve(storedContext.Context);
return SharedTypes.UnknownType;
}
public override string ToString()
{
if (visitor == null)
@ -1778,6 +2067,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1778,6 +2067,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return "var (not yet resolved)";
}
}
static IType GetElementType(IType result, ITypeResolveContext context, bool allowIEnumerator)
{
bool foundSimpleIEnumerable = false;
foreach (IType baseType in result.GetAllBaseTypes(context)) {
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef != null && (
baseTypeDef.Name == "IEnumerable" || (allowIEnumerator && baseType.Name == "IEnumerator")))
{
if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) {
ParameterizedType pt = baseType as ParameterizedType;
if (pt != null) {
return pt.TypeArguments[0];
}
} else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) {
foundSimpleIEnumerable = true;
}
}
}
// System.Collections.IEnumerable found in type hierarchy -> Object is element type.
if (foundSimpleIEnumerable)
return KnownTypeReference.Object.Resolve(context);
return SharedTypes.UnknownType;
}
#endregion
#region Attributes
@ -1792,7 +2105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1792,7 +2105,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// Scan the non-constructor arguments
foreach (var arg in nonConstructorArguments)
Scan(arg);
Scan(arg); // TODO: handle these like object initializers
// Resolve the ctor arguments and find the matching ctor overload
string[] argumentNames;

Loading…
Cancel
Save