|
|
|
|
@ -27,7 +27,6 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
@@ -27,7 +27,6 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
|
|
|
|
|
using ICSharpCode.NRefactory.Semantics; |
|
|
|
|
using ICSharpCode.NRefactory.TypeSystem; |
|
|
|
|
using ICSharpCode.NRefactory.TypeSystem.Implementation; |
|
|
|
|
using ICSharpCode.NRefactory.Utils; |
|
|
|
|
|
|
|
|
|
namespace ICSharpCode.NRefactory.CSharp.Resolver |
|
|
|
|
{ |
|
|
|
|
@ -393,10 +392,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -393,10 +392,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MarkUnknownNamedArguments(IEnumerable<Expression> arguments) |
|
|
|
|
{ |
|
|
|
|
foreach (var nae in arguments.OfType<NamedArgumentExpression>()) { |
|
|
|
|
StoreCurrentState(nae); |
|
|
|
|
StoreResult(nae, new NamedArgumentResolveResult(nae.Name, resolveResultCache[nae.Expression])); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ProcessConversionsInInvocation(Expression target, IEnumerable<Expression> arguments, CSharpInvocationResolveResult invocation) |
|
|
|
|
{ |
|
|
|
|
if (invocation == null) |
|
|
|
|
if (invocation == null) { |
|
|
|
|
// we still need to handle the named arguments if invocation==null
|
|
|
|
|
MarkUnknownNamedArguments(arguments); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
int i = 0; |
|
|
|
|
if (invocation.IsExtensionMethodInvocation) { |
|
|
|
|
Debug.Assert(arguments.Count() + 1 == invocation.Arguments.Count); |
|
|
|
|
@ -406,11 +416,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -406,11 +416,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
Debug.Assert(arguments.Count() == invocation.Arguments.Count); |
|
|
|
|
} |
|
|
|
|
foreach (Expression arg in arguments) { |
|
|
|
|
ResolveResult argRR = invocation.Arguments[i++]; |
|
|
|
|
NamedArgumentExpression nae = arg as NamedArgumentExpression; |
|
|
|
|
if (nae != null) |
|
|
|
|
ProcessConversionResult(nae.Expression, invocation.Arguments[i++] as ConversionResolveResult); |
|
|
|
|
else |
|
|
|
|
ProcessConversionResult(arg, invocation.Arguments[i++] as ConversionResolveResult); |
|
|
|
|
NamedArgumentResolveResult nrr = argRR as NamedArgumentResolveResult; |
|
|
|
|
Debug.Assert((nae == null) == (nrr == null)); |
|
|
|
|
if (nae != null && nrr != null) { |
|
|
|
|
StoreCurrentState(nae); |
|
|
|
|
StoreResult(nae, nrr); |
|
|
|
|
ProcessConversionResult(nae.Expression, nrr.Argument as ConversionResolveResult); |
|
|
|
|
} else { |
|
|
|
|
ProcessConversionResult(arg, argRR as ConversionResolveResult); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
@ -1398,7 +1414,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1398,7 +1414,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
|
|
|
|
|
ResolveResult IAstVisitor<ResolveResult>.VisitIndexerExpression(IndexerExpression indexerExpression) |
|
|
|
|
{ |
|
|
|
|
if (resolverEnabled) { |
|
|
|
|
if (resolverEnabled || NeedsResolvingDueToNamedArguments(indexerExpression)) { |
|
|
|
|
Expression target = indexerExpression.Target; |
|
|
|
|
ResolveResult targetResult = Resolve(target); |
|
|
|
|
string[] argumentNames; |
|
|
|
|
@ -1406,6 +1422,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1406,6 +1422,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
ResolveResult rr = resolver.ResolveIndexer(targetResult, arguments, argumentNames); |
|
|
|
|
ArrayAccessResolveResult aarr = rr as ArrayAccessResolveResult; |
|
|
|
|
if (aarr != null) { |
|
|
|
|
MarkUnknownNamedArguments(indexerExpression.Arguments); |
|
|
|
|
ProcessConversionResults(indexerExpression.Arguments, aarr.Indexes); |
|
|
|
|
} else { |
|
|
|
|
ProcessConversionsInInvocation(target, indexerExpression.Arguments, rr as CSharpInvocationResolveResult); |
|
|
|
|
@ -1437,8 +1454,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1437,8 +1454,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
// by calling GetArguments().
|
|
|
|
|
// This method gets called only when scanning, or when the named argument is used
|
|
|
|
|
// in an invalid context.
|
|
|
|
|
Scan(namedArgumentExpression.Expression); |
|
|
|
|
return null; |
|
|
|
|
if (resolverEnabled) { |
|
|
|
|
return new NamedArgumentResolveResult(namedArgumentExpression.Name, Resolve(namedArgumentExpression.Expression)); |
|
|
|
|
} else { |
|
|
|
|
Scan(namedArgumentExpression.Expression); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// NamedExpression is "identifier = Expression" in object initializers and attributes
|
|
|
|
|
@ -1477,48 +1498,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1477,48 +1498,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
|
|
|
|
|
ResolveResult IAstVisitor<ResolveResult>.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) |
|
|
|
|
{ |
|
|
|
|
if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) { |
|
|
|
|
var typeResolveResult = Resolve(objectCreateExpression.Type); |
|
|
|
|
if (typeResolveResult.IsError) { |
|
|
|
|
ScanChildren (objectCreateExpression); |
|
|
|
|
return typeResolveResult; |
|
|
|
|
} |
|
|
|
|
IType type = typeResolveResult.Type; |
|
|
|
|
|
|
|
|
|
List<ResolveResult> initializerStatements = null; |
|
|
|
|
var initializer = objectCreateExpression.Initializer; |
|
|
|
|
if (!initializer.IsNull) { |
|
|
|
|
initializerStatements = new List<ResolveResult>(); |
|
|
|
|
HandleObjectInitializer(new InitializedObjectResolveResult(type), initializer, initializerStatements); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string[] argumentNames; |
|
|
|
|
ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); |
|
|
|
|
|
|
|
|
|
ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements); |
|
|
|
|
if (arguments.Length == 1 && rr.Type.Kind == TypeKind.Delegate) { |
|
|
|
|
// Apply conversion to argument if it directly wraps the argument
|
|
|
|
|
// (but not when creating a delegate from a delegate, as then there would be a MGRR for .Invoke in between)
|
|
|
|
|
// This is necessary for lambda type inference.
|
|
|
|
|
var crr = rr as ConversionResolveResult; |
|
|
|
|
if (crr != null && crr.Input == arguments[0]) { |
|
|
|
|
ProcessConversionResult(objectCreateExpression.Arguments.Single(), crr); |
|
|
|
|
|
|
|
|
|
// wrap the result so that the delegate creation is not handled as a reference
|
|
|
|
|
// to the target method - otherwise FindReferencedEntities would produce two results for
|
|
|
|
|
// the same delegate creation.
|
|
|
|
|
return WrapResult(rr); |
|
|
|
|
} else { |
|
|
|
|
return rr; |
|
|
|
|
} |
|
|
|
|
var typeResolveResult = Resolve(objectCreateExpression.Type); |
|
|
|
|
if (typeResolveResult.IsError) { |
|
|
|
|
ScanChildren (objectCreateExpression); |
|
|
|
|
return typeResolveResult; |
|
|
|
|
} |
|
|
|
|
IType type = typeResolveResult.Type; |
|
|
|
|
|
|
|
|
|
List<ResolveResult> initializerStatements = null; |
|
|
|
|
var initializer = objectCreateExpression.Initializer; |
|
|
|
|
if (!initializer.IsNull) { |
|
|
|
|
initializerStatements = new List<ResolveResult>(); |
|
|
|
|
HandleObjectInitializer(new InitializedObjectResolveResult(type), initializer, initializerStatements); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
string[] argumentNames; |
|
|
|
|
ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); |
|
|
|
|
|
|
|
|
|
ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames, false, initializerStatements); |
|
|
|
|
if (arguments.Length == 1 && rr.Type.Kind == TypeKind.Delegate) { |
|
|
|
|
MarkUnknownNamedArguments(objectCreateExpression.Arguments); |
|
|
|
|
// Apply conversion to argument if it directly wraps the argument
|
|
|
|
|
// (but not when creating a delegate from a delegate, as then there would be a MGRR for .Invoke in between)
|
|
|
|
|
// This is necessary for lambda type inference.
|
|
|
|
|
var crr = rr as ConversionResolveResult; |
|
|
|
|
if (crr != null && crr.Input == arguments[0]) { |
|
|
|
|
ProcessConversionResult(objectCreateExpression.Arguments.Single(), crr); |
|
|
|
|
|
|
|
|
|
// wrap the result so that the delegate creation is not handled as a reference
|
|
|
|
|
// to the target method - otherwise FindReferencedEntities would produce two results for
|
|
|
|
|
// the same delegate creation.
|
|
|
|
|
return WrapResult(rr); |
|
|
|
|
} else { |
|
|
|
|
// process conversions in all other cases
|
|
|
|
|
ProcessConversionsInInvocation(null, objectCreateExpression.Arguments, rr as CSharpInvocationResolveResult); |
|
|
|
|
return rr; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
ScanChildren(objectCreateExpression); |
|
|
|
|
return null; |
|
|
|
|
// process conversions in all other cases
|
|
|
|
|
ProcessConversionsInInvocation(null, objectCreateExpression.Arguments, rr as CSharpInvocationResolveResult); |
|
|
|
|
return rr; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1701,6 +1718,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1701,6 +1718,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets and resolves the arguments; unpacking any NamedArgumentExpressions.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// Callers of GetArguments must also call either ProcessConversionsInInvocation or MarkUnknownNamedArguments
|
|
|
|
|
/// to ensure the named arguments get resolved.
|
|
|
|
|
/// Also, as named arguments get resolved by the parent node, the parent node must not scan
|
|
|
|
|
/// into the argument list without being resolved - see NeedsResolvingDueToNamedArguments().
|
|
|
|
|
/// </remarks>
|
|
|
|
|
ResolveResult[] GetArguments(IEnumerable<Expression> argumentExpressions, out string[] argumentNames) |
|
|
|
|
{ |
|
|
|
|
argumentNames = null; |
|
|
|
|
@ -1722,6 +1748,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1722,6 +1748,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
return arguments; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool NeedsResolvingDueToNamedArguments(Expression nodeWithArguments) |
|
|
|
|
{ |
|
|
|
|
for (AstNode child = nodeWithArguments.FirstChild; child != null; child = child.NextSibling) { |
|
|
|
|
if (child is NamedArgumentExpression) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static NameLookupMode GetNameLookupMode(Expression expr) |
|
|
|
|
{ |
|
|
|
|
InvocationExpression ie = expr.Parent as InvocationExpression; |
|
|
|
|
@ -1840,7 +1875,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -1840,7 +1875,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Regular code path
|
|
|
|
|
if (resolverEnabled) { |
|
|
|
|
if (resolverEnabled || NeedsResolvingDueToNamedArguments(invocationExpression)) { |
|
|
|
|
ResolveResult target = Resolve(invocationExpression.Target); |
|
|
|
|
return ResolveInvocationOnGivenTarget(target, invocationExpression); |
|
|
|
|
} else { |
|
|
|
|
@ -3779,10 +3814,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
@@ -3779,10 +3814,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
|
|
|
|
|
#region Constructor Initializer
|
|
|
|
|
ResolveResult IAstVisitor<ResolveResult>.VisitConstructorInitializer(ConstructorInitializer constructorInitializer) |
|
|
|
|
{ |
|
|
|
|
if (!resolverEnabled) { |
|
|
|
|
ScanChildren(constructorInitializer); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
ResolveResult target; |
|
|
|
|
if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.Base) { |
|
|
|
|
target = resolver.ResolveBaseReference(); |
|
|
|
|
|