public static IEnumerable <CompletionItem> GetCompletionForProcedure(FileCompiler fileCompiler, CodeElement codeElement, Token userFilterToken, Dictionary <SignatureInformation, FunctionDeclaration> functionDeclarationSignatureDictionary)
        {
            var node = GetMatchingNode(fileCompiler, codeElement);
            IEnumerable <FunctionDeclaration> procedures = null;
            IEnumerable <DataDefinition>      variables  = null;
            var completionItems = new List <CompletionItem>();

            if (node != null)
            {
                if (node.SymbolTable != null)
                {
                    var userFilterText = userFilterToken == null ? string.Empty : userFilterToken.Text;
                    procedures =
                        node.SymbolTable.GetFunctions(
                            f =>
                            f.VisualQualifiedName.ToString()
                            .StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase) ||
                            f.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase),
                            new List <SymbolTable.Scope>
                    {
                        SymbolTable.Scope.Declarations,
                        SymbolTable.Scope.Intrinsic,
                        SymbolTable.Scope.Namespace
                    });
                    variables = node.SymbolTable.GetVariables(da => da.Picture != null &&
                                                              da.DataType ==
                                                              Compiler.CodeElements.DataType.Alphanumeric &&
                                                              da.Name.StartsWith(userFilterText,
                                                                                 StringComparison.InvariantCultureIgnoreCase),
                                                              new List <SymbolTable.Scope> {
                        SymbolTable.Scope.Declarations, SymbolTable.Scope.Global
                    });
                }
            }

            completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForProcedures(procedures, node, functionDeclarationSignatureDictionary));

            foreach (var variable in variables)
            {
                var completionItem = new CompletionItem(string.Format("{0}", variable.Name));
                completionItem.insertText = variable.Name;
                completionItem.kind       = CompletionItemKind.Variable;
                completionItems.Add(completionItem);
            }


            return(completionItems);
        }
        public static IEnumerable <CompletionItem> GetCompletionForQualifiedName(Position position, FileCompiler fileCompiler, CodeElement codeElement, Token qualifiedNameSeparatorToken, Token userFilterToken, Dictionary <SignatureInformation, FunctionDeclaration> functionDeclarationSignatureDictionary)
        {
            var completionItems     = new List <CompletionItem>();
            var arrangedCodeElement = codeElement as CodeElementWrapper;
            var node           = GetMatchingNode(fileCompiler, codeElement);
            var userFilterText = userFilterToken == null ? string.Empty : userFilterToken.Text;

            //Get the token before MatchingToken
            var userTokenToSeek =
                arrangedCodeElement?.ArrangedConsumedTokens.ElementAt(
                    arrangedCodeElement.ArrangedConsumedTokens.IndexOf(qualifiedNameSeparatorToken) - 1);
            var qualifiedNameTokens = new List <Token>();

            if (arrangedCodeElement != null)
            {
                qualifiedNameTokens.AddRange(
                    arrangedCodeElement.ArrangedConsumedTokens?.Where(
                        t => (t?.TokenType == TokenType.UserDefinedWord || t?.TokenType == TokenType.QualifiedNameSeparator) && (t.EndColumn <= position.character && t.Line == position.line + 1) || t.Line < position.line + 1));
                //Remove all the userdefinedword token and also QualifiedNameToken
                arrangedCodeElement.ArrangedConsumedTokens = arrangedCodeElement.ArrangedConsumedTokens.Except(qualifiedNameTokens).ToList();
                //We only wants the token that in front of any QualifiedName
                //Get the first significant token (i.e CALL/TYPE/...)
                Token firstSignificantToken, tempUserFilterToken;
                CodeElementMatcher.MatchCompletionCodeElement(position, new List <CodeElementWrapper> {
                    arrangedCodeElement
                }, out tempUserFilterToken,
                                                              out firstSignificantToken);


                //Select the qualifiedName chain closest to cursor
                Token previousToken = null;
                qualifiedNameTokens.Reverse();
                var filteredQualifiedNameTokens = new List <Token>(); //Will contains all the tokens forming the qualifiedName chain.
                foreach (var token in qualifiedNameTokens)
                {
                    if (previousToken == null ||
                        ((previousToken.TokenType == TokenType.QualifiedNameSeparator && token.TokenType == TokenType.UserDefinedWord) ||
                         (token.TokenType == TokenType.QualifiedNameSeparator && previousToken.TokenType == TokenType.UserDefinedWord)))
                    {
                        filteredQualifiedNameTokens.Add(token);
                    }
                    else
                    {
                        break;
                    }

                    previousToken = token;
                }
                filteredQualifiedNameTokens.Reverse();

                //For MOVE INPUT OUTPUT variables etc.. , get all the children of a variable that are accessible
                //Try to find corresponding variables
                var qualifiedName = string.Join(".",
                                                filteredQualifiedNameTokens.Where(
                                                    t =>
                                                    t.TokenType == TokenType.UserDefinedWord &&
                                                    !(t.Text == userFilterText && userFilterToken != null &&
                                                      t.StartIndex == userFilterToken.StartIndex && t.EndColumn == userFilterToken.EndColumn) &&
                                                    ((firstSignificantToken != null && ((t.StartIndex >= firstSignificantToken.EndColumn && t.Line == firstSignificantToken.Line) || t.Line > firstSignificantToken.Line)) ||
                                                     firstSignificantToken == null) &&
                                                    ((t.EndColumn <= position.character && t.Line == position.line + 1) || t.Line < position.line + 1))
                                                .Select(t => t.Text));
                var possibleVariables = node.SymbolTable.GetVariablesExplicit(new URI(qualifiedName));

                if (possibleVariables != null && possibleVariables.Any())
                {
                    //Get children of a type to get completion possibilities
                    foreach (var variable in possibleVariables)
                    {
                        var children = new List <Node>();
                        if (variable.Children != null && variable.Children.Count > 0) //It's a variable with levels inside
                        {
                            children.AddRange(variable.Children);
                        }
                        else //It's a typed variable, we have to search for children in the type
                        {
                            var typeChildren = GetTypeChildrens(node.SymbolTable, variable);
                            if (typeChildren != null)
                            {
                                children.AddRange(typeChildren.Where(t => t.Name != null));
                            }
                        }

                        var computedChildrenList = new List <Node>();
                        foreach (var child in children)
                        {
                            GetNextRelevantChildren(child, computedChildrenList);
                        }

                        completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForVariables(
                                                     computedChildrenList.Where(
                                                         c => c.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase)) //Filter on user text
                                                     .Select(child => child as DataDefinition), false));
                    }
                }
                else
                { //If no variables found, it's could be a children declared in a typedef..
                    var children       = new List <Node>();
                    var potentialTypes =
                        node.SymbolTable.GetTypes(
                            t =>
                            t.Children != null &&
                            t.Children.Any(
                                tc => tc.Name != null && tc.Name.Equals(userTokenToSeek.Text, StringComparison.InvariantCultureIgnoreCase)),
                            new List <SymbolTable.Scope>
                    {
                        SymbolTable.Scope.Declarations,
                        SymbolTable.Scope.Global,
                        SymbolTable.Scope.Intrinsic,
                        SymbolTable.Scope.Namespace
                    });

                    foreach (var nodeType in potentialTypes.SelectMany(t => t.Children).Where(c => c != null && c.Name != null && c.Name.Equals(userTokenToSeek.Text, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        var nodeDataDef = nodeType as DataDefinition;
                        if (nodeDataDef == null)
                        {
                            continue;
                        }

                        var typeChildrens = GetTypeChildrens(node.SymbolTable, nodeDataDef);
                        if (typeChildrens != null)
                        {
                            children.AddRange(typeChildrens);
                        }
                    }

                    completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForVariables(
                                                 children.Where(
                                                     c => c.Name.StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase)) //Filter on user text
                                                 .Select(child => child as DataDefinition), false));
                }

                if (firstSignificantToken != null)
                {
                    switch (firstSignificantToken.TokenType)
                    {
                    case TokenType.CALL:
                    {
                        functionDeclarationSignatureDictionary.Clear();     //Clear to avoid key collision
                        //On CALL get possible procedures and functions in the seeked program
                        var programs = node.SymbolTable.GetPrograms(userTokenToSeek.Text);
                        if (programs != null && programs.Any())
                        {
                            var procedures =
                                programs.First()
                                .SymbolTable.GetFunctions(
                                    f =>
                                    f.Name.StartsWith(userFilterText,
                                                      StringComparison.InvariantCultureIgnoreCase) ||
                                    f.VisualQualifiedName.ToString()
                                    .StartsWith(userFilterText, StringComparison.InvariantCultureIgnoreCase),
                                    new List <SymbolTable.Scope>
                                {
                                    SymbolTable.Scope.Declarations
                                });
                            completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForProcedures(procedures, node, functionDeclarationSignatureDictionary, false));
                        }
                        break;
                    }

                    case TokenType.TYPE:
                    {
                        //On TYPE get possible public types in the seeked program
                        var programs = node.SymbolTable.GetPrograms(userTokenToSeek.Text);
                        if (programs != null && programs.Any())
                        {
                            var types =
                                programs.First()
                                .SymbolTable.GetTypes(
                                    t =>
                                    t.Name.StartsWith(userFilterText,
                                                      StringComparison.InvariantCultureIgnoreCase),
                                    new List <SymbolTable.Scope>
                                {
                                    SymbolTable.Scope.Declarations,
                                    SymbolTable.Scope.Global
                                });
                            completionItems.AddRange(CompletionFactoryHelpers.CreateCompletionItemsForType(types, node, false));
                        }
                        break;
                    }
                    }
                }
            }

            return(completionItems.Distinct());
        }