/// <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="CastExpression"/>s! /// </param> /// <param name="argumentNames"> /// The argument names. Pass the null string for positional arguments. /// </param> /// <param name="allowProtectedAccess"> /// Whether to allow calling protected constructors. /// This should be false except when resolving constructor initializers. /// </param> /// <param name="initializerStatements"> /// Statements for Objects/Collections initializer. /// <see cref="InvocationExpression.InitializerStatements"/> /// </param> /// <returns>InvocationResolveResult or ErrorResolveResult</returns> public static Expression ResolveObjectCreation(ResolveContext rc, Location l, IType type, Expression[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false, IList <Expression> initializerStatements = null) { if (type.Kind == TypeKind.Delegate) { if (arguments == null || arguments.Length != 1) { rc.Report.Error(0, l, "Method name expected"); return(null); } Expression input = arguments[0]; IMethod invoke = input.Type.GetDelegateInvokeMethod(); if (invoke != null) { input = new MethodGroupExpression( input, invoke.Name, methods: new[] { new MethodListWithDeclaringType(input.Type) { invoke } }, typeArguments: EmptyList <IType> .Instance ); } return(rc.Convert(input, type)); } OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames); MemberLookup lookup = rc.CreateMemberLookup(); List <IMethod> allApplicable = null; foreach (IMethod ctor in type.GetConstructors()) { if (lookup.IsAccessible(ctor, allowProtectedAccess)) { or.AddCandidate(ctor); } else { or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible); } } if (or.BestCandidate != null) { return(or.CreateInvocation(null, initializerStatements)); } else { rc.Report.Error(0, l, "The type `{0}' does not contain a constructor that takes `{1}' arguments", type.ToString(), arguments != null ? arguments.Length.ToString() : "0"); return(ErrorResult); } }
public Expression ResolveMemberAccess(ResolveContext rc, VSC.AST.Expression target, string identifier, IList <IType> typeArguments, NameLookupMode lookupMode = NameLookupMode.Expression) { // V# 4.0 spec: §7.6.4 bool parameterizeResultType = !(typeArguments.Count != 0 && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)); AliasNamespace nrr = target as AliasNamespace; if (nrr != null) { return(ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, parameterizeResultType)); } // TODO:Dynamic Resolution //if (target.Type.Kind == TypeKind.Dynamic) // return new DynamicMemberResolveResult(target, identifier); MemberLookup lookup = rc.CreateMemberLookup(lookupMode); Expression result; switch (lookupMode) { case NameLookupMode.Expression: result = lookup.Lookup(target, identifier, typeArguments, isInvocation: false); break; case NameLookupMode.InvocationTarget: result = lookup.Lookup(target, identifier, typeArguments, isInvocation: true); break; case NameLookupMode.Type: case NameLookupMode.TypeInUsingDeclaration: case NameLookupMode.BaseTypeReference: // Don't do the UnknownMemberResolveResult/MethodGroupResolveResult processing, // it's only relevant for expressions. return(lookup.LookupType(target.Type, identifier, typeArguments, parameterizeResultType)); default: throw new NotSupportedException("Invalid value for NameLookupMode"); } if (result is UnknownMemberExpression) { // We intentionally use all extension methods here, not just the eligible ones. // Proper eligibility checking is only possible for the full invocation // (after we know the remaining arguments). // The eligibility check in GetExtensionMethods is only intended for code completion. var extensionMethods = rc.GetExtensionMethods(identifier, typeArguments); if (extensionMethods.Count > 0) { return(new MethodGroupExpression(target, identifier, EmptyList <MethodListWithDeclaringType> .Instance, typeArguments) { extensionMethods = extensionMethods }); } } else { MethodGroupExpression mgrr = result as MethodGroupExpression; if (mgrr != null) { Debug.Assert(mgrr.extensionMethods == null); // set the values that are necessary to make MethodGroupResolveResult.GetExtensionMethods() work mgrr.resolver = rc; } } return(result); }
/// <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>InvocationExpression</returns> private Expression ResolveInvocation(ResolveContext rc, Expression target, Expression[] arguments, string[] argumentNames, bool allowOptionalParameters) { // C# 4.0 spec: §7.6.5 MethodGroupExpression mgrr = target as MethodGroupExpression; if (mgrr != null) { OverloadResolution or = mgrr.PerformOverloadResolution(rc.compilation, arguments, argumentNames, checkForOverflow: rc.checkForOverflow, conversions: rc.conversions, allowOptionalParameters: allowOptionalParameters); if (or.BestCandidate != null) { var m = or.BestCandidate; if (arguments == null && m.Name == DestructorDeclaration.MetadataName) { rc.Report.Error(0, loc, "Destructors cannot be called directly. Consider calling IDisposable.Dispose if available"); } CheckSpecialMethod(rc, m); if (or.BestCandidate.IsStatic && !or.IsExtensionMethodInvocation && !(mgrr.TargetResult is TypeExpression)) { return(or.CreateInvocation(new TypeExpression(mgrr.TargetType), returnTypeOverride: null)); } else { return(or.CreateInvocation(mgrr.TargetResult, returnTypeOverride: null)); } } else { // No candidate found at all (not even an inapplicable one). // This can happen with empty method groups (as sometimes used with extension methods) rc.Report.Error(0, loc, "`{0}' does not contain a definition for `{1}'", mgrr.TargetType.ToString(), mgrr.MethodName); return(null); } } if (target == null && expr is SimpleName) { rc.Report.Error(0, loc, "`{0}' does not contain a definition for `{1}'", rc.CurrentTypeDefinition.ToString(), expr.GetSignatureForError()); return(null); } else if (target == null) { return(null); } IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); if (invokeMethod != null) { // is it a delegate ? if (target.Type.Kind != TypeKind.Delegate) { rc.Report.Error(0, loc, "Cannot invoke a non-delegate type `{0}'", target.Type.ToString()); return(null); } OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames); or.AddCandidate(invokeMethod); return(new Invocation( target, invokeMethod, //invokeMethod.ReturnType.Resolve(context), or.GetArgumentsWithConversionsAndNames(), or.BestCandidateErrors, isExpandedForm: or.BestCandidateIsExpandedForm, isDelegateInvocation: true, argumentToParameterMap: or.GetArgumentToParameterMap(), returnTypeOverride: null)); } rc.Report.Error(0, loc, "The member `{0}' cannot be used as method or delegate", target.GetSignatureForError()); return(ErrorResult); }