ResolveResult FallbackResolveMethod(InvocationExpression invocation, MethodGroupResolveResult mgrr, IReturnType[] argumentTypes) { // method not found, let's try if we can find a method if we violate the // accessibility rules MemberReferenceExpression mre = invocation.TargetObject as MemberReferenceExpression; if (mre != null) { List<IMethod> methods = mgrr.ContainingType.GetMethods().Where(m => resolver.IsSameName(m.Name, mre.MemberName)).ToList(); bool resultIsAcceptable; IMethod result = MemberLookupHelper.FindOverload( methods, argumentTypes, out resultIsAcceptable); if (result != null) { return CreateMemberResolveResult(result); } } // TODO: method still not found, now return invalid ResolveResult describing the expected method return null; }
IEnumerable<ICompletionData> CreateParameterCompletion(MethodGroupResolveResult resolveResult, CSharpResolver state, AstNode invocation, SyntaxTree unit, int parameter, bool controlSpace) { var result = new CompletionDataWrapper(this); var addedEnums = new HashSet<string>(); var addedDelegates = new HashSet<string>(); foreach (var method in resolveResult.Methods) { CreateParameterForInvocation(result, method, state, parameter, addedEnums, addedDelegates); } foreach (var methods in resolveResult.GetEligibleExtensionMethods (true)) { foreach (var method in methods) { if (resolveResult.Methods.Contains (method)) continue; CreateParameterForInvocation(result, new ReducedExtensionMethod (method), state, parameter, addedEnums, addedDelegates); } } foreach (var method in resolveResult.Methods) { if (parameter < method.Parameters.Count && method.Parameters [parameter].Type.Kind == TypeKind.Delegate) { AutoSelect = false; AutoCompleteEmptyMatch = false; } foreach (var p in method.Parameters) { result.AddNamedParameterVariable(p); } } if (!controlSpace) { if (addedEnums.Count + addedDelegates.Count == 0) { return Enumerable.Empty<ICompletionData>(); } AutoCompleteEmptyMatch = false; AutoSelect = false; } AddContextCompletion(result, state, invocation); // resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc); // if (addedDelegates.Count > 0) { // foreach (var data in result.Result) { // if (data is MemberCompletionData) // ((MemberCompletionData)data).IsDelegateExpected = true; // } // } return result.Result; }
private static string GetText(ResolveResult result) { if (result == null) { return(null); } if (result is MixedResolveResult) { return(GetText(((MixedResolveResult)result).PrimaryResult)); } IAmbience ambience = MainForm.IsVisualBasic ? (IAmbience) new VBNetAmbience() : new CSharpAmbience(); ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowAccessibility; if (result is MemberResolveResult) { return(GetMemberText(ambience, ((MemberResolveResult)result).ResolvedMember)); } else if (result is LocalResolveResult) { LocalResolveResult rr = (LocalResolveResult)result; ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedTypeNames | ConversionFlags.ShowReturnType; StringBuilder b = new StringBuilder(); if (rr.IsParameter) { b.Append("parameter "); } else { b.Append("local variable "); } b.Append(ambience.Convert(rr.Field)); 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)); } else { return(ambience.Convert(result.ResolvedType)); } } else if (result is MethodGroupResolveResult) { MethodGroupResolveResult mrr = result as MethodGroupResolveResult; IMethod m = mrr.GetMethodIfSingleOverload(); if (m != null) { return(GetMemberText(ambience, m)); } else { return("Overload of " + ambience.Convert(mrr.ContainingType) + "." + mrr.Name); } } else { return(null); } }
static string GetText(ResolveResult result, string expression, out bool debuggerCanShowValue) { 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(); if (m != null) { return(GetMemberText(ambience, m, 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 void MethodNameResolveIsWriteLine() { MethodGroupResolveResult methodResolveResult = (MethodGroupResolveResult)resolveResult; Assert.AreEqual("WriteLine", methodResolveResult.Name); }
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { if (resolver.Language == SupportedLanguage.CSharp && resolver.CallingClass != null) { if (invocationExpression.TargetObject is ThisReferenceExpression) { // call to constructor return(ResolveConstructorOverload(resolver.CallingClass, invocationExpression.Arguments)); } else if (invocationExpression.TargetObject is BaseReferenceExpression) { return(ResolveConstructorOverload(resolver.CallingClass.BaseType, invocationExpression.Arguments)); } } ResolveResult rr = Resolve(invocationExpression.TargetObject); MixedResolveResult mixedRR = rr as MixedResolveResult; if (mixedRR != null) { rr = mixedRR.PrimaryResult; } MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; if (mgrr != null) { if (resolver.Language == SupportedLanguage.VBNet && mgrr.Methods.All(mg => mg.Count == 0)) { return(CreateMemberResolveResult(GetVisualBasicIndexer(invocationExpression))); } IReturnType[] argumentTypes = invocationExpression.Arguments.Select <Expression, IReturnType>(ResolveType).ToArray(); MemberResolveResult firstResult = null; foreach (MethodGroup methodGroup in mgrr.Methods) { bool resultIsAcceptable; IMethod method; if (methodGroup.IsExtensionMethodGroup) { IReturnType[] extendedTypes = new IReturnType[argumentTypes.Length + 1]; extendedTypes[0] = mgrr.ContainingType; argumentTypes.CopyTo(extendedTypes, 1); method = MemberLookupHelper.FindOverload(methodGroup, extendedTypes, out resultIsAcceptable); } else { method = MemberLookupHelper.FindOverload(methodGroup, argumentTypes, out resultIsAcceptable); } MemberResolveResult result = CreateMemberResolveResult(method); if (result != null && methodGroup.IsExtensionMethodGroup) { result.IsExtensionMethodCall = true; } if (resultIsAcceptable) { return(result); } if (firstResult == null) { firstResult = result; } } if (firstResult != null) { return(firstResult); } else { return(FallbackResolveMethod(invocationExpression, mgrr, argumentTypes)); } } else if (rr != null && rr.ResolvedType != null) { IClass c = rr.ResolvedType.GetUnderlyingClass(); if (c != null && c.ClassType == ClassType.Delegate) { // We don't want to show "System.EventHandler.Invoke" in the tooltip // of "EventCall(this, EventArgs.Empty)", we just show the event/delegate for now // but for DelegateCall(params).* completion, we use the delegate's // return type instead of the delegate type itself IMethod method = rr.ResolvedType.GetMethods().FirstOrDefault(innerMethod => innerMethod.Name == "Invoke"); if (method != null) { return(new DelegateCallResolveResult(rr, method)); } } } if (resolver.Language == SupportedLanguage.VBNet) { return(CreateMemberResolveResult(GetVisualBasicIndexer(invocationExpression))); } return(null); }
/// <summary> /// Tries to find a resource reference in the specified expression. /// </summary> /// <param name="expressionResult">The ExpressionResult for the expression.</param> /// <param name="expr">The AST representation of the full expression.</param> /// <param name="resolveResult">SharpDevelop's ResolveResult for the expression.</param> /// <param name="caretLine">The 0-based line where the expression is located.</param> /// <param name="caretColumn">The 0-based column where the expression is located.</param> /// <param name="fileName">The name of the source file where the expression is located.</param> /// <param name="fileContent">The content of the source file where the expression is located.</param> /// <param name="expressionFinder">The ExpressionFinder for the file.</param> /// <param name="charTyped">The character that has been typed at the caret position but is not yet in the buffer (this is used when invoked from code completion), or <c>null</c>.</param> /// <returns>A ResourceResolveResult describing the referenced resource, or <c>null</c>, if this expression does not reference a resource using the standard .NET framework classes.</returns> public ResourceResolveResult Resolve(ExpressionResult expressionResult, Expression expr, ResolveResult resolveResult, int caretLine, int caretColumn, string fileName, string fileContent, IExpressionFinder expressionFinder, char?charTyped) { /* * We need to catch the following cases here: * * Something.GetString( * Something.GetString("...") * Something.ApplyResources(obj, "...") * Something[ * Something["..."] * */ if (charTyped == '(') { // Something.GetString // This is a MethodResolveResult and we need the reference to "Something", // which is the next outer expression. // This is only valid when invoked from code completion // and the method invocation character ('(' in C# and VB) // has been typed. // This code is also reused when reducing a complete InvocationExpression // (MemberResolveResult) to the method reference by passing '(' as // charTyped explicitly. MethodGroupResolveResult methrr = resolveResult as MethodGroupResolveResult; if (methrr != null) { if ((methrr.Name == "GetString" || methrr.Name == "GetObject" || methrr.Name == "GetStream" || methrr.Name == "ApplyResources") && (resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return(ResolveResource(resolveResult, expr)); } else { return(null); } } } // Do not use "else if" here. // '(' is also the IndexerExpressionStartToken for VB, // so the "else" block further down might still apply. if (charTyped == null) { // A MemberResolveResult with a complete expression // must only be considered a valid resource reference // when Resolve is not invoked from code completion // (i.e. charTyped == null) because this indicates // that the resource reference is already before the typed character // and we are not interested in the following expression. // This may happen when typing something like: // Something.GetString("...")[ MemberResolveResult mrr = resolveResult as MemberResolveResult; if (mrr != null) { if (mrr.ResolvedMember is IMethod && (mrr.ResolvedMember.Name == "GetString" || mrr.ResolvedMember.Name == "GetObject" || mrr.ResolvedMember.Name == "GetStream" || mrr.ResolvedMember.Name == "ApplyResources")) { // Something.GetString("...") // This is a MemberResolveResult and we need the reference to "Something". // The expression finder may only remove the string literal, so // we have to call Resolve again in this case to resolve // the method reference. if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { if (resolveResult is MethodGroupResolveResult) { return(this.Resolve(expressionResult, expr, resolveResult, caretLine, caretColumn, fileName, fileContent, expressionFinder, '(')); } else { return(ResolveResource(resolveResult, expr)); } } else { return(null); } } else if (expr is IndexerExpression && IsResourceManager(mrr.ResolvedMember.DeclaringType.DefaultReturnType, fileName)) { // Something["..."] is an IndexerExpression. // We need the reference to Something and this is // the next outer expression. if ((resolveResult = NRefactoryAstCacheService.ResolveNextOuterExpression(ref expressionResult, caretLine, caretColumn, fileName, fileContent, expressionFinder)) != null) { return(ResolveResource(resolveResult, expr)); } else { return(null); } } } } else { // This request is triggered from code completion. // The only case that has not been caught above is: // Something[ // The reference to "Something" is already in this expression. // So we have to test the trigger character against the // indexer expression start token of the file's language. LanguageProperties lp = NRefactoryResourceResolver.GetLanguagePropertiesForFile(fileName); if (lp != null && !String.IsNullOrEmpty(lp.IndexerExpressionStartToken) && lp.IndexerExpressionStartToken[0] == charTyped) { #if DEBUG LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: Indexer expression start typed, ResolveResult: " + resolveResult.ToString()); LoggingService.Debug("ResourceToolkit: BclNRefactoryResourceResolver: -> Expression: " + expr.ToString()); #endif return(ResolveResource(resolveResult, expr)); } } return(null); }
/// <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="ConversionResolveResult"/>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="InvocationResolveResult.InitializerStatements"/> /// </param> /// <returns>InvocationResolveResult or ErrorResolveResult</returns> public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null, bool allowProtectedAccess = false, IList<ResolveResult> initializerStatements = null) { if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { ResolveResult input = arguments[0]; IMethod invoke = input.Type.GetDelegateInvokeMethod(); if (invoke != null) { input = new MethodGroupResolveResult( input, invoke.Name, methods: new[] { new MethodListWithDeclaringType(invoke.DeclaringType) { invoke } }, typeArguments: EmptyList<IType>.Instance ); } return Convert(input, type); } OverloadResolution or = CreateOverloadResolution(arguments, argumentNames); MemberLookup lookup = CreateMemberLookup(); var allApplicable = (arguments.Any(a => a.Type.Kind == TypeKind.Dynamic) ? new List<IMethod>() : null); foreach (IMethod ctor in type.GetConstructors()) { if (lookup.IsAccessible(ctor, allowProtectedAccess)) { var orErrors = or.AddCandidate(ctor); if (allApplicable != null && OverloadResolution.IsApplicable(orErrors)) allApplicable.Add(ctor); } else or.AddCandidate(ctor, OverloadResolutionErrors.Inaccessible); } if (allApplicable != null && allApplicable.Count > 1) { // If we have dynamic arguments, we need to represent the invocation as a dynamic invocation if there is more than one applicable constructor. return new DynamicInvocationResolveResult(new MethodGroupResolveResult(null, allApplicable[0].Name, new[] { new MethodListWithDeclaringType(type, allApplicable) }, null), DynamicInvocationType.ObjectCreation, AddArgumentNamesIfNecessary(arguments, argumentNames), initializerStatements); } if (or.BestCandidate != null) { return or.CreateResolveResult(null, initializerStatements); } else { return new ErrorResolveResult(type); } }
IEnumerable<ICompletionData> CreateParameterCompletion (MethodGroupResolveResult resolveResult, CppResolver state, AstNode invocation, int parameter, bool controlSpace) { var result = new CompletionDataWrapper (this); var addedEnums = new HashSet<string> (); var addedDelegates = new HashSet<string> (); foreach (var method in resolveResult.Methods) { if (method.Parameters.Count <= parameter) continue; var resolvedType = method.Parameters [parameter].Type; if (resolvedType.Kind == TypeKind.Enum) { if (addedEnums.Contains (resolvedType.ReflectionName)) continue; addedEnums.Add (resolvedType.ReflectionName); AddEnumMembers (result, resolvedType, state); } else if (resolvedType.Kind == TypeKind.Delegate) { // if (addedDelegates.Contains (resolvedType.DecoratedFullName)) // continue; // addedDelegates.Add (resolvedType.DecoratedFullName); // string parameterDefinition = AddDelegateHandlers (completionList, resolvedType, false, addedDelegates.Count == 1); // string varName = "Handle" + method.Parameters [parameter].ReturnType.Name + method.Parameters [parameter].Name; // result.Add (new EventCreationCompletionData (document, varName, resolvedType, null, parameterDefinition, resolver.Unit.GetMemberAt (location), resolvedType) { AddSemicolon = false }); } } if (!controlSpace) { if (addedEnums.Count + addedDelegates.Count == 0) return Enumerable.Empty<ICompletionData> (); AutoCompleteEmptyMatch = false; AutoSelect = false; } AddContextCompletion (result, state, invocation); // resolver.AddAccessibleCodeCompletionData (ExpressionContext.MethodBody, cdc); // if (addedDelegates.Count > 0) { // foreach (var data in result.Result) { // if (data is MemberCompletionData) // ((MemberCompletionData)data).IsDelegateExpected = true; // } // } return result.Result; }
public virtual object VisitMethodGroupResolveResult(MethodGroupResolveResult rr, object data) { VisitChildResolveResults(rr, data); return(null); }
public JsNode VisitMethodGroupResolveResult(MethodGroupResolveResult res) { var info = res.GetInfo(); IMethod me; if (info != null && info.Conversion != null && info.Conversion.Method != null) { me = info.Conversion.Method; } else //happens when invoking a method with overloads, and a parameter is dynamic { var list = res.Methods.ToList(); if (list.Count == 0) { throw new Exception("Method group not resolved to any method"); } else if (list.Count == 1) { me = list[0]; } else { me = list[0]; } //TODO: verify all methods has the same js name } var isExtensionMethodStyle = me.IsExtensionMethod && !(res.TargetResult is TypeResolveResult) && info != null && info.Conversion != null && info.Conversion.DelegateCapturesFirstArgument;//TODO: IsExtensionMethodStyle(new CsInvocationExpression { entity = me, expression = node }); JsExpression firstPrm = null; if (isExtensionMethodStyle) { firstPrm = (JsExpression)Visit(res.TargetResult); } var node2 = SkJs.EntityToMember(me); JsExpression node3; JsExpression instanceContext = null; if (me.IsStatic || res.TargetResult == null) //getting ThisResolveResult even on static methods, getting TargetResult=null when MethodGroupResolveResult when using delegates { node3 = node2; } else { instanceContext = VisitExpression(res.TargetResult); node3 = instanceContext.Member(node2); } if (info != null && (instanceContext != null || firstPrm != null)) { var conv = info.Conversion; if (info.ConversionTargetType != null && !UseNativeFunctions(info.ConversionTargetType))//delegate type { var parentMethod = info.Nodes.FirstOrDefault().GetCurrentMethod(); if (parentMethod == null || !Sk.ForceDelegatesAsNativeFunctions(parentMethod)) { if (parentMethod == null) { Log.Warn(info.Nodes.FirstOrDefault(), "GetParentMethod() returned null"); } var func = (JsExpression)node2; if (instanceContext != null) { node3 = CreateJsDelegate(instanceContext, func); } else if (firstPrm != null) { node3 = CreateJsExtensionDelegate(firstPrm, func); } } } } return(node3); }
public object VisitMethodGroupResolveResult(MethodGroupResolveResult res) { throw new NotImplementedException(); }
protected virtual void SetupDataProvider(string fileName, IDocument document, ExpressionResult expressionResult, int caretLineNumber, int caretColumn) { bool constructorInsight = false; if (expressionResult.Context == ExpressionContext.Attribute) { constructorInsight = true; } else if (expressionResult.Context.IsObjectCreation) { constructorInsight = true; expressionResult.Context = ExpressionContext.Type; } else if (expressionResult.Context == ExpressionContext.BaseConstructorCall) { constructorInsight = true; } ResolveResult results = ParserService.Resolve(expressionResult, caretLineNumber, caretColumn, fileName, document.TextContent); if (results == null) { return; } LanguageProperties language = ParserService.CurrentProjectContent.Language; TypeResolveResult trr = results as TypeResolveResult; if (trr == null && language.AllowObjectConstructionOutsideContext) { if (results is MixedResolveResult) { trr = (results as MixedResolveResult).TypeResult; } } if (trr != null && !constructorInsight) { if (language.AllowObjectConstructionOutsideContext) { constructorInsight = true; } } if (constructorInsight) { if (trr != null || expressionResult.Context == ExpressionContext.BaseConstructorCall) { if (results.ResolvedType != null) { methods.AddRange(GetConstructorMethods(results.ResolvedType.GetMethods())); } } } else { MethodGroupResolveResult result = results as MethodGroupResolveResult; if (result == null) { return; } bool classIsInInheritanceTree = false; if (result.CallingClass != null) { classIsInInheritanceTree = result.CallingClass.IsTypeInInheritanceTree(result.ContainingType.GetUnderlyingClass()); } foreach (IMethod method in result.ContainingType.GetMethods()) { if (language.NameComparer.Equals(method.Name, result.Name)) { if (method.IsAccessible(result.CallingClass, classIsInInheritanceTree)) { methods.Add(method); } } } if (methods.Count == 0 && result.CallingClass != null && language.SupportsExtensionMethods) { ArrayList list = new ArrayList(); ResolveResult.AddExtensions(language, list, result.CallingClass, result.ContainingType); foreach (IMethodOrProperty mp in list) { if (language.NameComparer.Equals(mp.Name, result.Name) && mp is IMethod) { DefaultMethod m = (DefaultMethod)mp.CreateSpecializedMember(); // for the insight window, remove first parameter and mark the // method as normal - this is required to show the list of // parameters the method expects. m.IsExtensionMethod = false; m.Parameters.RemoveAt(0); methods.Add(m); } } } } }
public virtual TResult VisitMethodGroupResolveResult(MethodGroupResolveResult rr, TData data) { VisitChildResolveResults(rr, data); return(default(TResult)); }
IEnumerable<IMethod> CollectMethods(AstNode resolvedNode, MethodGroupResolveResult resolveResult) { var lookup = new MemberLookup(ctx.CurrentTypeDefinition, Compilation.MainAssembly); bool onlyStatic = false; if (resolvedNode is IdentifierExpression && currentMember != null && currentMember.IsStatic || resolveResult.TargetResult is TypeResolveResult) { onlyStatic = true; } var methods = new List<IMethod>(); foreach (var method in resolveResult.Methods) { if (method.IsConstructor) { continue; } if (!lookup.IsAccessible (method, true)) continue; if (onlyStatic && !method.IsStatic) { continue; } if (method.IsShadowing) { for (int j = 0; j < methods.Count; j++) { if (ParameterListComparer.Instance.Equals(methods[j].Parameters, method.Parameters)) { methods.RemoveAt (j); j--; } } } methods.Add (method); } foreach (var m in methods) { yield return m; } foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) { foreach (var method in extMethods) { if (methods.Contains (method)) continue; yield return new ReducedExtensionMethod (method); } } }