admin管理员组

文章数量:1122846

I am working on a VSIX project to produce plugins for vs2019, I have created a menu command that can jump to the appropriate code position based on the cursor position text. I Use DTE.Find.Execute interface to implement my requirements, this function can run normally, but I found that after executing this command, there was a problem with the View.Navigate Backward function (The built-in function of vs2019). It could not jump back to the code position before the command call, and there were many irrelevant code positions between the new and old positions.

I want to know how to solve this problem ?

Here is the main code:

bool GoToRegexJump(string originalText)
{
    string config = UtilsClass.GetRegexJumpConfig(Package);
    JArray array = JArray.Parse(config);
    string project = UtilsClass.GetSolutionSort(Package).ToString();
    foreach (var item in array)
    {
        string projects = item[Constants.USERSETTINGS_REGEX_JUMP_PROJECT].ToObject<string>();
        string files = item[Constants.USERSETTINGS_REGEX_JUMP_FILES].ToObject<string>();
        string[] allowProjects = projects.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
        string key = item[Constants.USERSETTINGS_REGEX_JUMP_KEY].ToObject<string>();
        bool matchCase = item[Constants.USERSETTINGS_REGEX_JUMP_MATCH_CASE].ToObject<bool>();

        if (allowProjects.Contains(project))
        {
            var match = Regex.Match(originalText, key);
            if (match.Success)
            {
                string pattern = item[Constants.USERSETTINGS_REGEX_JUMP_VALUE].ToObject<string>();
                for (int i = 0; i < match.Groups.Count; ++i)
                {
                    string value = match.Groups[i].Value;
                    value = Regex.Escape(value);
                    pattern = pattern.Replace($"${i}", value);
                }
                
                if (FindText(
                        pattern
                        , false
                        , vsFindTarget.vsFindTargetSolution, vsFindPatternSyntax.vsFindPatternSyntaxRegExpr
                        , false, matchCase, string.IsNullOrEmpty(files) ? "*.h;*.cpp" : files))
                {
                    return true;
                }
            }
        }
    }

    return false;
}

bool FindText(string text, bool backwards = false, vsFindTarget target = vsFindTarget.vsFindTargetCurrentDocument, vsFindPatternSyntax syntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral, bool matchWholeWord = false, bool matchCase = false, string filesOfType = "*.h;*.cpp", string searchPath = "")
{
    Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

    var dte = Package.GetService<DTE, DTE2>();
    if (dte == null)
    {
        return false;
    }

    if (target == vsFindTarget.vsFindTargetCurrentDocument)
    {
        var textView = GetActiveTextView();
        if (textView == null)
        {
            return false;
        }
    }

    dte.Find.MatchCase = matchCase;
    dte.Find.MatchWholeWord = matchWholeWord;
    dte.Find.Action = vsFindAction.vsFindActionFind;
    dte.Find.SearchPath = searchPath;
    dte.Find.Target = target;
    dte.Find.Backwards = backwards;
    dte.Find.MatchInHiddenText = true;
    dte.Find.PatternSyntax = syntax;
    dte.Find.FindWhat = text;
    dte.Find.FilesOfType = filesOfType;

    var findResult = dte.Find.Execute();

    if (findResult == vsFindResult.vsFindResultFound)
    {
        return true;
    }

    if (UtilsClass.IsDebugMode(Package))
    {
        UtilsClass.PrintMessage(
            $"Found {dte.Find.FindWhat} Failed,SearchPath={dte.Find.SearchPath},FilesOfType={dte.Find.FilesOfType}。");
    }

    return false;
}

I am working on a VSIX project to produce plugins for vs2019, I have created a menu command that can jump to the appropriate code position based on the cursor position text. I Use DTE.Find.Execute interface to implement my requirements, this function can run normally, but I found that after executing this command, there was a problem with the View.Navigate Backward function (The built-in function of vs2019). It could not jump back to the code position before the command call, and there were many irrelevant code positions between the new and old positions.

I want to know how to solve this problem ?

Here is the main code:

bool GoToRegexJump(string originalText)
{
    string config = UtilsClass.GetRegexJumpConfig(Package);
    JArray array = JArray.Parse(config);
    string project = UtilsClass.GetSolutionSort(Package).ToString();
    foreach (var item in array)
    {
        string projects = item[Constants.USERSETTINGS_REGEX_JUMP_PROJECT].ToObject<string>();
        string files = item[Constants.USERSETTINGS_REGEX_JUMP_FILES].ToObject<string>();
        string[] allowProjects = projects.Split(new string[] { "|" }, StringSplitOptions.RemoveEmptyEntries);
        string key = item[Constants.USERSETTINGS_REGEX_JUMP_KEY].ToObject<string>();
        bool matchCase = item[Constants.USERSETTINGS_REGEX_JUMP_MATCH_CASE].ToObject<bool>();

        if (allowProjects.Contains(project))
        {
            var match = Regex.Match(originalText, key);
            if (match.Success)
            {
                string pattern = item[Constants.USERSETTINGS_REGEX_JUMP_VALUE].ToObject<string>();
                for (int i = 0; i < match.Groups.Count; ++i)
                {
                    string value = match.Groups[i].Value;
                    value = Regex.Escape(value);
                    pattern = pattern.Replace($"${i}", value);
                }
                
                if (FindText(
                        pattern
                        , false
                        , vsFindTarget.vsFindTargetSolution, vsFindPatternSyntax.vsFindPatternSyntaxRegExpr
                        , false, matchCase, string.IsNullOrEmpty(files) ? "*.h;*.cpp" : files))
                {
                    return true;
                }
            }
        }
    }

    return false;
}

bool FindText(string text, bool backwards = false, vsFindTarget target = vsFindTarget.vsFindTargetCurrentDocument, vsFindPatternSyntax syntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral, bool matchWholeWord = false, bool matchCase = false, string filesOfType = "*.h;*.cpp", string searchPath = "")
{
    Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread();

    var dte = Package.GetService<DTE, DTE2>();
    if (dte == null)
    {
        return false;
    }

    if (target == vsFindTarget.vsFindTargetCurrentDocument)
    {
        var textView = GetActiveTextView();
        if (textView == null)
        {
            return false;
        }
    }

    dte.Find.MatchCase = matchCase;
    dte.Find.MatchWholeWord = matchWholeWord;
    dte.Find.Action = vsFindAction.vsFindActionFind;
    dte.Find.SearchPath = searchPath;
    dte.Find.Target = target;
    dte.Find.Backwards = backwards;
    dte.Find.MatchInHiddenText = true;
    dte.Find.PatternSyntax = syntax;
    dte.Find.FindWhat = text;
    dte.Find.FilesOfType = filesOfType;

    var findResult = dte.Find.Execute();

    if (findResult == vsFindResult.vsFindResultFound)
    {
        return true;
    }

    if (UtilsClass.IsDebugMode(Package))
    {
        UtilsClass.PrintMessage(
            $"Found {dte.Find.FindWhat} Failed,SearchPath={dte.Find.SearchPath},FilesOfType={dte.Find.FilesOfType}。");
    }

    return false;
}
Share Improve this question edited Nov 23, 2024 at 2:28 hchlqlz asked Nov 23, 2024 at 2:20 hchlqlzhchlqlz 234 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I have a VS plugin with a custom Code Map for VS which includes custom navigation to code elements. I also struggled a lot with an integration of my navigation into VS Navigate Backward functionality. I tried many things including DTE ExecuteCommand API with the "Go To" command but nothing really helped until I used this helper from the Roslyn VisualStudioWorkspace: VisualStudioWorkspace.TryGoToDefinitionAsync().

It is described in my own question: How to navigate to a definition of a Symbol located in the external assembly

And also in another one: Roslyn - Navigate to SourceText in a Visual Studio extension

I can't guarantee that it will solve your issue, but it greatly helped me. Now custom navigation in VS feels like it is native to VS with cool features like:

  • Integration with Navigate Backward/Forward VS functionality
  • When user tries to navigate to a partial class, a dialog with all partial class declarations is opened
  • When user tries to navigate to something defined in an external dependency (a referenced DLL, for example), depending of VS settings the navigation takes him to the generated metadata or decompiled sources.

本文标签: visual studioHow to manipulate position navigation in VSIX projectStack Overflow