我有兴趣为SQL和C#编写一个通用的Intellisense启用编辑器(如果可能,等等!)。我想在C#中将其作为重写或扩展的WPF richTextBox类型控件。我知道有很多可用的示例项目,我已经实现了我自己的基本版本;但我遇到的大多数例子(实际上是我自己的)只是 basic 。
以下是一些代码示例:
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)以及创建我自己的同一标准有多难?
编辑A:一年过去了,我已经设法用基本的智能感知来开发我自己的编辑器控件,主要是为了我自己的“享受”。我想我会回来提供一个免费提供的.NET项目列表,这些项目帮助我完成自己的开发,可以开箱即用,免费使用:
Query Commander [for example of intellisense implementation] (WinForms)
编辑B:提问后15个月,我仍在寻找新的改进编辑。这个很好......
编辑C:问题2年以上,我找到了以下项目,都使用WPF并由AvalonEdit支持。
CodeCompletion for AvalonEdit使用NRefactory。这个项目非常好,并且使用NRefactory完全实现了intellisense。
ScriptCS ScriptCS使用简单的文本编辑器轻松编写和执行C#。
答案 0 :(得分:122)
Microsoft(如何)(详细地)实现他们的类型智能感知?
我可以将其描述为您想要命名的任何详细程度,但我没有时间进行简短的解释。我将在罗斯林解释我们是如何做到的。
首先,我们使用可以有效表示编辑的数据结构构建令牌流的不可变模型,因为显然编辑正是将会有很多内容。
使持久重用高效的关键见解是在编辑缓冲区中表示令牌的字符长度而不是字符位置;请记住,文件末尾的标记将在每次编辑时更改位置,但标记的长度不会更改。 如果您希望在极大的文件上有效,则必须不惜一切代价最大限度地减少总回复率。
一旦你拥有一个可以处理插入和删除的不可变模型来构建一个不可变的令牌流,而不是每次都重新整理整个文件,那么你必须执行相同的事情,但对于语法分析。 这实际上是一个相当难的问题。我建议你获得计算机科学的本科或研究生学位,重点是解析器理论,如果你还没有。我们获得了博士论文的人的帮助,他们在解析器理论上做了他们的论文,以设计算法的这一特定位。
然后,显然,构建一个可以分析C#的语法分析器。请记住,它必须分析已损坏的 C#,而不是正确的 C#;当程序处于非编译状态时,IntelliSense必须工作。因此,首先要对具有良好错误恢复特性的语法进行修改。
好的,所以现在你已经有了一个解析器,它可以有效地进行语法分析而不需要重新编译或重新解析除编辑区域之外的任何东西,大多数时候,这意味着你可以在击键之间进行工作。我忘了提及,当然你需要提出一些机制来不阻止UI线程,而在进行所有这些分析时,如果分析发生的时间要比两次击键之间的时间长。新的" async / await" C#5的功能应该有所帮助。 (我可以从个人经验告诉你:小心任务的扩散和取消令牌。如果你粗心大意,有可能进入一个状态,其中有数万个被取消的任务待定,那就是不快。)
现在你已经进行了语法分析,你需要构建一个语义分析器。由于您只是在进行智能感知,因此它不需要是一个特别复杂的语义分析器。 (我们的语义分析器必须进行适合于从正确的程序生成代码并从错误的程序中纠正错误分析的分析。)当然,它还必须对损坏的程序进行良好的语义分析,这确实会大大增加复杂性。
我的建议是从建立一个顶级"语义分析器,再次使用不可变模型,该模型可以将声明的源代码类型的状态从编辑持久化到编辑。顶级分析器处理 not 语句或表达式的任何内容:类型声明,指令,命名空间,方法声明,构造函数,析构函数等。构成"形状的东西"编译器生成元数据时的程序。
元数据!我忘记了元数据。您需要一个元数据阅读器。显然,您需要能够在引用库中类型的表达式上生成IntelliSense。我建议使用CCI库作为元数据阅读器,而不是反射。由于您只是在进行智能感知,显然您不需要元数据编写器。
无论如何,一旦你有一个顶级语义分析器,你就可以编写一个语句和表达式语义分析器来分析给定语句中表达式的类型。请特别注意名称查找和重载决策算法。方法类型推断将特别棘手,尤其是在LINQ查询中。
一旦掌握了所有这些,智能感应引擎应该很容易;只需计算当前光标位置的表达式类型并适当显示下拉列表。
创建我自己的相同标准对我来说有多难?
好吧,我们有一个团队,称之为十个人,并且它可能会采取,称之为五年,以便从头到尾完成所有事情。但我们还有很多工作要做,而不仅仅是IntelliSense引擎。这可能只占工作的40%。哦,有一半的人在VB上工作,现在我想起来了。但是那些人平均可能有五到十年的工作经验,所以如果你以前从未这样做过,他们会比你更快。
所以,让我们说你应该花大约10到20年的全职工作,独自工作,为C#构建一个Roslyn品质的智能感知引擎,可以接受大致接近正确的分析按键之间的程序。
如果你需要先做博士学位,那就更长了。
或者,你可以简单地使用Roslyn,因为它是的用途。这可能会花费你几个小时,但你不能自己做到这一点。这很有趣!
您可以在此处下载预览版本:
答案 1 :(得分:16)
这是微软通常会产生很好结果的领域 - 微软的开发者工具真的非常棒。销售他们的开发人员工具以及销售Windows以获得最佳的智能感知具有明显的商业优势,因此微软有理由将他所描述的资源用于他非常详细的答案中。不过,我认为值得指出一些事情:
您的客户可能实际上并不需要Microsoft实施提供的所有功能。就您需要提供给 客户/用户的功能而言,Microsoft解决方案可能会过度设计。除非您实际上实现了旨在与Visual Studio竞争的通用编码环境,否则您的预期用途可能会简化问题,或者允许您对Microsoft感觉到的解决方案做出妥协他们做不到。微软可能会花费资源来减少已经在几百毫秒内测量的响应时间。这可能不是你需要做的事情。 Microsoft正在花时间为其他人提供API以用于代码分析。这可能不是你计划的一部分。优先考虑您的功能并确定您和您的客户的“足够好”,然后估算实施该功能的成本。
除了承担实施您可能没有的要求的明显成本之外,如果您没有在团队中工作,Microsoft还会承担一些可能并不明显的成本。与团队相关的沟通成本很高。实际上,让五个聪明人花费更长时间来制作解决方案比单个聪明人生产同等解决方案所需要的要难得多。微软招聘实践和组织结构的某些方面使这种情况更有可能发生。如果你聘请了一群有自我意识的聪明人,然后让他们所有人做出决定,那么你也可以获得5%的更好的解决方案来获得500%的成本。这个5%更好的解决方案对微软来说可能是有利可图的,但对于一家小公司来说这可能是致命的。
从单人解决方案转变为5人解决方案会增加成本,但这只是团队内部开发成本。 Microsoft拥有独立的团队,致力于(大致)设计,开发和测试甚至是单一功能。跨越这些边界的同行之间的项目相关沟通具有比每个学科内部更高的摩擦力。这不仅会增加个人之间的沟通成本,还会导致团队规模扩大。还有更多 - 因为它不是一个由12个人组成的团队,而是由5个人组成的3个团队,这是向上沟通成本的3倍。微软选择承担的更多成本可能无法转化为其他公司的类似成本。
我的观点不是将微软描述为效率低下的公司。我的观点是,微软做出了大量关于从招聘,团队组织到设计和实施的决策,这些决策从对盈利能力和风险的假设开始,而这些假设根本不适用于非Microsoft的公司。
就智能感知而言,有各种各样的方法来思考这个问题。微软正在制作一个非常通用,可重复使用的解决方案,它不仅解决了智能感知,还针对代码导航,重构以及代码分析的各种其他用途。如果您的唯一目标是让开发人员轻松输入代码而不必输入太多内容,则无需以相同的方式执行操作。定位该功能不需要多年的努力,如果您不仅仅提供API,还可以执行各种创造性的事情,但实际上您也可以控制用户界面。