如何在解决方案中通过 FQN 查找类型?

问题描述

我正在编写一个 Rider/ReSharper nav-from-here 插件,它应该使用一些简单的规则根据我站在的符号确定目标类型,最后导航到它。

第一部分没问题,我已经设法形成了所需的 FQN,但我在导航方面遇到了困难。我找到了 this StackOverflow 帖子,并认为我可以尝试这种方法。所以我一直在尝试使用 TypeFactory.CreateTypeByCLRName 大约两个小时来创建一个 IDeclaredType 实例,以便能够使用 IDeclaredElement 获取 GetTypeElement() 并最终获取其声明。但是 API 似乎发生了变化,无论我做什么,我的代码都无法正常工作。

这是我目前得到的:

// does not work with Modules.GetModules(),either
foreach (var psiModule in solution.GetPsiServices().Modules.GetSourceModules())
{
    var type = TypeFactory.CreateTypeByCLRName("MyNamespace.MyClassName",psiModule);
    var typeElement = type.GetTypeElement();

    if (typeElement != null)
    {
        MessageBox.ShowInfo(psiModule.Name); // to make sure sth is happening
        break;
    }
}

奇怪的部分是,我实际上看到了一个消息框 - 但仅当带有 MyClassName.cs 的选项卡处于活动状态时。当它聚焦时,一切都很好。当它不是或文件关闭时,类不会得到解析,type.IsResolvedfalse

我做错了什么?

解决方法

要做到这一点,您应该有一个来自上下文的 IPsiModule 实例,您打算在其中使用您正在寻找的类型。您可以通过 .GetPsiModule() 方法或许多其他方式(例如 dataContext.GetData(PsiDataConstants.SOURCE_FILE)?.GetPsiModule().

)从您正在使用的某个语法节点获取它
void FindTypes(string fullTypeName,IPsiModule psiModule)
{
  // access the symbol cache where all the solution types are stored
  var symbolCache = psiModule.GetPsiServices().Symbols;

  // get a view on that cache from specific IPsiModule,include all referenced assemblies
  var symbolScope = symbolCache.GetSymbolScope(psiModule,withReferences: true,caseSensitive: true);

  // or use this to search through all of the solution types
  // var symbolScope = symbolCache.GetSymbolScope(LibrarySymbolScope.FULL,caseSensitive: true);

  // request all the type symbols with the specified full type name
  foreach (var typeElement in symbolScope.GetTypeElementsByCLRName(fullTypeName))
  {
    // ...
  }
}