/// <summary> /// Handles the case of: /// function myFunction(args: "A" | "B" | "C"); /// const myVar = myFunc({completion happens here}); /// </summary> /// <remarks> /// The type is based on the expected type of the initializer. So we ask the type checker for /// that type. We then expand all union types and then return the unique set /// of possibilities. /// </remarks> internal static IEnumerable <CompletionItem> CreateCompletionFromCallExperssion(CompletionState completionState, INode completionNode) { var callExpression = completionNode.Cast <ICallExpression>(); // The user can type a random function that looks like a call expresion: // const myVar == fooBar(); // In which case we have nothing to resolve var callSymbol = completionState.TypeChecker.GetSymbolAtLocation(callExpression.Expression); if (callSymbol == null) { return(null); } var typeOfExpression = completionState.TypeChecker.GetTypeAtLocation(callExpression.Expression); if (typeOfExpression == null) { return(null); } var signature = completionState.TypeChecker.GetSignaturesOfType(typeOfExpression, SignatureKind.Call).FirstOrDefault(); var parameterIndex = DScriptFunctionSignature.GetActiveParameterIndex(callExpression, completionState.StartingNode); var parameterCount = signature?.Parameters?.Count ?? 0; if (parameterIndex >= 0 && parameterIndex < parameterCount) { var parameter = signature.Parameters[parameterIndex]; var type = completionState.TypeChecker.GetTypeAtLocation(parameter.GetFirstDeclarationOrDefault()); if (type != null) { var results = AddStringLiteralSymbolsFromType(type, completionState.TypeChecker); return(CreateCompletionItemsFromStrings(results)); } } return(null); }
/// <nodoc/> public Result <SignatureHelp, ResponseError> SignatureHelp(TextDocumentPositionParams positionParams, CancellationToken token) { // TODO: support cancellation if (!TryFindNode(positionParams, out var nodeAtPosition)) { return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } ICallExpression callExpression = GetContainingCallExpression(nodeAtPosition); if (callExpression == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var callSymbol = TypeChecker.GetSymbolAtLocation(callExpression.Expression); // If the user has typed a call expresion to a symbol (function) that doesn't exist (i.e. "foo.bar()") // Then just issue a debug writeline and a success instead of crashing. // There is going to be a red-line squiggle under it anyway. if (callSymbol == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find symbol for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var signature = TypeChecker.GetSignaturesOfType(TypeChecker.GetTypeAtLocation(callExpression.Expression), SignatureKind.Call).FirstOrDefault(); if (signature == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call signature for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var functionDeclaration = DScriptFunctionSignature.FromSignature(callSymbol.Name, signature); var parameterInformations = functionDeclaration.FormattedParameterNames.Select(formattedParameterName => new ParameterInformation() { Label = formattedParameterName, }); int activeParameterIndex = DScriptFunctionSignature.GetActiveParameterIndex(callExpression, nodeAtPosition); var signatureHelp = new SignatureHelp() { Signatures = new SignatureInformation[] { new SignatureInformation() { Label = functionDeclaration.FormattedFullFunctionSignature, Parameters = parameterInformations.ToArray(), Documentation = DocumentationUtilities.GetDocumentationForSymbolAsString(callSymbol), }, }, ActiveParameter = activeParameterIndex, ActiveSignature = 0, }; return(Result <SignatureHelp, ResponseError> .Success(signatureHelp)); }