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

标签 c# resharper-sdk

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

var declaredElements = context.GetData(DataConstants.DECLARED_ELEMENTS)


此元素是用户将鼠标光标放在其上的元素。

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

The resharper SDK documentation is quite light when it comes to the type system,并且根本没有解释各种类型之间的关系。

我搜寻其他插件来尝试查找此示例,但都空了。我检查了每个Util和Extension类,看看是否有某个方法可以满足我的需求,但没有实现。

关于我发现的唯一内容是:

declaredElements.First().GetSuperTypes()


它返回类型层次结构,不包括当前类型。有用,但不是我想要的。

是否有人对此API有任何经验或了解其工作原理?我希望得到一个可以解释类型之间关系的答案。

我对此的理解很简单:


名称为(IDeclaredElement, IDeclaredType)且声明为“ Declared”的类型似乎是指物理代码元素。
IType似乎是所有类型的顶级接口,与物理代码元素不对应
我不清楚名称为(ITypeElement, IDeclaredElement)的Element的类型的含义,也许它是指AST元素。


我希望对此有所澄清。

最佳答案

我在文档中添加了一个问题来对此进行更新:https://github.com/JetBrains/resharper-devguide/issues/4

我将在此处尝试提供一些解释。

ITreeNode类型层次结构定义了代码的抽象语法树。这提供了很多信息,但是级别很低-它直接映射到代码的原始文本。它还会丢失一些更高级别的信息。例如,如果我想为一个类声明获取所有类型成员,则可以遍历该类的AST,并收集所有适当的树节点,但是那时我还必须处理部分类,而AST不提供任何信息用于定位课程的其他部分。同样,如果看到类声明public class Foo : Bar,则必须对Bar基本类型进行手动解析。

IDeclaredElement类型层次结构本质上是语法树的语义视图。最简单的说,声明的元素是“具有声明的内容”。这可以是类声明,也可以是方法声明,甚至可以是与代码不相关的内容-HTML元素,CSS类甚至颜色和文件系统路径(这就是为什么将其称为“元素”的原因-它需要一个名称可以应用于很多不同的东西)。

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

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

此外,ReSharper具有一个非常强大的机制,称为引用,该机制允许树节点具有将解析为已声明元素的传出引用(它也可能无法解析,这是诸如使用尚未使用的方法之类的错误。 ,或者它可以解析为多个元素,例如使用一种方法而不限定它是哪个重载)。这些引用可以应用于任何节点,例如,引用回变量声明的变量名称,或者Bar中的public class Foo : Bar引用了Bar的声明元素(可以从中获取< cc>和IDeclaration的源代码)。

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

具体来说(看CLR类型),它不能表示将类型的用法表示为数组,指针或封闭的泛型类型。 Bar可以提供类ITypeElementFoo的语义视图,但不能表示Bar<T>Foo[]

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

IJavaScriptType是附加信息,而不是已声明元素的语义视图的替代。 IType可以返回所有类型成员的符号表,但不能以与IType相同的方式提供访问器。相反,(取决于所建模的内容)ITypeElement本质上是声明元素和IType实例的包装,它提供了通用类型参数的替代(数组表示为ISubstitution类型,带有基础元素类型,其本身就是System.Array,因为它可以是封闭的泛型或另一个数组)。替换也可以是空替换,它不替换任何内容,允许表示为开放泛型的类型或根本不是泛型的类型。 IType接口是引用已声明元素的IDeclaredType


  另外:解析引用实际上解析为一个声明的元素和一个IType,以再次建模泛型。解决方法声明签名的引用时,您需要既知道它是ISubstitution又是什么IList<T>


为了获得T实例,您需要从现有的已声明元素(方法签名,基类等)中获得一个实例,或者通过使用IType创建它。如果它是泛型类型,您很可能也需要指定TypeFactory.CreateType。您还可以通过以下方式获得一堆常见的“预定义”类型:

var type = psiModule.GetPredefinedType(context).String; 


您可以使用这些类型传递给ISubstitution方法之一,以作为您也传递的TypeFactory.CreateType的类型参数。

因此,结果是,我们在源代码中声明了一个类,这为我们提供了ITypeElementITreeNodeIDeclaration。我们可以使用ITypeDeclaration或解析引用来获取此声明IDeclaration的语义视图,其中IDeclaredElement是表示类的派生接口。基于CLR的声明元素使用ITypeElement表示类型用法,例如基类(可能需要是封闭的泛型)或方法参数(可能是开放的泛型)或数组。 IType是一种类型用法,可以使我们回到已声明的元素。类型通常在内部用声明的元素和IDeclaredType表示,可以在没有通用参数的情况下填写任何通用参数,或者用ID替换。最后,您可以使用ISubstitutionIType上的属性获得TypeFactory.CreateType

关于c# - 如何使用Resharper SDK从IClrDeclaredElement获取IDeclaredType,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26794277/

相关文章:

c# - 解析我专有的字符串格式

C# 如何在用户控件上显示文本气泡?

c# - C# 中的负标志

c# - 如何在 resharper 插件中提供具有 datacontext 类型的智能感知?

c# - 上下文操作的 ReSharper SDK 测试不起作用

c# - 如何使用 ReSharper SDK 创建 [CustomAttribute(typeof(GenericType<,>))]?

c# - 循环依赖最佳实践

c# - 从字符串中删除指定的标点符号