/// <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); } }
/// <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="CastExpression"/>s! /// </param> /// <param name="argumentNames"> /// The argument names. Pass the null string for positional arguments. /// </param> /// <returns>ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult</returns> public Expression ResolveIndexer(ResolveContext rc, Expression target, Expression[] arguments, string[] argumentNames = null) { switch (target.Type.Kind) { case TypeKind.Array: // �6.6.1 Array access if (argumentNames != null && argumentNames.Length > 0) { rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument"); } return(new ArrayAccessExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments)); case TypeKind.Pointer: // �.5.3 Pointer element access if (argumentNames != null && argumentNames.Length > 0) { rc.Report.Error(0, Arguments.args.Where(x => x is NamedArgument).First().loc, "An element access expression cannot use named argument"); } return(new PointerArithmeticExpression(((ElementTypeSpec)target.Type).ElementType, target, arguments)); } // �6.6.2 Indexer access MemberLookup lookup = rc.CreateMemberLookup(); var indexers = lookup.LookupIndexers(target); OverloadResolution or = rc.CreateOverloadResolution(arguments, argumentNames); or.AddMethodLists(indexers); if (or.BestCandidate != null) { return(or.CreateInvocation(target)); } else { rc.Report.Error(0, loc, "Cannot apply indexing with [] to an expression of type `{0}'", target.Type.ToString()); return(null); } }
Expression SetUserDefinedOperationInformations(ResolveContext rc, OverloadResolution r) {//TODO:Is It OK if (r.BestCandidateErrors != OverloadResolutionErrors.None) { rc.Report.Error(0, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'", OperName(Oper), Expr.Type.ToString()); return(r.CreateInvocation(null)); } IMethod method = (IMethod)r.BestCandidate; var operands = r.GetArgumentsWithConversions(); this.operatortype = ResolveContext.GetLinqNodeType(this.Oper, rc.checkForOverflow); this.isLiftedOperator = method is OverloadResolution.ILiftedOperator; this.ResolvedType = method.ReturnType; this.Expr = operands[0]; this.userDefinedOperatorMethod = method; _resolved = true; return(this); }
/// <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); }