/// <summary>
        /// This method parses the current line, and determines which suggestions to show for code completion (intellisense)
        /// </summary>
        /// <param name="session"></param>
        private void UpdateCodeComplete(CompletionSession session)
        {
            //parse current line
            //set results
            //set filter
            try
            {
                ParseQueueProcessor.ShowProgressDialog = false; //maybe not actually required anymore

                var currentLine = VisualStudio.GetCurrentLine();

                var currentIndex = VisualStudio.GetCursorPositionInLine();

                var lineParser = new FortranStatementParser();

                var beginOfStatement = 0;

                var statement     = lineParser.FindEffectiveStatementAtOffset(currentLine, currentIndex, out beginOfStatement);
                var fullStatement = currentLine.Substring(beginOfStatement, currentIndex - beginOfStatement);

                var currentMember = GetCurrent <IMember>();

                ShowMethodSignatureAsToolTip(session, currentMember, currentLine, currentIndex);

                IList <INameable> codeCompleteOptions;
                var filter = "";
                var addLanguageKeywords = false;
                var codeElementsInScope =
                    FortranSyntaxTreeModel.GetElementsAvailableInScope(SyntaxTreeMaintainer.GetSyntaxTrees(),
                                                                       currentMember);

                // are we in a 'call something' statement?
                var callMatch = callRegex.Match(statement);
                if (callMatch.Success)
                {
                    //only subroutines
                    codeCompleteOptions          = codeElementsInScope.OfType <Subroutine>().Cast <INameable>().ToList(); //subroutines only
                    session.InsertionIndexInLine = beginOfStatement + callMatch.Groups[1].Index;
                    filter = callMatch.Groups[1].Value;
                }
                else if (!statement.Contains('%')) //local scope
                {
                    if (statement.Length > 0 &&
                        FortranParseHelper.IsWhiteSpace(statement[statement.Length - 1]))
                    {
                        //reset: wrong statement:
                        beginOfStatement += statement.Length;
                        statement         = "";
                    }

                    codeCompleteOptions          = codeElementsInScope.Where(ce => !(ce is Subroutine)).ToList(); //subroutines only available after a 'call'
                    session.InsertionIndexInLine = beginOfStatement;
                    filter = statement;
                    addLanguageKeywords = true;
                }
                else // nested in type, eg: channel % sourceNode % id
                {
                    var elements = FortranParseHelper.SplitElementsInStatement(statement, fullStatement, ref beginOfStatement, out filter);

                    if (elements.Count < 1)
                    {
                        throw new NotSupportedException("help!");
                    }

                    var variableName = elements[0];

                    var matchingVariable = codeElementsInScope
                                           .OfType <Variable>()
                                           .FirstOrDefault(lv => String.Equals(lv.Name, variableName, StringComparison.InvariantCultureIgnoreCase));

                    var typeOfVariable = matchingVariable.TypeString;

                    var currentType = codeElementsInScope
                                      .OfType <Type>()
                                      .FirstOrDefault(tp => String.Equals(tp.Name, typeOfVariable, StringComparison.InvariantCultureIgnoreCase));

                    for (int i = 1; i < elements.Count; i++)
                    {
                        if (currentType == null)
                        {
                            break;
                        }

                        var propertyName = elements[i];
                        var property     = GetElementsOfType(currentType).FirstOrDefault(vf => String.Equals(vf.Name, propertyName, StringComparison.InvariantCultureIgnoreCase));

                        typeOfVariable = property.TypeString;

                        currentType = codeElementsInScope
                                      .OfType <Type>()
                                      .FirstOrDefault(tp => String.Equals(tp.Name, typeOfVariable, StringComparison.InvariantCultureIgnoreCase));
                    }

                    if (currentType == null)
                    {
                        codeCompleteOptions = new INameable[] { }
                    }
                    ;
                    else
                    {
                        codeCompleteOptions = GetElementsOfType(currentType).Cast <INameable>().ToList();
                    }

                    session.InsertionIndexInLine = beginOfStatement;
                }

                // gather all results
                var completionItems = codeCompleteOptions.Select(e => new CompletionItem(e.Name, FortranIconProvider.GetIconForMember(e))
                {
                    ToolTip = GetTooltipForMember(currentMember, e)
                }).ToList();
                if (addLanguageKeywords)
                {
                    foreach (var keyword in fortranKeywords)
                    {
                        completionItems.Add(new CompletionItem(keyword, null));
                    }

                    foreach (var intrinsic in fortranIntrinsics)
                    {
                        completionItems.Add(new CompletionItem(intrinsic.Key, IntrinsicIcon)
                        {
                            ToolTip = intrinsic.Value
                        });
                    }
                }
                session.SetCompletionSet(completionItems, filter);
            }
            catch (Exception e)
            {
                Log.Error("Error while updating code complete", e);
            }
            finally
            {
                ParseQueueProcessor.ShowProgressDialog = true; //messes with intellisense popup
            }
        }
        /// <summary>
        /// This method parses the current line, and determines which suggestions to show for code completion (intellisense)
        /// </summary>
        /// <param name="session"></param>
        private void UpdateCodeComplete(CompletionSession session)
        {
            //parse current line
            //set results
            //set filter
            try
            {
                ParseQueueProcessor.ShowProgressDialog = false; //maybe not actually required anymore

                var currentLine = VisualStudio.GetCurrentLine();

                var currentIndex = VisualStudio.GetCursorPositionInLine();

                var lineParser = new FortranStatementParser();

                var beginOfStatement = 0;

                var statement     = lineParser.FindEffectiveStatementAtOffset(currentLine, currentIndex, out beginOfStatement);
                var fullStatement = currentLine.Substring(beginOfStatement, currentIndex - beginOfStatement);

                var currentMember = GetCurrent <IMember>();

                ShowMethodSignatureAsToolTip(session, currentMember, currentLine, currentIndex);

                IList <INameable> codeCompleteOptions;
                var filter = "";
                var addLanguageKeywords = false;
                var codeElementsInScope =
                    FortranSyntaxTreeModel.GetElementsAvailableInScope(SyntaxTreeMaintainer.GetSyntaxTrees(),
                                                                       currentMember);

                // are we in a 'call something' statement?
                var callMatch = callRegex.Match(statement);
                if (callMatch.Success)
                {
                    //only subroutines
                    codeCompleteOptions          = codeElementsInScope.OfType <Subroutine>().Cast <INameable>().ToList(); //subroutines only
                    session.InsertionIndexInLine = beginOfStatement + callMatch.Groups[1].Index;
                    filter = callMatch.Groups[1].Value;
                }
                else if (!statement.Contains('%')) //local scope
                {
                    if (statement.Length > 0 &&
                        FortranParseHelper.IsWhiteSpace(statement[statement.Length - 1]))
                    {
                        //reset: wrong statement:
                        beginOfStatement += statement.Length;
                        statement         = "";
                    }

                    codeCompleteOptions          = codeElementsInScope.Where(ce => !(ce is Subroutine)).ToList(); //subroutines only available after a 'call'
                    session.InsertionIndexInLine = beginOfStatement;
                    filter = statement;
                    addLanguageKeywords = true;
                }
                else // nested in type, eg: channel % sourceNode % id
                {
                    var elements = FortranParseHelper.SplitElementsInStatement(statement, fullStatement, ref beginOfStatement, out filter);

                    if (elements.Count < 1)
                    {
                        throw new NotSupportedException("help!");
                    }

                    var variableName = elements[0];

                    var matchingVariable = codeElementsInScope
                                           .OfType <Variable>()
                                           .FirstOrDefault(lv => String.Equals(lv.Name, variableName, StringComparison.InvariantCultureIgnoreCase));

                    var typeOfVariable = matchingVariable.TypeString;

                    var currentType = codeElementsInScope
                                      .OfType <Type>()
                                      .FirstOrDefault(tp => String.Equals(tp.Name, typeOfVariable, StringComparison.InvariantCultureIgnoreCase));

                    for (int i = 1; i < elements.Count; i++)
                    {
                        if (currentType == null)
                        {
                            break;
                        }

                        var propertyName = elements[i];
                        var property     = GetElementsOfType(currentType).FirstOrDefault(vf => String.Equals(vf.Name, propertyName, StringComparison.InvariantCultureIgnoreCase));

                        typeOfVariable = property.TypeString;

                        currentType = codeElementsInScope
                                      .OfType <Type>()
                                      .FirstOrDefault(tp => String.Equals(tp.Name, typeOfVariable, StringComparison.InvariantCultureIgnoreCase));
                    }

                    if (currentType == null)
                    {
                        codeCompleteOptions = new INameable[] { }
                    }
                    ;
                    else
                    {
                        codeCompleteOptions = GetElementsOfType(currentType).Cast <INameable>().ToList();
                    }

                    session.InsertionIndexInLine = beginOfStatement;
                }

                // gather all results
                var completionItems = codeCompleteOptions.Select(e => new CompletionItem(e.Name, FortranIconProvider.GetIconForMember(e))
                {
                    ToolTip = GetTooltipForMember(currentMember, e)
                }).ToList();
                if (addLanguageKeywords)
                {
                    foreach (var keyword in fortranKeywords)
                    {
                        completionItems.Add(new CompletionItem(keyword, null));
                    }

                    foreach (var intrinsic in fortranIntrinsics)
                    {
                        completionItems.Add(new CompletionItem(intrinsic.Key, IntrinsicIcon)
                        {
                            ToolTip = intrinsic.Value
                        });
                    }
                }

                {//YK, 2020, also add all the words already in this current file
                    //check file content.
                    var myFileContents = VisualStudio.GetCurrentCodeFileContent();

                    {
                        ////two methods to replace \t, \n, \r, tested and works
                        //myFileContents = Regex.Replace(myFileContents, @"\t", " ");
                        ////myFileContents = myFileContents.Replace("\t", " ");
                        //myFileContents = myFileContents.Replace("\r", " ");
                        //myFileContents = myFileContents.Replace("\n", " ");
                    }

                    {//example to remove separator...
                     //char[] separators = new char[] { ' ', ';', ',', '\r', '\t', '\n', '(', ')', '!', ':', '=', '+', '*', '/' };
                     //string s = "replace;multiple,characters\tin;a,c\rsharp,string";
                     //string[] temp = s.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                     //s = String.Join("\n", temp);
                    }

                    {//example to remove duplicated string
                     //String[] a = { "1", "1", "2", "1", "1", "3", "1", "1", };
                     //Console.WriteLine("原数组长度:    {0}", a.Length);
                     //Console.WriteLine("排除后数组长度:{0}", a.Distinct<string>().ToArray().Length);
                     //Console.ReadKey();
                    }

                    char[]   separators = new char[] { ' ', ';', ',', '\r', '\t', '\n', '(', ')', '!', ':', '=', '+', '-', '*', '/', '&', '.', '\'', '<', '>', '{', '}', '[', ']', '$', '%', '?' };
                    string   s          = myFileContents;
                    string[] myFileContentSplittedStr         = myFileContents.Split(separators, StringSplitOptions.RemoveEmptyEntries);
                    string[] myFileContentSplittedStrDistinct = myFileContentSplittedStr.Distinct <string>().ToArray();
                    foreach (var keyword in myFileContentSplittedStrDistinct)
                    {
                        //{//example to add non-duplicated string
                        //    //if (!listString.Contains(eachString))
                        //    //    listString.Add(eachString);
                        //}

                        completionItems.Add(new CompletionItem(keyword, null));
                    }
                }

                session.SetCompletionSet(completionItems, filter);
            }
            catch (Exception e)
            {
                Log.Error("Error while updating code complete", e);
            }
            finally
            {
                ParseQueueProcessor.ShowProgressDialog = true; //messes with intellisense popup
            }
        }