/// <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); } }
Expression LookInCurrentType(ResolveContext rc, string identifier, IList <IType> typeArguments, NameLookupMode lookupMode, bool parameterizeResultType) { int k = typeArguments.Count; MemberLookup lookup = rc.CreateMemberLookup(lookupMode); // look in current type definitions for (ITypeDefinition t = rc.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { if (k == 0) { // Look for type parameter with that name var typeParameters = t.TypeParameters; // Look at all type parameters, including those copied from outer classes, // so that we can fetch the version with the correct owner. for (int i = 0; i < typeParameters.Count; i++) { if (typeParameters[i].Name == identifier) { return(new TypeExpression(typeParameters[i], Location)); } } } if (lookupMode == NameLookupMode.BaseTypeReference && t == rc.CurrentTypeDefinition) { // don't look in current type when resolving a base type reference continue; } Expression r; if (lookupMode == NameLookupMode.Expression || lookupMode == NameLookupMode.InvocationTarget) { Expression targetResolveResult = (t == rc.CurrentTypeDefinition ? (Expression) new SelfReference(t, Location) : new TypeExpression(t, Location)); r = lookup.Lookup(targetResolveResult, identifier, typeArguments, lookupMode == NameLookupMode.InvocationTarget); } else { r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType); } if (!(r is UnknownMemberExpression)) // but do return AmbiguousMemberResolveResult { return(r); } } return(null); }
/// <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); } }
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); }