Javascript代码分析引擎-Tern

Tern

Tern 是一个javascript代码分析引擎,其目标是被代码编辑插件使用以增强编辑器的javascript代码智能编辑能力。其提供的主要特征如下:

  • 变量和属性的自动完成
  • 函数参数提示
  • 查询一个表达式的类型
  • 查找定义
  • 重构

Tern是开源项目(MIT),使用javascript编写,能运行于node.js和浏览器中。

Editor plugins

Tern当前支持的编辑器如下:

  • Emacs
  • Vim
  • Sublime Text
  • Brackets
  • Light Table
  • Eclipse(提供了一般性通用api)
  • TextMate

社区支持

有一个论坛用于讨论和问有关Tern的论坛,并会有一些最新消息的通告,比如新版本的发行。可以通过github issue tracker来报告缺陷。

欢迎通过pull requests来进行代码分发。

如果你正从中获取收益,特别是用于盈利目的,考虑为更多的开发提供资金,Marijn Haverbeke将会为你提供咨询。

文档

了解如何安装Tern,阅读参考手册是你需要进行的第一步。

如果你对这个系统的内容工作比较感兴趣,可以查看下blog和一些会议上的视频

Tern 使用手册##

Tern又几个组件组成,依赖你利用它来做什么,你将关注Tern的不同层次。Editor Plugins,它位于最高的层次。Tern server,它是在Server模块(提供编程接口)的基础上实现,利用推断引擎inference engine来做真正的类型推断。

Tern server

bin/tern用来启动Tern server,你会经常使用一个Editor plugin来启动它,但是也可以手动启动它,这样比较方便调试。(注意server的基础是通过编程接口提供出来的,对于使用在浏览器中的场景,将直接使用编程接口而不是这里描述的http方式)。

Server启动时将在当前文件夹或者其子文件夹下寻找.tern-project文件,读取里面的内容作为配置。如果没有project文件,默认配置将创建失败。你可以通过放置一个.tern-config文件来改变默认配置,该文件的配置格式和.tern-project文件一致,并将该文件放在你的HOME目录下。

Server在启动时将其监听的端口(默认随机)写入标准输出,Server通过http方式和json格式数据进行交互,客户端可以通过http上传代码并询问一些关于代码的问题。

以下命令行标识将得到支持:

--port

指定监听端口,通过这种方式可以取代默认的随机端口方式

--host

指定监听的host,默认127.0.0.1

--persistent

默认情况下,Server将在五分钟没有交互的情况下自动关闭,通过该选项可以禁用自动关闭

--ignore-stdin

默认情况下,在标准输入流关闭时Server将自动关闭,通过该选项可以禁用该行为

--verbose

Server将输出请求和返回的信息,以及错误信息,这有助于调试

--no-port-file

Server将不会输出.tern-port文件

JSON格式协议

向Tern发送查询请求要通过POST方式发送,请求体以json格式传送。请求提有三个可选字段:query,files,timeout。

query描述了你所请求的信息类型,如果请求只是为了推送新的代码,那该字段可以忽略。files用于指定一组文件,如果请求所操作的代码Server上已经存在,并没有添加新的文件,那么该字段将被忽略。timeout用于指定该请求的最大工作时长(cpu时间),毫秒。

query是一个对象,至少有一个type属性,用以标识请求类型,其他属性依赖于不同的类型而不同。

以下是Tern server所能理解的请求。(插件可能添加自定义的类型)

  1. completions

    在给定的位置,询问代码完成

    字段:

    • file,end(required)

      指定代码完成的位置

    • types(optional,默认false)

      是否在结果数据中包含代码完成的类型

    • depths(optional,默认false)

    • docs,urls,origins(optional,默认false)

    • filter(optional,默认true)

      是否只返回符合当前位置的词语的完成列表,否则返回全部

    • caseInsensitive(optional,默认false)

      当前位置的词语和潜在完成列表是否采用大小写敏感性比较

    • guess(optional,默认true)

      当找不到匹配的完成结果时,是否返回启发式的建议

    • sort(optional,默认true)

      结果是否排序

    • expandWordForward(optional,默认true)

      true,鼠标所在的整个变量名将被包含,false,只有指定位置前的文本内容会被考虑

    • omitObjectPrototype(optional,默认true)

      是否忽略Object.prototype的属性

    • includeKeywords(optional,默认false)

      当代码完成发生在一个属性上,是否包含javascript的关键字

    • inLiteral(optional,默认true)

      字面量上是否返回完成内容

    返回结果包含两个属性,start和end,表示完成的词语的偏移量,isProperty是布尔类型,表示完成的是否为一个属性或者一个变量,completions包含一组完成

  2. define

    询问表达式的定义。

    略。

  3. documentation

  4. refs

    获取一个变量或属性的所有引用。

    file,end(required)

    start(optional)

    返回:一个对象,包含name属性,变量或属性的名字,refs是一个数组,包含{file,start,end},如果是变量,将包含type:"global"或"local"

  5. rename

    重命名一个变量

    file,end(required)

    start(optional)

    返回:一个对象,changes属性是一个数组,该数组包含{file,start,end,text},客户端需要根据这个结果做真正的修改。

  6. properties

    获取一个对象的所有属性名

  7. files

    获取server当前持有的文件

编程接口

基础Server是没有http交互也没有配置文件的,其实现在lib/tern.js中。

该包提供了一个Server构造器,通过它我们可以创建一个server对象。它使用一个对象作为配置,该配置包含的选项如下(都有默认值):

  • defs(array of strings)

    类型定义对象,加入到sever

  • plugins(object)

    指定server需要加载的插件

  • ecmaVersion(number)

    按ECMAScript哪个版本进行解析。应该选择5或6,默认6.

  • getFile(function)

    为server提供一个获取文件内容的方式。如果async选项为false,该函数接收filename作为参数,并返回一个字符串,或者接收一个filename参数和一个callback参数,callback接收error信息作为第一个参数,第二个参数为字符串类型的文件内容。

  • async(bool)

    指定getFile是否为异步,默认为false.

  • fetchTimeout(number)
    指定异步getFile最大等待时间,单位为毫秒。默认1000。

Server对象拥有以下方法:

  • addFile(name:string,text?:string,parent?:string)

    向server注册一个文件。注意文件也可包含在请求中,如果需要通过这个方法加载一个依赖,就在第三个参数中指定文件名称(如果Tern理解这个文件)。该文件将计入依赖预算。

  • delFile(name:string)

    注销一个文件。

  • request(doc:object,callback:fn(error,response))

    执行一个请求。doc是一个json文档,其格式在JSON格式协议中有所描述。请求执行完毕后,callback将得到执行,如果有错误发生将在第一个参数中传入,返回内容将以第二个参数传入。

    当server并没有配置为异步方式,callcack

  • flush(callback:fn())

    强行读取并解析所有文件,然后调用callback。

  • on(eventType:string,handler:fn())

    注册事件处理器

  • off(eventType:string,handler:fn())

    注销事件处理器

  • addDefs(defs:object,atFront?:bool)

    添加类型定义,atFront表示是否添加在已有定义之前

  • deleteDefs(name:string)

    删除类型定义

  • loadPlugin(name:string,options?:object)

    加载一个server plugin

Server会触发以下类型的事件:

  • reset

    当server抛弃已有的分析并开始新的运行状态时

  • beforeLoad(file)

    分析一个文件前,file是个对象包含{name,text,scope}属性

  • afterLoad(file)

    分析一个文件后

  • preParse(text,options)

    在一个文件解析之前,将传入给定的text和options

  • postParse(ast,text)

    在一个文件解析之后,传入ast树和被解析的文件

  • preInfer(ast,scope)

    在类型推断之前,传入ast树和scope对象

  • postInfer(ast,scope)

    在类型推断之后

  • typeAt(file,end,expr,type)

    在查找文件的指定点end处的类型后触发

  • completion(file,query)

    代码完成开始时执行,可以返回一个代码完成结果来替换默认算法

你可能感兴趣的:(Javascript代码分析引擎-Tern)