通用智能感知的全新实现

问题描述 投票:61回答:2

我有兴趣为SQL和C#编写一个通用的Intellisense启用编辑器(如果可能,等等!)。我想在C#中将其作为重写或扩展的WPF richTextBox类型控件。我知道有很多可用的示例项目,我已经实现了我自己的基本版本;但我遇到的大多数例子(实际上是我自己的)都是基本的。

一些代码示例如下:

  1. DIY Intellisense By yetanotherchris
  2. CodeTextBox - another RichTextBox control with syntax highlighting and Intellisense By Tamas Honfi

但是,我发现了一个使用Intellisense QueryCommander SQL Editor By Mikael Håkansson的SQL编辑器的一个很好的例子,它似乎运行良好。 Microsoft必须使用命令关键字的XML库,但我的问题是:Microsoft如何(详细地)实现他们的智能感知(as-you-type Intellisense)以及创建我自己的同一标准有多难?


编辑答:一年过去了,我已经设法用基本的智能感知开发我自己的编辑器控件,主要是为了我自己的“享受”。我想我会回来提供一个免费提供的.NET项目列表,帮助我自己开发,可以开箱即用,免费:

  1. ICSharpCode (WinForms)
  2. AvalonEdit (WPF)
  3. ScintillaNET (WinForms)
  4. Query Commander [for example of intellisense implementation] (WinForms)

编辑B:提问后15个月,我仍在寻找新的改进编辑。这个很好......

  1. RoslynPAD很酷!

编辑C:问题2年以上,我发现了以下项目,两者都使用WPF并由AvalonEdit支持。

  1. CodeCompletion for AvalonEdit使用NRefactory。这个项目非常好,并且使用NRefactory完全实现了intellisense。
  2. ScriptCS ScriptCS使用简单的文本编辑器轻松编写和执行C#。
c# wpf intellisense
2个回答
122
投票

微软如何(详细)实现他们的类型智能感知?

我可以将它描述为您想要命名的任何详细程度,但我没有时间进行简短的解释。我将解释我们如何在Roslyn中做到这一点。

首先,我们使用可以有效表示编辑的数据结构构建令牌流的不可变模型,因为显然编辑正是将会有很多内容。

使持久重用有效的关键见解是表示令牌的字符长度,而不是编辑缓冲区中的字符位置;请记住,文件末尾的标记将在每次编辑时更改位置,但标记的长度不会更改。如果您希望在极大文件上有效,则必须不惜一切代价最大限度地减少总修复次数。

一旦你有一个可以处理插入和删除的不可变模型来构建一个不可变的令牌流,而不是每次都重新整理整个文件,你就必须做同样的事情,但是要进行语法分析。这实际上是一个相当困难的问题。我建议你获得计算机科学的本科或研究生学位,重点是解析器理论,如果你还没有。我们获得了博士论文的人的帮助,他们在解析器理论上做了他们的论文来设计这个算法的特定位。

然后,显然,构建一个可以分析C#的语法分析器。记住,它必须分析破碎的C#,而不是正确的C#;当程序处于非编译状态时,IntelliSense必须工作。因此,首先提出具有良好错误恢复特性的语法修改。

好了,所以现在你已经有了一个解析器,它可以有效地进行语法分析,而不需要重新编译或重新解析除编辑区域之外的任何东西,大多数情况下,这意味着你可以在击键之间完成工作。我忘了提及,当然你需要提出一些机制来阻止UI线程,而在进行所有这些分析时,如果分析发生的时间要比两次击键之间的时间长。 C#5的新“异步/等待”功能应该有所帮助。 (我可以从个人经验告诉你:小心任务的扩散和取消令牌。如果你粗心大意,就有可能进入一个有数万个被取消的任务待定的状态,这并不快。 )

现在您已经进行了语法分析,您需要构建一个语义分析器。由于您只是在进行智能感知,因此它不需要是一个特别复杂的语义分析器。 (我们的语义分析器必须进行适合于从正确的程序生成代码并从错误的程序中纠正错误分析的分析。)当然,它还必须对损坏的程序进行良好的语义分析,这确实会大大增加复杂性。

我的建议是从构建“顶级”语义分析器开始,再次使用不可变模型,该模型可以将源代码中声明的代码类型的状态从编辑保持到编辑。顶级分析器处理的不是语句或表达式:类型声明,指令,命名空间,方法声明,构造函数,析构函数等。编译器生成元数据时构成程序“形状”的东西。

元数据!我忘记了元数据。你需要一个元数据阅读器。显然,您需要能够在引用库中类型的表达式上生成IntelliSense。我建议使用CCI库作为元数据阅读器,而不是反射。由于您只是在进行智能感知,显然您不需要元数据编写器。

无论如何,一旦你有一个顶级语义分析器,那么你可以编写一个语句和表达式语义分析器来分析给定语句中表达式的类型。特别注意名称查找和重载解析算法。方法类型推断将特别棘手,尤其是在LINQ查询中。

一旦掌握了所有这些,智能感知引擎应该很容易;只需计算当前光标位置的表达式类型并适当显示下拉列表。

我创建自己的同一标准有多难?

好吧,我们有一个团队,称之为十个人,并且它可能需要,将它称为五年,以便从头到尾完成所有事情。但我们还有很多工作要做,而不仅仅是IntelliSense引擎。这可能只占工作的40%。哦,有一半的人在VB上工作,现在我想起来了。但是那些人平均可能有五到十年的工作经验,所以如果你以前从未这样做过,他们会比你更快。

因此,假设您需要大约十到二十年的全职工作,独自工作,为C#构建一个Roslyn品质的IntelliSense引擎,可以在击键之间对大型程序进行可接受 - 接近正确的分析。

显然,如果你需要先做博士,那就更长了。

或者,您可以简单地使用Roslyn,因为它就是它的用途。这可能需要几个小时,但你不能自己做到这一点。它很有趣!

您可以在此处下载预览版:

http://www.microsoft.com/download/en/details.aspx?id=27746


16
投票

这是微软通常会产生很好结果的领域 - 微软的开发人员工具真的很棒。销售他们的开发人员工具以及销售Windows以获得最佳的智能感知具有明显的商业优势,因此微软有必要将他所描述的资源用于他非常详细的答案中。不过,我认为值得指出一些事情:

  1. 您的客户可能实际上并不需要Microsoft实施提供的所有功能。就您需要提供给客户/用户的功能而言,Microsoft解决方案可能会过度设计。除非您实际上实现了旨在与Visual Studio竞争的通用编码环境,否则您的预期用途可能会简化问题,或者允许您对Microsoft感觉到的解决方案做出妥协他们做不到。微软可能会花费资源来减少已经在几百毫秒内测量的响应时间。这可能不是你需要做的事情。 Microsoft正在花时间为其他人提供API以用于代码分析。这可能不是你计划的一部分。优先考虑您的功能并确定您和您的客户的“足够好”,然后估算实施该功能的成本。
  2. 除了承担实施您可能没有的要求的明显成本之外,如果您没有在团队中工作,Microsoft还会承担一些可能并不明显的成本。与团队相关的沟通成本很高。实际上,让五个聪明人花费更长时间来制作解决方案比单个聪明人生产同等解决方案所需要的要难得多。微软招聘实践和组织结构的某些方面使这种情况更有可能发生。如果你聘请了一群有自我意识的聪明人,然后让他们所有人做出决定,那么你也可以获得5%的更好的解决方案来获得500%的成本。对于微软来说,这个5%更好的解决方案可能会有利可图,但对于一家小公司来说这可能是致命的。
  3. 从单人解决方案转变为5人解决方案会增加成本,但这只是团队内部开发成本。微软拥有独立的团队,致力于(大致)设计,开发和测试甚至是单一功能。跨越这些边界的同行之间的项目相关沟通具有比每个学科内部更高的摩擦力。这不仅会增加个人之间的沟通成本,还会导致团队规模扩大。还有更多 - 因为它不是一个由12个人组成的团队,而是由5个人组成的3个团队,这是向上沟通成本的3倍。微软选择承担的更多成本可能无法转化为其他公司的类似成本。

我的观点并不是将微软描述为效率低下的公司。我的观点是,微软做出了大量关于从招聘,团队组织到设计和实施的决策,这些决策始于对盈利能力和风险的假设,而这些假设根本不适用于非Microsoft的公司。

就智能感知而言,有各种各样的方法来思考这个问题。微软正在制作一个非常通用,可重复使用的解决方案,它不仅解决了智能感知,还针对代码导航,重构以及代码分析的各种其他用途。如果您的唯一目标是让开发人员轻松输入代码而不必输入太多内容,则无需以相同的方式执行操作。定位该功能不需要多年的努力,如果您不仅仅提供API,还可以执行各种创造性的事情,但实际上您也可以控制UI。

© www.soinside.com 2019 - 2024. All rights reserved.