0

我正在为 C# 构建一个简单的 IDE。

..我正在使用FastColoredTextBox控件进行源代码编辑,内置自动完成菜单(http://www.codeproject.com/Articles/161871/Fast-Colored-TextBox-for-syntax-highlighting

问题是,我想用它NRefactor来自动完成代码,就像在 Visual Studio 中一样。

我做了一些研究,我发现了这个:https ://github.com/lukebuehler/NRefactory-Completion-Sample ...但我不明白代码,所以我不能重用它。

确切地说,我需要什么?

我需要一个函数,它将作为程序集的输入列表(字符串数组,它们是 DLL 的路径)、当前偏移量和编辑器的文本。

作为输出,我需要一个对象数组,其中将包含对象的名称,以及它的类型(变量、函数、类型……)

那么,我该怎么做呢?是否有必要在另一个线程中运行此自动完成代码?

谢谢你的回答,

维泰克ST

PS:不要讨厌我,我不熟悉NRefactor...

4

1 回答 1

0

我在你问这个问题的同一天开始探索 NRefactory)所以,我不能称自己为 NRefactory 专家。但我可以告诉你方法,我如何使用它。

理论资料: http: //www.codeproject.com/Articles/408663/Using-NRefactory-for-analyzing-Csharp-code

首先,您可以使用此示例项目中的 Visual Studio 解决方案模型为您的 IDE 解决方案格式制作类似的类:https ://github.com/icharpcode/NRefactory/tree/master/ICSharpCode.NRefactory.ConsistencyCheck 共有三个类你需要:CSharpFileCSharpProjectSolution。请看它的源代码,你就会知道,NRefactory 是如何对代码文件进行语法分析的。注意 CSharpProject 的“ Compilation ”字段和 CSharpFile 的“ CreateResolver ”方法。

其次,您需要对代码进行语义分析。为此,您需要实施

ICSharpCode.NRefactory.CSharp.Resolver.IResolveVisitorNavigator

界面。但在您的情况下,您最好使用现有的 NRefactory 实现:

ICSharpCode.NRefactory.CSharp.Resolver.FindReferencedEntities

具有两个参数的构造函数等待两个处理程序。首先执行然后解析的语法元素是类型的引用,包含在您的解决方案或引用的程序集中(如变量声明)。当解析的语法元素是某个类型的成员的引用时,第二个被执行(例如,“(new object()).ToString()”作为“object”实例的成员“ToString”的引用)。两个处理程序的第一个参数是 AstNode:未解析的代码语法元素。第二个参数是对应的解析语义元素:第一个处理程序的 IType 和另一个处理程序的 IMember。因此,您需要使用处理程序创建导航器实例,例如,将语法和相应的语义元素保存在字典中。

您的代码可能如下所示:

var solution = new Solution(slnPath);

IDictionary<AstNode, IType> typesMap = new Dictionary<AstNode, IType>();

IDictionary<AstNode, IMember> membersMap = new Dictionary<AstNode, IMember>();

var navigator = new FindReferencedEntities(typesMap.Add, membersMap.Add);

foreach (var codeFile in solution.AllFiles)
{
    codeFile.CreateResolver().ApplyNavigator(navigator);
}

执行此代码字典后,typeMapmembersMap将包含代码的语法元素,NRefactory 能够在字典的键中解析,以及在值中对应的解析语义。如果您编写自动完成,则在使用时处理的代码很可能无法编译(因为用户此时编写它)。因此,您的应用程序不仅必须使用已解析的代码,而且还必须使用未解析的代码。要获取代码文件中未解析的语法元素,此时用户编辑,您必须使用:

var syntaxTree = solution.Projects
    .Where(p => p.Title.Equals(editableProjName))
    .Files
    .Where(f => f.FileName.Equals(editableFileNamePath))
    .SyntaxTree;

SyntaxTree 是一个“ ICSharpCode.NRefactory.CSharp.SyntaxTree ”,它继承了 AstNode 类。它是代码文件的根语法节点。变量syntaxTree将包含当前正在编辑的文件的所有未解析的语法元素。要遍历语法树,您可以使用 AstNode 可枚举成员,如 Descendants、Children、GetParent() 等。或者您可以使用“Visitor”模式和 AstNode 方法“AcceptVisitor”。

在为自动完成生成列表时,您可以使用 typesMap 和 membersMap 作为已声明类型及其成员的快速存储,如果未找到用户输入,则可以使用 syntaxTree 作为慢速存储。

NRefactory 是一个非常广泛的话题,我无法完全揭示它。很遗憾,这个强大的框架没有详细的文档。但是希望我的回答可以帮助到你。

于 2015-01-15T16:25:36.163 回答