public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(returnType) { if (member == null) throw new ArgumentNullException("member"); this.targetResult = targetResult; this.member = member; }
public IMethod ResolveConstructor(ITypeResolveContext context) { CSharpResolver r = new CSharpResolver(context); IType type = attributeType.Resolve(context); int totalArgumentCount = 0; if (positionalArguments != null) totalArgumentCount += positionalArguments.Count; if (namedCtorArguments != null) totalArgumentCount += namedCtorArguments.Count; ResolveResult[] arguments = new ResolveResult[totalArgumentCount]; string[] argumentNames = new string[totalArgumentCount]; int i = 0; if (positionalArguments != null) { while (i < positionalArguments.Count) { IConstantValue cv = positionalArguments[i]; arguments[i] = new ConstantResolveResult(cv.GetValueType(context), cv.GetValue(context)); i++; } } if (namedCtorArguments != null) { foreach (var pair in namedCtorArguments) { argumentNames[i] = pair.Key; arguments[i] = new ConstantResolveResult(pair.Value.GetValueType(context), pair.Value.GetValue(context)); i++; } } MemberResolveResult mrr = r.ResolveObjectCreation(type, arguments, argumentNames) as MemberResolveResult; return mrr != null ? mrr.Member as IMethod : null; }
public bool ImplicitConversion(ResolveResult resolveResult, IType toType) { if (resolveResult == null) throw new ArgumentNullException("resolveResult"); if (resolveResult.IsCompileTimeConstant && (ImplicitEnumerationConversion(resolveResult, toType) || ImplicitConstantExpressionConversion(resolveResult, toType))) return true; return ImplicitConversion(resolveResult.Type, toType); }
public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion) : base(targetType) { if (input == null) throw new ArgumentNullException("input"); this.Input = input; this.Conversion = conversion; }
public UnaryOperatorResolveResult(IType resultType, UnaryOperatorType op, ResolveResult input) : base(resultType) { if (input == null) throw new ArgumentNullException("input"); this.Operator = op; this.Input = input; }
public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, object constantValue) : base(returnType) { if (member == null) throw new ArgumentNullException("member"); this.targetResult = targetResult; this.member = member; this.isConstant = true; this.constantValue = constantValue; }
public BinaryOperatorResolveResult(IType resultType, ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs) : base(resultType) { if (lhs == null) throw new ArgumentNullException("lhs"); if (rhs == null) throw new ArgumentNullException("rhs"); this.Left = lhs; this.Operator = op; this.Right = rhs; }
public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context) : base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context)) { this.targetResult = targetResult; this.member = member; IField field = member as IField; if (field != null) { isConstant = field.IsConst; if (isConstant) constantValue = field.ConstantValue.GetValue(context); } }
public InvocationResolveResult(ResolveResult targetResult, OverloadResolution or, ITypeResolveContext context) : base( or.IsExtensionMethodInvocation ? null : targetResult, or.GetBestCandidateWithSubstitutedTypeArguments(), context) { this.OverloadResolutionErrors = or.BestCandidateErrors; this.argumentToParameterMap = or.GetArgumentToParameterMap(); this.Arguments = or.GetArgumentsWithConversions(); this.IsExtensionMethodInvocation = or.IsExtensionMethodInvocation; this.IsExpandedForm = or.BestCandidateIsExpandedForm; this.IsLiftedOperatorInvocation = or.BestCandidate is OverloadResolution.ILiftedOperator; }
public bool ImplicitConversion(ResolveResult resolveResult, IType toType) { if (resolveResult == null) throw new ArgumentNullException("resolveResult"); if (resolveResult.IsCompileTimeConstant) { if (ImplicitEnumerationConversion(resolveResult, toType)) return true; if (ImplicitConstantExpressionConversion(resolveResult, toType)) return true; } if (ImplicitConversion(resolveResult.Type, toType)) return true; // TODO: Anonymous function conversions // TODO: Method group conversions return false; }
public InvocationResolveResult( ResolveResult targetResult, IParameterizedMember member, IType returnType, IList<ResolveResult> arguments, OverloadResolutionErrors overloadResolutionErrors = OverloadResolutionErrors.None, bool isExtensionMethodInvocation = false, bool isExpandedForm = false, bool isLiftedOperatorInvocation = false, bool isDelegateInvocation = false, IList<int> argumentToParameterMap = null) : base(targetResult, member, returnType) { this.OverloadResolutionErrors = overloadResolutionErrors; this.Arguments = arguments ?? EmptyList<ResolveResult>.Instance; this.IsExtensionMethodInvocation = isExtensionMethodInvocation; this.IsExpandedForm = isExpandedForm; this.IsLiftedOperatorInvocation = isLiftedOperatorInvocation; this.IsDelegateInvocation = isDelegateInvocation; this.argumentToParameterMap = argumentToParameterMap; }
public OverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null) { if (context == null) throw new ArgumentNullException("context"); if (arguments == null) throw new ArgumentNullException("arguments"); if (argumentNames == null) argumentNames = new string[arguments.Length]; else if (argumentNames.Length != arguments.Length) throw new ArgumentException("argumentsNames.Length must be equal to arguments.Length"); this.context = context; this.arguments = arguments; this.argumentNames = argumentNames; // keep explicitlyGivenTypeArguments==null when no type arguments were specified if (typeArguments != null && typeArguments.Length > 0) this.explicitlyGivenTypeArguments = typeArguments; this.conversions = new Conversions(context); }
/// <summary> /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) /// </summary> /// <returns>0 = neither is better; 1 = t1 is better; 2 = t2 is better</returns> public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) { LambdaResolveResult lambda = resolveResult as LambdaResolveResult; if (lambda != null) { if (!lambda.IsAnonymousMethod) { t1 = UnpackExpressionTreeType(t1); t2 = UnpackExpressionTreeType(t2); } IMethod m1 = t1.GetDelegateInvokeMethod(); IMethod m2 = t2.GetDelegateInvokeMethod(); if (m1 == null || m2 == null) { return(0); } int r = BetterConversionTarget(t1, t2); if (r != 0) { return(r); } if (m1.Parameters.Count != m2.Parameters.Count) { return(0); } IType[] parameterTypes = new IType[m1.Parameters.Count]; for (int i = 0; i < parameterTypes.Length; i++) { parameterTypes[i] = m1.Parameters[i].Type; if (!parameterTypes[i].Equals(m2.Parameters[i].Type)) { return(0); } } if (lambda.HasParameterList && parameterTypes.Length != lambda.Parameters.Count) { return(0); } IType ret1 = m1.ReturnType; IType ret2 = m2.ReturnType; if (ret1.Kind == TypeKind.Void && ret2.Kind != TypeKind.Void) { return(2); } if (ret1.Kind != TypeKind.Void && ret2.Kind == TypeKind.Void) { return(1); } IType inferredRet = lambda.GetInferredReturnType(parameterTypes); r = BetterConversion(inferredRet, ret1, ret2); if (r == 0 && lambda.IsAsync) { ret1 = UnpackTask(ret1); ret2 = UnpackTask(ret2); inferredRet = UnpackTask(inferredRet); if (ret1 != null && ret2 != null && inferredRet != null) { r = BetterConversion(inferredRet, ret1, ret2); } } return(r); } else { return(BetterConversion(resolveResult.Type, t1, t2)); } }
/// <summary> /// Performs a member lookup. /// </summary> public ResolveResult Lookup(ResolveResult targetResolveResult, string name, IList <IType> typeArguments, bool isInvocation) { if (targetResolveResult == null) { throw new ArgumentNullException("targetResolveResult"); } if (name == null) { throw new ArgumentNullException("name"); } if (typeArguments == null) { throw new ArgumentNullException("typeArguments"); } bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; bool allowProtectedAccess = (targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type)); Predicate <ITypeDefinition> nestedTypeFilter = delegate(ITypeDefinition entity) { return(entity.Name == name && IsAccessible(entity, allowProtectedAccess)); }; Predicate <IUnresolvedMember> memberFilter = delegate(IUnresolvedMember entity) { // NOTE: Atm destructors can be looked up with 'Finalize' return(entity.SymbolKind != SymbolKind.Indexer && entity.SymbolKind != SymbolKind.Operator && entity.Name == name); }; List <LookupGroup> lookupGroups = new List <LookupGroup>(); // This loop will handle base types before derived types. // The loop performs three jobs: // 1) It marks entries in lookup groups from base classes as removed when those members // are hidden by a derived class. // 2) It adds a new lookup group with the members from a declaring type. // 3) It replaces virtual members with the overridden version, placing the override in the // lookup group belonging to the base class. foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) { List <IType> newNestedTypes = null; List <IParameterizedMember> newMethods = null; IMember newNonMethod = null; IEnumerable <IType> typeBaseTypes = null; if (!isInvocation && !targetIsTypeParameter) { // Consider nested types only if it's not an invocation. // type.GetNestedTypes() is checking the type parameter count for an exact match, // so we don't need to do that in our filter. var nestedTypes = type.GetNestedTypes(typeArguments, nestedTypeFilter, GetMemberOptions.IgnoreInheritedMembers); AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } IEnumerable <IMember> members; if (typeArguments.Count == 0) { // Note: IsInvocable-checking cannot be done as part of the filter; // because it must be done after type substitution. members = type.GetMembers(memberFilter, GetMemberOptions.IgnoreInheritedMembers); if (isInvocation) { members = members.Where(m => IsInvocable(m)); } } else { // No need to check for isInvocation/isInvocable here: // we only fetch methods members = type.GetMethods(typeArguments, memberFilter, GetMemberOptions.IgnoreInheritedMembers); } AddMembers(type, members, allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newNestedTypes != null || newMethods != null || newNonMethod != null) { lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); } } // Remove interface members hidden by class members. if (targetIsTypeParameter) { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } return(CreateResult(targetResolveResult, lookupGroups, name, typeArguments)); }
void MakeOutputTypeInference(ResolveResult e, IType t) { Log.WriteLine(" MakeOutputTypeInference from " + e + " to " + t); // If E is an anonymous function with inferred return type U (§7.5.2.12) and T is a delegate type or expression // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb. LambdaResolveResult lrr = e as LambdaResolveResult; if (lrr != null) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { IType inferredReturnType; if (lrr.IsImplicitlyTyped) { if (m.Parameters.Count != lrr.Parameters.Count) { return; // cannot infer due to mismatched parameter lists } TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); IType[] inferredParameterTypes = new IType[m.Parameters.Count]; for (int i = 0; i < inferredParameterTypes.Length; i++) { IType parameterType = m.Parameters[i].Type; inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); } inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); } else { inferredReturnType = lrr.GetInferredReturnType(null); } MakeLowerBoundInference(inferredReturnType, m.ReturnType); return; } } // Otherwise, if E is a method group and T is a delegate type or expression tree type // with parameter types T1…Tk and return type Tb, and overload resolution // of E with the types T1…Tk yields a single method with return type U, then a lower-bound // inference is made from U to Tb. MethodGroupResolveResult mgrr = e as MethodGroupResolveResult; if (mgrr != null) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { ResolveResult[] args = new ResolveResult[m.Parameters.Count]; TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); for (int i = 0; i < args.Length; i++) { IParameter param = m.Parameters[i]; IType parameterType = param.Type.AcceptVisitor(substitution); if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); } else { args[i] = new ResolveResult(parameterType); } } var or = mgrr.PerformOverloadResolution(compilation, args, allowExpandingParams: false, allowOptionalParameters: false); if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { IType returnType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType; MakeLowerBoundInference(returnType, m.ReturnType); } } return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. if (IsValidType(e.Type)) { MakeLowerBoundInference(e.Type, t); } }
bool PhaseTwo() { // C# 4.0 spec: §7.5.2.2 The second phase Log.WriteLine("Phase Two"); // All unfixed type variables Xi which do not depend on any Xj are fixed. List <TP> typeParametersToFix = new List <TP>(); foreach (TP Xi in typeParameters) { if (Xi.IsFixed == false) { if (!typeParameters.Any((TP Xj) => !Xj.IsFixed && DependsOn(Xi, Xj))) { typeParametersToFix.Add(Xi); } } } // If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold: if (typeParametersToFix.Count == 0) { Log.WriteLine("Type parameters cannot be fixed due to dependency cycles"); Log.WriteLine("Trying to break the cycle by fixing any TPs that have non-empty bounds..."); foreach (TP Xi in typeParameters) { // Xi has a nonempty set of bounds if (!Xi.IsFixed && Xi.HasBounds) { // There is at least one type variable Xj that depends on Xi if (typeParameters.Any((TP Xj) => DependsOn(Xj, Xi))) { typeParametersToFix.Add(Xi); } } } } // now fix 'em bool errorDuringFix = false; foreach (TP tp in typeParametersToFix) { if (!Fix(tp)) { errorDuringFix = true; } } if (errorDuringFix) { return(false); } bool unfixedTypeVariablesExist = typeParameters.Any((TP X) => X.IsFixed == false); if (typeParametersToFix.Count == 0 && unfixedTypeVariablesExist) { // If no such type variables exist and there are still unfixed type variables, type inference fails. Log.WriteLine("Type inference fails: there are still unfixed TPs remaining"); return(false); } else if (!unfixedTypeVariablesExist) { // Otherwise, if no further unfixed type variables exist, type inference succeeds. return(true); } else { // Otherwise, for all arguments ei with corresponding parameter type Ti for (int i = 0; i < arguments.Length; i++) { ResolveResult Ei = arguments[i]; IType Ti = parameterTypes[i]; // where the output types (§7.4.2.4) contain unfixed type variables Xj // but the input types (§7.4.2.3) do not if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { // an output type inference (§7.4.2.6) is made for ei with type Ti. Log.WriteLine("MakeOutputTypeInference for argument #" + i); MakeOutputTypeInference(Ei, Ti); } } // Then the second phase is repeated. return(PhaseTwo()); } }
public ArrayCreateResolveResult(IType arrayType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements, bool allowArrayConstants) : base(arrayType) { this.SizeArguments = sizeArguments; this.InitializerElements = initializerElements; if (allowArrayConstants) { this.constantArray = MakeConstantArray(sizeArguments, initializerElements); } }
// TODO: add support for user-defined conversions #region BetterConversion /// <summary> /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) /// </summary> /// <returns>0 = neither is better; 1 = t1 is better; 2 = t2 is better</returns> public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) { // TODO: implement the special logic for anonymous functions return BetterConversion(resolveResult.Type, t1, t2); }
public ByReferenceResolveResult(ResolveResult elementResult, bool isOut) : this(elementResult.Type, isOut) { this.ElementResult = elementResult; }
public override IList <ResolveResult> GetArgumentsForCall() { ResolveResult[] results = new ResolveResult[Member.Parameters.Count]; List <ResolveResult> paramsArguments = IsExpandedForm ? new List <ResolveResult>() : null; // map arguments to parameters: for (int i = 0; i < Arguments.Count; i++) { int mappedTo; if (argumentToParameterMap != null) { mappedTo = argumentToParameterMap[i]; } else { mappedTo = IsExpandedForm ? Math.Min(i, results.Length - 1) : i; } if (mappedTo >= 0 && mappedTo < results.Length) { if (IsExpandedForm && mappedTo == results.Length - 1) { paramsArguments.Add(Arguments[i]); } else { var narr = Arguments[i] as NamedArgumentResolveResult; if (narr != null) { results[mappedTo] = narr.Argument; } else { results[mappedTo] = Arguments[i]; } } } } if (IsExpandedForm) { IType arrayType = Member.Parameters.Last().Type; IType int32 = Member.Compilation.FindType(KnownTypeCode.Int32); ResolveResult[] sizeArguments = { new ConstantResolveResult(int32, paramsArguments.Count) }; results[results.Length - 1] = new ArrayCreateResolveResult(arrayType, sizeArguments, paramsArguments); } for (int i = 0; i < results.Length; i++) { if (results[i] == null) { if (Member.Parameters[i].IsOptional) { results[i] = new ConstantResolveResult(Member.Parameters[i].Type, Member.Parameters[i].ConstantValue); } else { results[i] = ErrorResolveResult.UnknownError; } } } return(results); }
public static ResolveResult Resolve(Func <ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node, CancellationToken cancellationToken = default(CancellationToken)) { node = cu.GetNodeAt(location); if (node == null) { return(null); } if (CSharpAstResolver.IsUnresolvableNode(node)) { if (node is Identifier) { node = node.Parent; } else if (node.NodeType == NodeType.Token) { if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) { // There's no other place where one could hover to see the indexer's tooltip, // so we need to resolve it when hovering over the '[' or ']'. // For constructor initializer, the same applies to the 'base'/'this' token. node = node.Parent; } else { return(null); } } else { // don't resolve arbitrary nodes - we don't want to show tooltips for everything return(null); } } else { // It's a resolvable node. // However, we usually don't want to show the tooltip everywhere // For example, hovering with the mouse over an empty line between two methods causes // node==TypeDeclaration, but we don't want to show any tooltip. if (!node.GetChildByRole(Roles.Identifier).IsNull) { // We'll suppress the tooltip for resolvable nodes if there is an identifier that // could be hovered over instead: return(null); } } if (node == null) { return(null); } if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type) { node = node.Parent; } InvocationExpression parentInvocation = null; if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument) { // we also need to resolve the invocation parentInvocation = node.Parent as InvocationExpression; } CSharpAstResolver resolver = new CSharpAstResolver(compilation(), cu, parsedFile); resolver.ApplyNavigator(new NodeListResolveVisitorNavigator(node), cancellationToken); ResolveResult rr = resolver.Resolve(node, cancellationToken); if (rr is MethodGroupResolveResult && parentInvocation != null) { return(resolver.Resolve(parentInvocation)); } else { return(rr); } }
public void Resolved(AstNode node, ResolveResult result) { }
protected void AssertError(Type expectedType, ResolveResult rr) { Assert.IsTrue(rr.IsError, rr.ToString() + " is not an error, but an error was expected"); Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); }
public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType) { }
public ConditionalOperatorResolveResult(IType targetType, ResolveResult condition, ResolveResult @true, ResolveResult @false) : base(targetType) { if (condition == null) throw new ArgumentNullException("condition"); if (@true == null) throw new ArgumentNullException("true"); if (@false == null) throw new ArgumentNullException("false"); this.Condition = condition; this.True = @true; this.False = @false; }
IType[] OutputTypes(ResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.4 Output types LambdaResolveResult lrr = e as LambdaResolveResult; if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { return new[] { m.ReturnType.Resolve(context) }; } } return emptyTypeArray; }
void MakeOutputTypeInference(ResolveResult e, IType t) { Log.WriteLine(" MakeOutputTypeInference from " + e + " to " + t); // If E is an anonymous function with inferred return type U (§7.5.2.12) and T is a delegate type or expression // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb. LambdaResolveResult lrr = e as LambdaResolveResult; if (lrr != null) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { IType inferredReturnType; if (lrr.IsImplicitlyTyped) { if (m.Parameters.Count != lrr.Parameters.Count) return; // cannot infer due to mismatched parameter lists TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); IType[] inferredParameterTypes = new IType[m.Parameters.Count]; for (int i = 0; i < inferredParameterTypes.Length; i++) { IType parameterType = m.Parameters[i].Type.Resolve(context); inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); } inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); } else { inferredReturnType = lrr.GetInferredReturnType(null); } MakeLowerBoundInference(inferredReturnType, m.ReturnType.Resolve(context)); return; } } // Otherwise, if E is a method group and T is a delegate type or expression tree type // with parameter types T1…Tk and return type Tb, and overload resolution // of E with the types T1…Tk yields a single method with return type U, then a lower-bound // inference is made from U to Tb. MethodGroupResolveResult mgrr = e as MethodGroupResolveResult; if (mgrr != null) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { ResolveResult[] args = new ResolveResult[m.Parameters.Count]; TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); for (int i = 0; i < args.Length; i++) { IParameter param = m.Parameters[i]; IType parameterType = param.Type.Resolve(context); parameterType = parameterType.AcceptVisitor(substitution); if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { parameterType = ((ByReferenceType)parameterType).ElementType; args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); } else { args[i] = new ResolveResult(parameterType); } } var or = mgrr.PerformOverloadResolution(context, args, allowExtensionMethods: false, allowExpandingParams: false); if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { IType returnType = or.BestCandidate.ReturnType.Resolve(context); MakeLowerBoundInference(returnType, m.ReturnType.Resolve(context)); } } return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. if (e.Type != SharedTypes.UnknownType) { MakeLowerBoundInference(e.Type, t); } }
internal override bool IsMatch(ResolveResult rr) { ConversionResolveResult crr = rr as ConversionResolveResult; return(crr != null && crr.Conversion.IsUserDefined && crr.Conversion.Method.MemberDefinition == op); }
bool ImplicitConstantExpressionConversion(ResolveResult rr, IType toType) { // C# 4.0 spec: §6.1.9 TypeCode fromTypeCode = ReflectionHelper.GetTypeCode(rr.Type); TypeCode toTypeCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(toType)); if (fromTypeCode == TypeCode.Int64) { long val = (long)rr.ConstantValue; return val >= 0 && toTypeCode == TypeCode.UInt64; } else if (fromTypeCode == TypeCode.Int32) { int val = (int)rr.ConstantValue; switch (toTypeCode) { case TypeCode.SByte: return val >= SByte.MinValue && val <= SByte.MaxValue; case TypeCode.Byte: return val >= Byte.MinValue && val <= Byte.MaxValue; case TypeCode.Int16: return val >= Int16.MinValue && val <= Int16.MaxValue; case TypeCode.UInt16: return val >= UInt16.MinValue && val <= UInt16.MaxValue; case TypeCode.UInt32: return val >= 0; case TypeCode.UInt64: return val >= 0; } } return false; }
internal override bool IsMatch(ResolveResult rr) { var lrr = rr as LocalResolveResult; return(lrr != null && lrr.Variable.Name == variable.Name && lrr.Variable.Region == variable.Region); }
internal abstract bool IsMatch(ResolveResult rr);
public virtual void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) { }
public DynamicMemberResolveResult(ResolveResult target, string member) : base(SpecialType.Dynamic) { this.Target = target; this.Member = member; }
internal override bool IsMatch(ResolveResult rr) { TypeResolveResult trr = rr as TypeResolveResult; return(trr != null && typeDefinition.Equals(trr.Type.GetDefinition())); }
bool OutputTypeContainsUnfixed(ResolveResult argument, IType parameterType) { return(AnyTypeContainsUnfixedParameter(OutputTypes(argument, parameterType))); }
internal override bool IsMatch(ResolveResult rr) { var mrr = rr as MemberResolveResult; return(mrr != null && method == mrr.Member.MemberDefinition); }
/// <summary> /// Retrieves all members that are accessible and not hidden (by being overridden or shadowed). /// Returns both members and nested type definitions. Does not include extension methods. /// </summary> public IEnumerable <IEntity> GetAccessibleMembers(ResolveResult targetResolveResult) { if (targetResolveResult == null) { throw new ArgumentNullException("targetResolveResult"); } bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; bool allowProtectedAccess = (targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type)); // maps the member name to the list of lookup groups var lookupGroupDict = new Dictionary <string, List <LookupGroup> >(); // This loop will handle base types before derived types. // The loop performs three jobs: // 1) It marks entries in lookup groups from base classes as removed when those members // are hidden by a derived class. // 2) It adds a new lookup group with the members from a declaring type. // 3) It replaces virtual members with the overridden version, placing the override in the // lookup group belonging to the base class. foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes()) { List <IEntity> entities = new List <IEntity>(); entities.AddRange(type.GetMembers(options: GetMemberOptions.IgnoreInheritedMembers)); if (!targetIsTypeParameter) { var nestedTypes = type.GetNestedTypes(options: GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions); // GetDefinition() might return null if some IType has a strange implementation of GetNestedTypes. entities.AddRange(nestedTypes.Select(t => t.GetDefinition()).Where(td => td != null)); } foreach (var entityGroup in entities.GroupBy(e => e.Name)) { List <LookupGroup> lookupGroups = new List <LookupGroup>(); if (!lookupGroupDict.TryGetValue(entityGroup.Key, out lookupGroups)) { lookupGroupDict.Add(entityGroup.Key, lookupGroups = new List <LookupGroup>()); } List <IType> newNestedTypes = null; List <IParameterizedMember> newMethods = null; IMember newNonMethod = null; IEnumerable <IType> typeBaseTypes = null; if (!targetIsTypeParameter) { AddNestedTypes(type, entityGroup.OfType <IType>(), 0, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } AddMembers(type, entityGroup.OfType <IMember>(), allowProtectedAccess, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newNestedTypes != null || newMethods != null || newNonMethod != null) { lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); } } } foreach (List <LookupGroup> lookupGroups in lookupGroupDict.Values) { // Remove interface members hidden by class members. if (targetIsTypeParameter) { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } // Now report the results: foreach (LookupGroup lookupGroup in lookupGroups) { if (!lookupGroup.MethodsAreHidden) { foreach (IMethod method in lookupGroup.Methods) { yield return(method); } } if (!lookupGroup.NonMethodIsHidden) { yield return(lookupGroup.NonMethod); } if (lookupGroup.NestedTypes != null) { foreach (IType type in lookupGroup.NestedTypes) { ITypeDefinition typeDef = type.GetDefinition(); if (typeDef != null) { yield return(typeDef); } } } } } }
internal override bool IsMatch(ResolveResult rr) { MemberResolveResult mrr = rr as MemberResolveResult; return(mrr != null && indexer == mrr.Member.MemberDefinition); }
ResolveResult CreateResult(ResolveResult targetResolveResult, List <LookupGroup> lookupGroups, string name, IList <IType> typeArguments) { // Remove all hidden groups lookupGroups.RemoveAll(g => g.AllHidden); if (lookupGroups.Count == 0) { // No members found return(new UnknownMemberResolveResult(targetResolveResult.Type, name, typeArguments)); } if (lookupGroups.Any(g => !g.MethodsAreHidden && g.Methods.Count > 0)) { // If there are methods, make a MethodGroupResolveResult. // Note that a conflict between a member and a method (possible with multiple interface inheritance) // is only a warning, not an error, and the C# compiler will prefer the method group. List <MethodListWithDeclaringType> methodLists = new List <MethodListWithDeclaringType>(); foreach (var lookupGroup in lookupGroups) { if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0) { var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType); foreach (var method in lookupGroup.Methods) { methodListWithDeclType.Add((IMethod)method); } methodLists.Add(methodListWithDeclType); } } return(new MethodGroupResolveResult(targetResolveResult, name, methodLists, typeArguments)); } // If there are ambiguities, report the most-derived result (last group) LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1]; if (resultGroup.NestedTypes != null && resultGroup.NestedTypes.Count > 0) { if (resultGroup.NestedTypes.Count > 1 || !resultGroup.NonMethodIsHidden || lookupGroups.Count > 1) { return(new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0])); } else { return(new TypeResolveResult(resultGroup.NestedTypes[0])); } } if (resultGroup.NonMethod.IsStatic && targetResolveResult is ThisResolveResult) { targetResolveResult = new TypeResolveResult(targetResolveResult.Type); } if (lookupGroups.Count > 1) { return(new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod)); } else { if (isInEnumMemberInitializer) { IField field = resultGroup.NonMethod as IField; if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum) { return(new MemberResolveResult( targetResolveResult, field, field.DeclaringTypeDefinition.EnumUnderlyingType, field.IsConst, field.ConstantValue)); } } return(new MemberResolveResult(targetResolveResult, resultGroup.NonMethod)); } }
public ArrayAccessResolveResult(IType elementType, ResolveResult array, ResolveResult[] indices) : base(elementType) { if (array == null) throw new ArgumentNullException("array"); if (indices == null) throw new ArgumentNullException("indices"); this.Array = array; this.Indices = indices; }
IType[] InputTypes(ResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.3 Input types LambdaResolveResult lrr = e as LambdaResolveResult; if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { IType[] inputTypes = new IType[m.Parameters.Count]; for (int i = 0; i < inputTypes.Length; i++) { inputTypes[i] = m.Parameters[i].Type.Resolve(context); } return inputTypes; } } return emptyTypeArray; }
public CastResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow) : base(targetType, input, conversion, checkForOverflow) { }
bool OutputTypeContainsUnfixed(ResolveResult argument, IType parameterType) { return AnyTypeContainsUnfixedParameter(OutputTypes(argument, parameterType)); }
/// <summary> /// Gets whether access to protected instance members of the target expression is possible. /// </summary> public bool IsProtectedAccessAllowed(ResolveResult targetResolveResult) { return(targetResolveResult is ThisResolveResult || IsProtectedAccessAllowed(targetResolveResult.Type)); }
public IList<ResolveResult> GetArgumentsWithConversions() { if (bestCandidate == null) return arguments; var conversions = this.ArgumentConversions; ResolveResult[] args = new ResolveResult[arguments.Length]; for (int i = 0; i < args.Length; i++) { if (conversions[i] == Conversion.IdentityConversion || conversions[i] == Conversion.None) { args[i] = arguments[i]; } else { int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; IType parameterType; if (parameterIndex >= 0) parameterType = bestCandidate.ParameterTypes[parameterIndex]; else parameterType = SharedTypes.UnknownType; args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); } } return args; }
/// <summary> /// Performs a member lookup. /// </summary> public ResolveResult Lookup(ResolveResult targetResolveResult, string name, IList<IType> typeArguments, bool isInvocation) { bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult.Type); Predicate<IEntity> filter = delegate(IEntity entity) { return entity.Name == name && IsAccessible(entity, allowProtectedAccess); }; List<LookupGroup> lookupGroups = new List<LookupGroup>(); // This loop will handle base types before derived types. // The loop performs three jobs: // 1) It marks entries in lookup groups from base classes as removed when those members // are hidden by a derived class. // 2) It adds a new lookup group with the members from a declaring type. // 3) It replaces virtual members with the overridden version, placing the override in the // lookup group belonging to the base class. foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes(context)) { List<IType> newNestedTypes = null; List<IParameterizedMember> newMethods = null; IMember newNonMethod = null; IEnumerable<IType> typeBaseTypes = null; if (!isInvocation && !targetIsTypeParameter) { // Consider nested types only if it's not an invocation. // type.GetNestedTypes() is checking the type parameter count for an exact match, // so we don't need to do that in our filter. var nestedTypes = type.GetNestedTypes(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes); } IEnumerable<IMember> members; if (typeArguments.Count == 0) { // Note: IsInvocable-checking cannot be done as part of the filter; // because it must be done after type substitution. members = type.GetMembers(context, filter, GetMemberOptions.IgnoreInheritedMembers); if (isInvocation) members = members.Where(m => IsInvocable(m, context)); } else { // No need to check for isInvocation/isInvocable here: // we only fetch methods members = type.GetMethods(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); } AddMembers(type, members, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); if (newNestedTypes != null || newMethods != null || newNonMethod != null) lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); } // Remove interface members hidden by class members. if (targetIsTypeParameter) { // This can happen only with type parameters. RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); } return CreateResult(targetResolveResult, lookupGroups, name, typeArguments); }
bool ImplicitEnumerationConversion(ResolveResult rr, IType toType) { // C# 4.0 spec: §6.1.3 TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type); if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) { return NullableType.GetUnderlyingType(toType).IsEnum(); } return false; }
public BinaryOperatorResolveResult(IType resultType, ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs) : base(resultType) { if (lhs == null) { throw new ArgumentNullException("lhs"); } if (rhs == null) { throw new ArgumentNullException("rhs"); } this.Left = lhs; this.Operator = op; this.Right = rhs; }
// TODO: add support for user-defined conversions #region BetterConversion /// <summary> /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) /// </summary> /// <returns>0 = neither is better; 1 = t1 is better; 2 = t2 is better</returns> public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) { // TODO: implement the special logic for anonymous functions return(BetterConversion(resolveResult.Type, t1, t2)); }
Conversion AnonymousFunctionConversion(ResolveResult resolveResult, IType toType) { // C# 4.0 spec §6.5 Anonymous function conversions LambdaResolveResult f = resolveResult as LambdaResolveResult; if (f == null) { return(Conversion.None); } if (!f.IsAnonymousMethod) { // It's a lambda, so conversions to expression trees exist // (even if the conversion leads to a compile-time error, e.g. for statement lambdas) toType = UnpackExpressionTreeType(toType); } IMethod d = toType.GetDelegateInvokeMethod(); if (d == null) { return(Conversion.None); } IType[] dParamTypes = new IType[d.Parameters.Count]; for (int i = 0; i < dParamTypes.Length; i++) { dParamTypes[i] = d.Parameters[i].Type.Resolve(context); } IType dReturnType = d.ReturnType.Resolve(context); if (f.HasParameterList) { // If F contains an anonymous-function-signature, then D and F have the same number of parameters. if (d.Parameters.Count != f.Parameters.Count) { return(Conversion.None); } if (f.IsImplicitlyTyped) { // If F has an implicitly typed parameter list, D has no ref or out parameters. foreach (IParameter p in d.Parameters) { if (p.IsOut || p.IsRef) { return(Conversion.None); } } } else { // If F has an explicitly typed parameter list, each parameter in D has the same type // and modifiers as the corresponding parameter in F. for (int i = 0; i < f.Parameters.Count; i++) { IParameter pD = d.Parameters[i]; IParameter pF = f.Parameters[i]; if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut) { return(Conversion.None); } if (!dParamTypes[i].Equals(pF.Type.Resolve(context))) { return(Conversion.None); } } } } else { // If F does not contain an anonymous-function-signature, then D may have zero or more parameters of any // type, as long as no parameter of D has the out parameter modifier. foreach (IParameter p in d.Parameters) { if (p.IsOut) { return(Conversion.None); } } } return(f.IsValid(dParamTypes, dReturnType, this)); }
public ConditionalOperatorResolveResult(IType targetType, ResolveResult condition, ResolveResult @true, ResolveResult @false) : base(targetType) { if (condition == null) { throw new ArgumentNullException("condition"); } if (@true == null) { throw new ArgumentNullException("true"); } if (@false == null) { throw new ArgumentNullException("false"); } this.Condition = condition; this.True = @true; this.False = @false; }
protected void AssertError(Type expectedType, ResolveResult rr) { Assert.IsTrue(rr.IsError, rr.ToString() + " is not an error, but an error was expected"); Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); Assert.AreEqual(compilation.FindType(expectedType), rr.Type); }
/// <inheritdoc/> public void Resolved(AstNode node, ResolveResult result) { navigator.Resolved(node, result); }
static object[] MakeConstantArray(ResolveResult[] sizeArguments, ResolveResult[] initializerElements) { if (initializerElements == null) return null; for (int i = 0; i < initializerElements.Length; i++) { if (!initializerElements[i].IsCompileTimeConstant) return null; } if (sizeArguments != null && sizeArguments.Length > 0) { if (sizeArguments.Length > 1) { // 2D-arrays can't be constant return null; } if (!sizeArguments[0].IsCompileTimeConstant) return null; int expectedSize; try { expectedSize = (int)CSharpPrimitiveCast.Cast(TypeCode.Int32, sizeArguments[0].ConstantValue, true); } catch (InvalidCastException) { return null; } catch (OverflowException) { return null; } if (expectedSize != initializerElements.Length) return null; } object[] constants = new object[initializerElements.Length]; for (int i = 0; i < initializerElements.Length; i++) { constants[i] = initializerElements[i].ConstantValue; } return constants; }
/// <inheritdoc/> public void Resolved(AstNode node, ResolveResult result) { navigator.Resolved(node, result); }
/// <inheritdoc/> public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) { navigator.ProcessConversion(expression, result, conversion, targetType); }
static string GetText(ResolveResult result, string expression, out bool debuggerCanShowValue) { debuggerCanShowValue = false; return "FIXME"; // FIXME // debuggerCanShowValue = false; // if (result == null) { // // when pressing control, show the expression even when it could not be resolved // return (Control.ModifierKeys == Keys.Control) ? "" : null; // } // if (result is MixedResolveResult) // return GetText(((MixedResolveResult)result).PrimaryResult, expression, out debuggerCanShowValue); // else if (result is DelegateCallResolveResult) // return GetText(((DelegateCallResolveResult)result).Target, expression, out debuggerCanShowValue); // // IAmbience ambience = AmbienceService.GetCurrentAmbience(); // ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.UseFullyQualifiedMemberNames; // if (result is MemberResolveResult) { // return GetMemberText(ambience, ((MemberResolveResult)result).ResolvedMember, expression, out debuggerCanShowValue); // } else if (result is LocalResolveResult) { // LocalResolveResult rr = (LocalResolveResult)result; // ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedTypeNames // | ConversionFlags.ShowReturnType | ConversionFlags.ShowDefinitionKeyWord; // StringBuilder b = new StringBuilder(); // if (rr.IsParameter) // b.Append("parameter "); // else // b.Append("local variable "); // b.Append(ambience.Convert(rr.Field)); // if (currentDebugger != null) { // string currentValue = currentDebugger.GetValueAsString(rr.VariableName); // if (currentValue != null) { // debuggerCanShowValue = true; // b.Append(" = "); // if (currentValue.Length > 256) // currentValue = currentValue.Substring(0, 256) + "..."; // b.Append(currentValue); // } // } // return b.ToString(); // } else if (result is NamespaceResolveResult) { // return "namespace " + ((NamespaceResolveResult)result).Name; // } else if (result is TypeResolveResult) { // IClass c = ((TypeResolveResult)result).ResolvedClass; // if (c != null) // return GetMemberText(ambience, c, expression, out debuggerCanShowValue); // else // return ambience.Convert(result.ResolvedType); // } else if (result is MethodGroupResolveResult) { // MethodGroupResolveResult mrr = result as MethodGroupResolveResult; // IMethod m = mrr.GetMethodIfSingleOverload(); // IMethod m2 = mrr.GetMethodWithEmptyParameterList(); // if (m != null) // return GetMemberText(ambience, m, expression, out debuggerCanShowValue); // else if (ambience is VBNetAmbience && m2 != null) // return GetMemberText(ambience, m2, expression, out debuggerCanShowValue); // else // return "Overload of " + ambience.Convert(mrr.ContainingType) + "." + mrr.Name; // } else { // if (Control.ModifierKeys == Keys.Control) { // if (result.ResolvedType != null) // return "expression of type " + ambience.Convert(result.ResolvedType); // else // return "ResolveResult without ResolvedType"; // } else { // return null; // } // } }
public OverloadResolution PerformOverloadResolution(ICompilation compilation, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, bool allowOptionalParameters = true, bool checkForOverflow = false, CSharpConversions conversions = null) { Log.WriteLine("Performing overload resolution for " + this); Log.WriteCollection(" Arguments: ", arguments); var typeArgumentArray = this.TypeArguments.ToArray(); OverloadResolution or = new OverloadResolution(compilation, arguments, argumentNames, typeArgumentArray, conversions); or.AllowExpandingParams = allowExpandingParams; or.AllowOptionalParameters = allowOptionalParameters; or.CheckForOverflow = checkForOverflow; or.AddMethodLists(methodLists); if (allowExtensionMethods && !or.FoundApplicableCandidate) { // No applicable match found, so let's try extension methods. var extensionMethods = this.GetExtensionMethods(); if (extensionMethods.Any()) { Log.WriteLine("No candidate is applicable, trying {0} extension methods groups...", extensionMethods.Count()); ResolveResult[] extArguments = new ResolveResult[arguments.Length + 1]; extArguments[0] = new ResolveResult(this.TargetType); arguments.CopyTo(extArguments, 1); string[] extArgumentNames = null; if (argumentNames != null) { extArgumentNames = new string[argumentNames.Length + 1]; argumentNames.CopyTo(extArgumentNames, 1); } var extOr = new OverloadResolution(compilation, extArguments, extArgumentNames, typeArgumentArray, conversions); extOr.AllowExpandingParams = allowExpandingParams; extOr.AllowOptionalParameters = allowOptionalParameters; extOr.IsExtensionMethodInvocation = true; extOr.CheckForOverflow = checkForOverflow; foreach (var g in extensionMethods) { foreach (var method in g) { Log.Indent(); OverloadResolutionErrors errors = extOr.AddCandidate(method); Log.Unindent(); or.LogCandidateAddingResult(" Extension", method, errors); } if (extOr.FoundApplicableCandidate) { break; } } // For the lack of a better comparison function (the one within OverloadResolution // cannot be used as it depends on the argument set): if (extOr.FoundApplicableCandidate || or.BestCandidate == null) { // Consider an extension method result better than the normal result only // if it's applicable; or if there is no normal result. or = extOr; } } } Log.WriteLine("Overload resolution finished, best candidate is {0}.", or.GetBestCandidateWithSubstitutedTypeArguments()); return(or); }
ResolveResult CreateResult(ResolveResult targetResolveResult, List<LookupGroup> lookupGroups, string name, IList<IType> typeArguments) { // Remove all hidden groups lookupGroups.RemoveAll(g => g.AllHidden); if (lookupGroups.Count == 0) { // No members found return new UnknownMemberResolveResult(targetResolveResult.Type, name, typeArguments); } if (lookupGroups.Any(g => !g.MethodsAreHidden && g.Methods.Count > 0)) { // If there are methods, make a MethodGroupResolveResult. // Note that a conflict between a member and a method (possible with multiple interface inheritance) // is only a warning, not an error, and the C# compiler will prefer the method group. List<MethodListWithDeclaringType> methodLists = new List<MethodListWithDeclaringType>(); foreach (var lookupGroup in lookupGroups) { if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0) { var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType); foreach (var method in lookupGroup.Methods) { methodListWithDeclType.Add((IMethod)method); } methodLists.Add(methodListWithDeclType); } } return new MethodGroupResolveResult(targetResolveResult, name, methodLists, typeArguments); } // If there are ambiguities, report the most-derived result (last group) LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1]; if (resultGroup.NestedTypes != null && resultGroup.NestedTypes.Count > 0) { if (resultGroup.NestedTypes.Count > 1 || !resultGroup.NonMethodIsHidden || lookupGroups.Count > 1) return new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0]); else return new TypeResolveResult(resultGroup.NestedTypes[0]); } if (lookupGroups.Count > 1) { return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod, resultGroup.NonMethod.ReturnType.Resolve(context)); } else { return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod, context); } }
void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) { }