public static ResolveResult Resolve(Lazy <ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node, CancellationToken cancellationToken = default(CancellationToken)) { node = syntaxTree.GetNodeAt(location); if (node == null || node is ArrayInitializerExpression) { return(null); } if (node.Parent is UsingAliasDeclaration && node.Role == UsingAliasDeclaration.AliasRole) { var r = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile); return(r.Resolve(((UsingAliasDeclaration)node.Parent).Import, cancellationToken)); } 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 || node.Role == IndexerDeclaration.ThisKeywordRole) { // 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 if (node.Parent is BinaryOperatorExpression || node.Parent is UnaryOperatorExpression) { // Resolve user-defined operator 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; } else if (node is ThisReferenceExpression && node.Parent is IndexerExpression) { 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; } // TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile); ResolveResult rr = resolver.Resolve(node, cancellationToken); if (rr is MethodGroupResolveResult mgrr) { // For method groups, resolve the parent invocation instead. if (parentInvocation != null) { return(resolver.Resolve(parentInvocation)); } if (node is Expression) { // If it's not an invocation, try if it's a conversion to a delegate type: Conversion c = resolver.GetConversion((Expression)node, cancellationToken); if (c.IsMethodGroupConversion) { return(new MemberResolveResult(mgrr.TargetResult, c.Method)); } } } return(rr); }
public CastResolveResult(IType targetType, ResolveResult input, Conversion conversion, bool checkForOverflow) : base(targetType, input, conversion, checkForOverflow) { }
protected void AssertConversion(ResolveResult conversionResult, ResolveResult expectedRR, Conversion expectedConversion, string text) { if (expectedConversion == Conversion.IdentityConversion) { Assert.AreSame(expectedRR, conversionResult, "Expected no " + text); } else { ConversionResolveResult crr = conversionResult as ConversionResolveResult; Assert.IsNotNull(crr, "Could not find ConversionResolveResult for " + text); Assert.AreEqual(expectedConversion, crr.Conversion, text); Assert.AreSame(expectedRR, crr.Input, "Input of " + text); } }
void CheckApplicability(Candidate candidate) { // C# 4.0 spec: §7.5.3.1 Applicable function member // Test whether parameters were mapped the correct number of arguments: int[] argumentCountPerParameter = new int[candidate.ParameterTypes.Length]; foreach (int parameterIndex in candidate.ArgumentToParameterMap) { if (parameterIndex >= 0) { argumentCountPerParameter[parameterIndex]++; } } for (int i = 0; i < argumentCountPerParameter.Length; i++) { if (candidate.IsExpandedForm && i == argumentCountPerParameter.Length - 1) { continue; // any number of arguments is fine for the params-array } if (argumentCountPerParameter[i] == 0) { if (this.AllowOptionalParameters && candidate.Parameters[i].IsOptional) { candidate.HasUnmappedOptionalParameters = true; } else { candidate.AddError(OverloadResolutionErrors.MissingArgumentForRequiredParameter); } } else if (argumentCountPerParameter[i] > 1) { candidate.AddError(OverloadResolutionErrors.MultipleArgumentsForSingleParameter); } } candidate.ArgumentConversions = new Conversion[arguments.Length]; // Test whether argument passing mode matches the parameter passing mode for (int i = 0; i < arguments.Length; i++) { int parameterIndex = candidate.ArgumentToParameterMap[i]; if (parameterIndex < 0) { candidate.ArgumentConversions[i] = Conversion.None; continue; } ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; if (brrr != null) { if ((brrr.IsOut && !candidate.Parameters[parameterIndex].IsOut) || (brrr.IsRef && !candidate.Parameters[parameterIndex].IsRef)) { candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } } else { if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) { candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } } IType parameterType = candidate.ParameterTypes[parameterIndex]; Conversion c = conversions.ImplicitConversion(arguments[i], parameterType); candidate.ArgumentConversions[i] = c; if (IsExtensionMethodInvocation && parameterIndex == 0) { // First parameter to extension method must be an identity, reference or boxing conversion if (!(c == Conversion.IdentityConversion || c == Conversion.ImplicitReferenceConversion || c == Conversion.BoxingConversion)) { candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); } } else { if ((!c.IsValid && !c.IsUserDefined && !c.IsMethodGroupConversion) && parameterType.Kind != TypeKind.Unknown) { candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); } } } }
/// <inheritdoc/> public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) { navigator.ProcessConversion(expression, result, conversion, targetType); }
void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) { }