Exemplo n.º 1
0
        public static IEnumerable <CompletionItem> CreateCompletionItemsForProcedures(IEnumerable <FunctionDeclaration> procedures, Node node, Dictionary <SignatureInformation, FunctionDeclaration> functionDeclarationSignatureDictionary, bool enablePublicFlag = true)
        {
            var completionItems = new List <CompletionItem>();

            foreach (var proc in procedures)
            {
                string inputParams = null, outputParams = null, inoutParams = null;

                if (proc.Profile != null)
                {
                    if (proc.Profile.InputParameters != null && proc.Profile.InputParameters.Count > 0)
                    {
                        inputParams = string.Format("INPUT {0}",
                                                    string.Join(", ",
                                                                proc.Profile.InputParameters.Select(
                                                                    p => string.Format("{0}({1})", p.DataName, p.DataType.Name))));
                    }
                    if (proc.Profile.InoutParameters != null && proc.Profile.InoutParameters.Count > 0)
                    {
                        inoutParams = string.Format("IN-OUT {0}",
                                                    string.Join(", ",
                                                                proc.Profile.InoutParameters.Select(
                                                                    p => string.Format("{0}({1})", p.DataName, p.DataType.Name))));
                    }
                    if (proc.Profile.OutputParameters != null && proc.Profile.OutputParameters.Count > 0)
                    {
                        outputParams = string.Format("OUTPUT {0}",
                                                     string.Join(", ",
                                                                 proc.Profile.OutputParameters.Select(
                                                                     p => string.Format("{0}({1})", p.DataName, p.DataType.Name))));
                    }
                }
                bool procIsPublic = false;
                if (enablePublicFlag)
                {
                    procIsPublic = ((FunctionDeclarationHeader)proc.CodeElement).Visibility == AccessModifier.Public
                                   &&
                                   !(node.SymbolTable.GetTableFromScope(SymbolTable.Scope.Declarations)
                                     .Functions.Values.Any(t => t.Contains(proc))
                                                                                    //Ignore public if proc is in the current program
                                     || proc.IsFlagSet(Node.Flag.NodeIsIntrinsic)); //Ignore public if proc is in intrinsic;
                }
                var procDisplayName = procIsPublic ? proc.VisualQualifiedName.ToString() : proc.Name;
                var completionItem  =
                    new CompletionItem(string.Format("{0} {1} {2} {3}", procDisplayName, inputParams, inoutParams, outputParams));
                completionItem.insertText = procIsPublic
                    ? string.Format("{0}::{1}", proc.VisualQualifiedName.Tail, proc.VisualQualifiedName.Head)
                    : proc.Name;
                completionItem.kind = proc.Profile != null && proc.Profile.IsFunction ? CompletionItemKind.Function : CompletionItemKind.Method;
                //Add specific data for eclipse completion & signatureHelper context
                completionItem.data = new object[3];
                var signatureInformation = ProcedureSignatureHelper.SignatureHelperSignatureFormatter(proc);
                ((object[])completionItem.data)[1] = signatureInformation;

                //Store the link between the hash and the procedure. This will help to determine the procedure parameter completion context later.
                functionDeclarationSignatureDictionary.Add(signatureInformation, proc);
                completionItems.Add(completionItem);
            }

            return(completionItems);
        }
Exemplo n.º 2
0
        public override SignatureHelp OnSignatureHelp(TextDocumentPosition parameters)
        {
            AnalyticsWrapper.Telemetry.TrackEvent("[SignatureHelp]", EventType.Completion); //Send event to analytics
            var fileCompiler = GetFileCompilerFromStringUri(parameters.uri);

            if (fileCompiler?.CompilationResultsForProgram?.ProcessedTokensDocumentSnapshot == null) //Semantic snapshot is not available
            {
                return(null);
            }

            var wrappedCodeElement = CodeElementFinder(fileCompiler, parameters.position).FirstOrDefault();

            if (wrappedCodeElement == null) //No codeelements found
            {
                return(null);
            }

            var node = CompletionFactory.GetMatchingNode(fileCompiler, wrappedCodeElement);

            //Get procedure name or qualified name
            string procedureName = CompletionFactoryHelpers.GetProcedureNameFromTokens(wrappedCodeElement.ArrangedConsumedTokens);

            //Try to get procedure by its name
            var calledProcedures =
                node.SymbolTable.GetFunctions(
                    p =>
                    p.Name.Equals(procedureName) ||
                    p.QualifiedName.ToString().Equals(procedureName), new List <SymbolTable.Scope>
            {
                SymbolTable.Scope.Declarations,
                SymbolTable.Scope.Intrinsic,
                SymbolTable.Scope.Namespace
            });
            var signatureHelp = new SignatureHelp();

            if (calledProcedures == null)
            {
                return(null);
            }

            if (calledProcedures.Count() == 1)
            {
                var calledProcedure = calledProcedures.First();
                //Create and return SignatureHelp object
                signatureHelp.signatures      = new SignatureInformation[1];
                signatureHelp.signatures[0]   = ProcedureSignatureHelper.SignatureHelperSignatureFormatter(calledProcedure);
                signatureHelp.activeSignature = 0; //Set the active signature as the one just created
                //Select the current parameter the user is expecting
                signatureHelp.activeParameter = ProcedureSignatureHelper.SignatureHelperParameterSelecter(calledProcedure, wrappedCodeElement, parameters.position);

                //There is only one possibility so the context can be set right now
                _SignatureCompletionContext = calledProcedure;

                return(signatureHelp);
            }

            //Else try to find the best matching signature

            //Get all given INPUT
            var givenInputParameters = CompletionFactoryHelpers.AggregateTokens(
                wrappedCodeElement.ArrangedConsumedTokens.SkipWhile(t => t.TokenType != TokenType.INPUT)
                .Skip(1)     //Ignore the INPUT Token
                .TakeWhile(t => !(t.TokenType == TokenType.OUTPUT || t.TokenType == TokenType.IN_OUT))).ToList();
            //Get all given OUTPUT
            var givenOutputParameters = CompletionFactoryHelpers.AggregateTokens(
                wrappedCodeElement.ArrangedConsumedTokens.SkipWhile(t => t.TokenType != TokenType.OUTPUT)
                .Skip(1)    //Ignore the INPUT Token
                .TakeWhile(t => !(t.TokenType == TokenType.INPUT || t.TokenType == TokenType.IN_OUT))).ToList();
            //Get all given INOUT
            var givenInoutParameters = CompletionFactoryHelpers.AggregateTokens(
                wrappedCodeElement.ArrangedConsumedTokens.SkipWhile(t => t.TokenType != TokenType.IN_OUT)
                .Skip(1)   //Ignore the INPUT Token
                .TakeWhile(t => !(t.TokenType == TokenType.OUTPUT || t.TokenType == TokenType.INPUT))).ToList();
            var totalGivenParameters = givenInputParameters.Count + givenInoutParameters.Count + givenOutputParameters.Count;

            var signatureInformation = new List <SignatureInformation>();

            _FunctionDeclarationSignatureDictionary.Clear();
            FunctionDeclaration bestmatchingProcedure = null;
            int previousMatchingWeight = 0, selectedSignatureIndex = 0;

            if (totalGivenParameters == 0)
            {
                foreach (var procedure in calledProcedures) //No parameters given, return all possibilities
                {
                    var formattedSignatureInformation = ProcedureSignatureHelper.SignatureHelperSignatureFormatter(procedure);
                    signatureInformation.Add(formattedSignatureInformation);
                    _FunctionDeclarationSignatureDictionary.Add(formattedSignatureInformation, procedure);
                }
            }
            else
            {
                foreach (var procedure in calledProcedures)
                {
                    //The commented parts allow to restrict the potential compatible signature to return to the client
                    int matchingWeight = 0;
                    //Test INPUT parameters
                    matchingWeight = matchingWeight + ProcedureSignatureHelper.ParametersTester(procedure.Profile.InputParameters, givenInputParameters, node);

                    //Test OUTPUT parameters
                    matchingWeight = matchingWeight + ProcedureSignatureHelper.ParametersTester(procedure.Profile.OutputParameters, givenOutputParameters, node);

                    //Test INOUT parameters
                    matchingWeight = matchingWeight + ProcedureSignatureHelper.ParametersTester(procedure.Profile.InoutParameters, givenInoutParameters, node);

                    if (matchingWeight > 0 && matchingWeight >= previousMatchingWeight && totalGivenParameters > 0)
                    {
                        if (matchingWeight > previousMatchingWeight)
                        {
                            signatureInformation.Clear();  //If the matchingWeight is superior than previous, it means that the previous signature is not precise enough.
                        }
                        var formattedSignatureInformation = ProcedureSignatureHelper.SignatureHelperSignatureFormatter(procedure);
                        signatureInformation.Add(formattedSignatureInformation);
                        _FunctionDeclarationSignatureDictionary.Add(formattedSignatureInformation, procedure);

                        previousMatchingWeight = matchingWeight;
                        bestmatchingProcedure  = procedure;
                    }
                    selectedSignatureIndex++;
                }
            }

            signatureHelp.signatures = signatureInformation.ToArray();

            if (signatureInformation.Count == 1)
            {
                _SignatureCompletionContext   = bestmatchingProcedure;                                                                                                     //Set the completion context
                signatureHelp.activeSignature = 0;                                                                                                                         //Select the only signature for the client
                signatureHelp.activeParameter = ProcedureSignatureHelper.SignatureHelperParameterSelecter(bestmatchingProcedure, wrappedCodeElement, parameters.position); //Select the current parameter
            }

            return(signatureHelp);
        }