/// <summary> /// Given a node and its symbol, and a string representation of a code snippet for the hover, constructs the language server Hover /// object with the documentation (trivia) collected for the symbol. /// </summary> /// <param name="symbol">The symbol for wich documentation will be collected.</param> /// <param name="node">The node, whose range will be used to indicate the location back through the languer server protocol</param> /// <param name="snippet">The code snippet that will be used to represent the node and the symbol to the user.</param> private static Result <Hover, ResponseError> CreateScriptHoverWithCodeSnippetAndDocumentation(ISymbol symbol, INode node, string snippet) { Contract.Requires(symbol != null); Contract.Requires(node != null); Contract.Requires(!string.IsNullOrEmpty(snippet)); var documentation = DocumentationUtilities.GetDocumentationForSymbol(symbol); // The documentation strings are sent to the client as regular strings, wheras // the symbolAsString is a code snippet that is sent with language specifier to enable syntax highlighting. var codeSnippets = new List <MarkedString> { new MarkedString { Language = "DScript", Value = snippet, } }; codeSnippets.AddRange(documentation.Select(d => new MarkedString() { Value = d })); return(Result <Hover, ResponseError> .Success(new Hover { Contents = new SumType <SumType <string, MarkedString>, SumType <string, MarkedString>[], MarkupContent>( codeSnippets.Select(snip => new SumType <string, MarkedString>(snip)).ToArray()), Range = node.ToRange(), })); }
/// <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)); }