Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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));
        }