protected string GetContext()
        {
            try
            {
                string context = "\n\n\nError context:";
                context += "\nSolution: " + VisualStudio.GetSolutionName();
                var codeFile = VisualStudio.GetCurrentCodeFile();
                if (codeFile != null)
                {
                    context += "\nCurrent file: " + codeFile.FilePath;
                    context += "\nLineNumber: " + VisualStudio.GetCurrentLine();
                    context += "\nCursor position: " + VisualStudio.GetCursorPositionInLine();
                }
                else
                {
                    context += "\nCurrent file: <none>";
                }
                context += "\n\n";

                return(context);
            }
            catch (Exception)
            {
                return("<exception during GetContext()>");
            }
        }
        public void BrowseTo()
        {
            try
            {
                if (!VisualStudio.IsDocumentOpen())
                {
                    return;
                }

                var cursorPosition = VisualStudio.GetCursorPositionInLine();
                var line           = VisualStudio.GetCurrentLine();

                int beginIndex;
                var elementName = FortranParseHelper.GetElementName(line, cursorPosition, out beginIndex);

                if (String.IsNullOrEmpty(elementName))
                {
                    return;
                }

                var memberMatches = SyntaxTreeMaintainer.GetSyntaxTrees()
                                    .SelectMany(st => st.GetAllMembers()
                                                .Where(m => Equals(elementName, m.Name))
                                                .Select(m => new SearchResult {
                    SyntaxTree = st, Member = m
                }))
                                    .ToList();

                if (memberMatches.Any())
                {
                    BrowseToCore(memberMatches);
                }
                else
                {
                    BrowseToVariable(elementName);
                }
            }
            catch (Exception e)
            {
                Log.Error("BrowseTo failed", e, GetContext());
            }
        }
        /// <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
            }
        }
Beispiel #4
0
        public void FindUsage()
        {
            try
            {
                if (!VisualStudio.IsDocumentOpen())
                {
                    return;
                }

                var coords         = VisualStudio.GetCaretPositionInScreenCoordinates();
                var cursorPosition = VisualStudio.GetCursorPositionInLine();
                var line           = VisualStudio.GetCurrentLine();

                int beginIndex;
                var memberName = FortranParseHelper.GetElementName(line, cursorPosition, out beginIndex);

                if (String.IsNullOrEmpty(memberName.Trim()))
                {
                    return;
                }

                var asts = SyntaxTreeMaintainer.GetSyntaxTrees().ToList();

                var matchingMember = asts.SelectMany(a => a.GetAllMembers())
                                     .FirstOrDefault(m => String.Equals(m.Name, memberName, StringComparison.InvariantCultureIgnoreCase));

                var searchObj = matchingMember != null ?
                                new MemberOrSearchTerm(matchingMember) :
                                new MemberOrSearchTerm(memberName);

                var usages = new FortranUsageSearcher().FindInFiles(searchObj, asts);

                if (usages.Count == 0)
                {
                    return;
                }
                if (usages.Count == 1)
                {
                    GotoUsage(usages.First());
                    return;
                }

                dialog                  = CreateListFindControl();
                dialog.Location         = coords;
                dialog.MaxResults       = 500;//something big
                dialog.DataSource       = usages.OfType <object>().ToList();
                dialog.AlwaysShowList   = true;
                dialog.HideSearchDialog = true;
                dialog.OnGetIconForItem = o => null;
                dialog.DataMember       = "Name";
                dialog.HintMember       = "Hint";
                dialog.OnGetHintEmphasisRangeForItem = o =>
                {
                    var usageRes = (UsageResult)o;
                    var start    = usageRes.Location.Offset;
                    var end      = start + memberName.Length;
                    return(new Point(start, end));
                };
                dialog.ItemChosen += (chosenUsage, e) => GotoUsage((UsageResult)chosenUsage);
                dialog.Show();
            }
            catch (Exception e)
            {
                Log.Error("FindUsage failed", e, GetContext());
            }
        }
        /// <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
            }
        }