实例分析SharpDevelop代码完成功能(续)——添加对Boo语言的支持

接着上一篇《实例分析SharpDevelop代码完成功能》里添加的InsightWindow的功能。这回将要为那个CSharpCodeCompletionDemo添加Boo语言的代码自动完成功能的支持。

 

Boo语言,可能不少人还没有听说过。好像是语言使用的排行榜上100名之外的一种编程语言。语法接近Python。就连Wiki上对它的介绍也少得可怜。目前支持这种语言的IDE只有SharpDevelop以其衍生的IDE

 

SharpDevelop支持BooCodeCompletion,但是给的Sample里,只支持C#VB.NET。下面就来介绍,如何一步步地让Sample支持Boo

 

C#不同,Boo是一种弱类型的语言,所以(也许不充分)不能像C#VB那样用一个Parser进行分析来得到语法树。SD通过插件的方式,提供了对于PythonBoo等语言的支持。如图1所示。

 

1. SharpDevelop中的Backends Bindings

 

BooBinding里,应该就提供了SD对于支持Boo所需要的全部代码。再来看BooBinding

 

2. BooBinding Project

 

里面居然专门有一个文件夹叫CodeCompletion,看来我们要找的东西都在里面了。下一步就是支持Boo了,其实说起来还是很容易的,不就是等价类替换一下嘛。在上一篇里介绍的用于CodeCompletion的类不少,但是语言相关的大约有5个类。3种语言的的这5 个类如表1所示。

 

 

C#

VB

Boo

Parser

ParserFactory

ParserFactory

BooParser

Ambience

CSharpAmbience

VBNetAmbience

BooAmbience

Resolver

NRefactoryResolver

NRefactoryResolver

BooResolver

Expression Finder

CSharpExpressionFinder

VBExpressionFinder

ExpressionFinder

LanguageProperties

LanguageProperties

LanguageProperties

BooLanugageProperties

1. 三种语言对于CodeCompletion功能的等价类

 

在进行无味的等价类替换工作之前先分别大致介绍一下3个类的用途。

 

1.       Ambience:词典里的是“环境,气氛”。从名字看不出什么用途,图3是其定义。

 

3. IAmbience

 

从这个接口里的方法大致就能猜个八九不离十了。就是将Parse出来的类啊,变量啊转化成用户可读的文本。因为不同的编程语言有不同的语言和专有名词,所以转化出来的文本也应该根据语言有所不同喽。这个接口,就分离了不同语言间这种可读性的不同。

2.       ExpressionFinder:感觉图4IExpressionFinder的定义没有给出比这个名字更多的信息了。

 

4. IExpressionFinder

 

这个就是源代码里找表达式的接口。通过这个接口里定义的方法,就可以知道当前位置上应该是个什么东西,以及当前位置上是个什么东西。是个数字,还是变量等等。它找到的结果是个这么个东西。如图5

 

5. ExpressionResult

 

有兴趣的话,可以去看看它的内部结构。这里就不展开了。

 

3.       IParser:这个就是最重要的部分。可以叫解析器吧。图6里把函数的参数也显示了出来,更能清楚地表达IParser接口的作用。(C#VBParser接口与此略有不同)

 

6. IParser

 

其中Parse函数的stringfileContent就是要Parse的源文件。Demo的注释里就说明了fileName参数不一定就是源文件在磁盘上的文件名,就当是一个GUID就可以。再来看一下图7所示的这个函数的返回类型的结构就一目了然了。

 

7. ICompilationUnit

 

很强大的样子,从源文件直接得到了里面的Class,Attribute,Usings……,这些数据就可以用来做CodeCompletion了。如果看一下CSharpBooParser的源代码就可以知道这两个Parser是完全不一样的。CSharpParser是完全的对源文件进行分析的结果。而BooParser只是搭了Boo Compiler的便车,在使用BooCompiler编译源文件的过程中让Compiler“顺便”帮它把它想要的语法树给它了。所以CSharpParser的效率会高不少。例子里就是用这个Parser在后台每2秒做一次Parser,用结果对ProjectContent进行更新。Resolver就是用Parser进行表达式类型的分析的。SharpDevelop的运行时也与此类似。

 

4.       Resolver:用ExpressionFinder找到当前的Expression之后,就会用Resolver去知道当前的Expression倒底是个什么东西。Resolver的接口如图8所示。非常简单。

 

8. IResolver

 

Resolve出来的Result也很简单。如图9所示。

 

9. ResolveResult

 

有了上面的分析,解理这个图应该不成问题了吧。

 

5.       LanguageProperties:这个在DEMO里的作用就是指示当前语言是什么。

 

基于上面的分析,我们知道BooParser使用到了Boo的编译器,所以先把要用到的Library找到。如下:

1.       BooBinding

2.       Boo语言编译支持:Boo.Lang, Boo.Lang.Compiler, Boo.Lange.Parser, Boo.Lang.Useful

3.       还有一些其它的SharpDeveloprLibraryICSharpCode.SharpDevelop….

为了提供BooCodeCompletion的支持居然要多加这么多库,一开始也没有想到。因为C#CodeCompletion只有34个就足够了。(而且这些库都是必需的)

 

终于到了更改源代码的时候了。先要把Demo里的所有实例化这些Resolver, Ambience, Parser, ExpressionFinder的所有代码进行重构。把实例化过程分离出来,并交给MainForm来做。然后,添加Boo语言支持的工作就变成了——给四个工厂方法添加一个Else if分支——这么简单。其中一个工厂方法的代码如下。

 

 1//应该不需要注释了吧
 2public static IAmbience GetAmbience()
 3{
 4     if (CurrentLanguageProperties == LanguageProperties.VBNet)
 5          return new VBNetAmbience();
 6     else if (CurrentLanguageProperties == LanguageProperties.CSharp)
 7          return new CSharpAmbience();
 8     else if (CurrentLanguageProperties == BooLanguageProperties.Instance)
 9          return new BooAmbience();
10     else
11          throw new NotSupportedException();
12}

13

 

修改完成之后。运行一下。如图10所示。

 

 

图10. Boo代码完成功能

表面上是成功了,可以分析出类和方法。但是事实上运行一会儿就会Crash,而且如果改了方法名,给的Code Completion还是原来的结果。可见后台的Parse线程成功地走了一次,然后就死掉了。还把整个程序搞死了。

后来经过向Output输出消息,找出了出错的地方,是BooParser在调用Boo compiler的时候有一个编译步骤出现了StackOverflowException。这个问题可以通过稍稍修改BooParser的方式实现。有兴趣的读者可以自己尝试一下。修复版的代码将会在下一个续文中给出。这里是添加了Boo语言支持的CodeCompletionDemo的源代码。

 

posted on 2008-11-28 23:45  南柯之石  阅读(4122)  评论(9编辑  收藏  举报

导航