我正在为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
......
答案 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是一个非常广泛的话题,我无法完全揭示它。令人遗憾的是,这个强大的框架还没有得到详细的文件。但我希望我的回答可以帮到你。