使用C#中的FastColoredTextBox完成NRefactory代码

时间:2014-12-12 16:13:08

标签: c# autocomplete nrefactory

我正在为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的路径),当前偏移量和编辑器的文本。

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

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

感谢您的回答,

VitekST

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

1 个答案:

答案 0 :(得分:0)

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

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

首先,您可以使用此示例项目中的Visual Studio解决方案模型为IDE解决方案格式创建类似的类:https://github.com/icsharpcode/NRefactory/tree/master/ICSharpCode.NRefactory.ConsistencyCheck 您需要三个类: CSharpFile CSharpProject 解决方案。请查看其源代码,您将了解NRefactory如何执行代码文件的语法分析。注意CSharpProject的“编译”字段和CSharpFile的“ CreateResolver ”方法。

其次,您需要执行代码的语义分析。为此,您需要实现

ICSharpCode.NRefactory.CSharp.Resolver.IResolveVisitorNavigator

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

ICSharpCode.NRefactory.CSharp.Resolver.FindReferencedEntities

具有两个参数的构造函数等待两个处理程序。首先执行然后解析语法元素是类型的引用,包含在您的解决方案或引用的程序集中(如变量声明)。第二个在解析语法元素是某个类型成员的引用时执行(例如“(new object())。ToString()”作为“对象”实例的成员“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);
}

执行此代码后,词典 typesMap membersMap 将包含代码的语法元素,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是一个非常广泛的话题,我无法完全揭示它。令人遗憾的是,这个强大的框架还没有得到详细的文件。但我希望我的回答可以帮到你。