C# 如何使用Resharper SDK从IClrDeclaredElement获取IDeclaredType

C# 如何使用Resharper SDK从IClrDeclaredElement获取IDeclaredType,c#,resharper-sdk,C#,Resharper Sdk,我正在为Resharper编写一个导航插件,我的情况是,我有一个从中获得的IDeclaredElement列表 var declaredElements = context.GetData(DataConstants.DECLARED_ELEMENTS) 此元素是用户鼠标光标所在的元素 我想做的是获取声明元素的IDeclaredType,包括它可能具有的任何类型参数,如果它是泛型类型 ,并没有真正解释各种类型之间的关系 我已经搜索了其他插件,试图找到这方面的例子,但结果都是空的。我检查了每个U

我正在为Resharper编写一个导航插件,我的情况是,我有一个从中获得的
IDeclaredElement
列表

var declaredElements = context.GetData(DataConstants.DECLARED_ELEMENTS)
此元素是用户鼠标光标所在的元素

我想做的是获取声明元素的
IDeclaredType
,包括它可能具有的任何类型参数,如果它是泛型类型

,并没有真正解释各种类型之间的关系

我已经搜索了其他插件,试图找到这方面的例子,但结果都是空的。我检查了每个Util和扩展类,看看是否有一个方法可以满足我的需求,但是没有

我发现的唯一一件事是:

declaredElements.First().GetSuperTypes()
返回类型层次结构,不包括当前类型。有用,但不是我想要的

有没有人对这个API有任何经验或了解它是如何工作的?我希望能有一个更能解释这些类型之间关系的答案

简而言之,我对它的理解是:

  • 名称
    (IDeclaredElement,IDeclaredType)
    中声明的类型似乎是指物理代码元素
  • IType似乎是所有类型的顶级接口,它与物理代码元素不对应
  • 我不清楚名称
    (itypelement,IDeclaredElement)
    中带有元素的类型的含义,可能它指的是AST元素
我希望得到一些澄清。

查看以下代码:

void Do(IDataContext dataContext)
{
  foreach (var reference in dataContext.GetData(DataConstants.REFERENCES))
  {
    var resolveResultWithInfo = reference.Resolve().Result;
    var typeElement = resolveResultWithInfo.DeclaredElement as ITypeElement;
    if (typeElement != null)
    {
      var substitution = resolveResultWithInfo.Substitution;
      var declaredType = TypeFactory.CreateType(typeElement, substitution);
    }
  }
}

我在文档中添加了一个问题以更新此内容:

我将尝试在这里提供一个简单的解释

ITreeNode
类型层次结构定义了代码的抽象语法树。这提供了大量信息,但级别非常低-它直接映射到代码的原始文本。它还遗漏了一些更高级别的信息。例如,如果我想为一个类声明获取所有类型成员,我可以遍历该类的AST,并收集所有适当的树节点,但是我还必须处理部分类,并且AST不提供用于定位该类其他部分的信息。类似地,如果我看到类声明
public class Foo:Bar
,我将不得不手动解析
Bar
基类型

IDeclaredElement
类型层次结构本质上是语法树的语义视图。在最简单的层次上,声明的元素是“具有声明的东西”。这可以是一个类声明,或者一个方法声明,或者甚至与代码无关的东西——HTML元素、CSS类,甚至颜色和文件系统路径(这就是为什么它被称为“元素”——它需要一个可以应用于许多不同事物的名称)

例如,CLR类型由
itypelement
接口表示,该接口源自
idecladelement
。它提供了获取目标类型的方法、属性、构造函数等的声明元素的方法和属性。因此,(几乎)可以仅根据声明的元素提供CLR源项目的语义视图。差不多,但不完全一样

声明的元素具有
GetDeclarations
方法,该方法提供作为声明元素声明的
IDeclaration
语法树节点。类似地,
IDeclaration
节点提供了
DeclaredElement
属性,以便能够从节点获取声明的元素

此外,ReSharper有一个非常强大的机制称为references,它允许树节点有一个将解析为声明元素的传出引用(它也可能无法解析,这是一个错误,例如使用尚未写入的方法,或者它可以解析为多个元素,例如使用一个方法而不限定它是哪个重载)。这些引用可以应用于任何节点,例如引用回变量声明的变量名,或
公共类Foo:Bar
中引用
Bar
的声明元素的
Bar
(从中可以获得
标识
Bar
的源代码)

这提供了一组令人印象深刻的特性—代码文件的语法视图、代码声明的语义视图,以及将所有内容连接在一起的引用,但这并不涵盖所有内容。声明元素提供声明内容的语义视图,但并不表示所有使用场景

具体来说(查看CLR类型),它不能将类型的用法表示为数组、指针或封闭泛型类型。
ITypeElement
可以提供类
Foo
Bar
,但不能表示
Foo[]
Bar

声明的元素需要能够将这些使用场景建模为基类、方法签名等。为此,派生的声明元素(如
itypelement
)使用额外的接口层次结构来表示此“类型系统”信息。此层次结构取决于所分析的语言。对于CLR类型,它是
IType
层次结构,对于JavaScript,它是
IJavaScriptType

IType
是附加信息,而不是替换已声明元素的语义视图。
IType
可以返回所有类型成员的符号表,但不提供与
itypelement
相同的访问器。相反,(取决于建模的内容)
IType
本质上是一个围绕已声明元素和
issubstitution
实例的包装器,它为泛型类型参数提供替换(数组表示为
System.array
类型,wi
var type = psiModule.GetPredefinedType(context).String;