Tern
Tern 是一個(gè)javascript代碼分析引擎,其目標(biāo)是被代碼編輯插件使用以增強(qiáng)編輯器的javascript代碼智能編輯能力。其提供的主要特征如下:
- 變量和屬性的自動(dòng)完成
- 函數(shù)參數(shù)提示
- 查詢一個(gè)表達(dá)式的類型
- 查找定義
- 重構(gòu)
Tern是開源項(xiàng)目(MIT),使用javascript編寫,能運(yùn)行于node.js和瀏覽器中。
Editor plugins
Tern當(dāng)前支持的編輯器如下:
- Emacs
- Vim
- Sublime Text
- Brackets
- Light Table
- Eclipse(提供了一般性通用api)
- TextMate
社區(qū)支持
有一個(gè)論壇用于討論和問有關(guān)Tern的論壇,并會(huì)有一些最新消息的通告,比如新版本的發(fā)行。可以通過github issue tracker來報(bào)告缺陷。
歡迎通過pull requests來進(jìn)行代碼分發(fā)。
如果你正從中獲取收益,特別是用于盈利目的,考慮為更多的開發(fā)提供資金,Marijn Haverbeke將會(huì)為你提供咨詢。
文檔
了解如何安裝Tern,閱讀參考手冊(cè)是你需要進(jìn)行的第一步。
如果你對(duì)這個(gè)系統(tǒng)的內(nèi)容工作比較感興趣,可以查看下blog和一些會(huì)議上的視頻
Tern 使用手冊(cè)##
Tern又幾個(gè)組件組成,依賴你利用它來做什么,你將關(guān)注Tern的不同層次。Editor Plugins,它位于最高的層次。Tern server,它是在Server模塊(提供編程接口)的基礎(chǔ)上實(shí)現(xiàn),利用推斷引擎inference engine來做真正的類型推斷。
Tern server
bin/tern用來啟動(dòng)Tern server,你會(huì)經(jīng)常使用一個(gè)Editor plugin來啟動(dòng)它,但是也可以手動(dòng)啟動(dòng)它,這樣比較方便調(diào)試。(注意server的基礎(chǔ)是通過編程接口提供出來的,對(duì)于使用在瀏覽器中的場(chǎng)景,將直接使用編程接口而不是這里描述的http方式)。
Server啟動(dòng)時(shí)將在當(dāng)前文件夾或者其子文件夾下尋找.tern-project文件,讀取里面的內(nèi)容作為配置。如果沒有project文件,默認(rèn)配置將創(chuàng)建失敗。你可以通過放置一個(gè).tern-config文件來改變默認(rèn)配置,該文件的配置格式和.tern-project文件一致,并將該文件放在你的HOME目錄下。
Server在啟動(dòng)時(shí)將其監(jiān)聽的端口(默認(rèn)隨機(jī))寫入標(biāo)準(zhǔn)輸出,Server通過http方式和json格式數(shù)據(jù)進(jìn)行交互,客戶端可以通過http上傳代碼并詢問一些關(guān)于代碼的問題。
以下命令行標(biāo)識(shí)將得到支持:
--port <number>
指定監(jiān)聽端口,通過這種方式可以取代默認(rèn)的隨機(jī)端口方式
--host <host>
指定監(jiān)聽的host,默認(rèn)127.0.0.1
--persistent
默認(rèn)情況下,Server將在五分鐘沒有交互的情況下自動(dòng)關(guān)閉,通過該選項(xiàng)可以禁用自動(dòng)關(guān)閉
--ignore-stdin
默認(rèn)情況下,在標(biāo)準(zhǔn)輸入流關(guān)閉時(shí)Server將自動(dòng)關(guān)閉,通過該選項(xiàng)可以禁用該行為
--verbose
Server將輸出請(qǐng)求和返回的信息,以及錯(cuò)誤信息,這有助于調(diào)試
--no-port-file
Server將不會(huì)輸出.tern-port文件
JSON格式協(xié)議
向Tern發(fā)送查詢請(qǐng)求要通過POST方式發(fā)送,請(qǐng)求體以json格式傳送。請(qǐng)求提有三個(gè)可選字段:query,files,timeout。
query描述了你所請(qǐng)求的信息類型,如果請(qǐng)求只是為了推送新的代碼,那該字段可以忽略。files用于指定一組文件,如果請(qǐng)求所操作的代碼Server上已經(jīng)存在,并沒有添加新的文件,那么該字段將被忽略。timeout用于指定該請(qǐng)求的最大工作時(shí)長(zhǎng)(cpu時(shí)間),毫秒。
query是一個(gè)對(duì)象,至少有一個(gè)type屬性,用以標(biāo)識(shí)請(qǐng)求類型,其他屬性依賴于不同的類型而不同。
以下是Tern server所能理解的請(qǐng)求。(插件可能添加自定義的類型)
-
completions
在給定的位置,詢問代碼完成
字段:
-
file,end(required)
指定代碼完成的位置
-
types(optional,默認(rèn)false)
是否在結(jié)果數(shù)據(jù)中包含代碼完成的類型
depths(optional,默認(rèn)false)
docs,urls,origins(optional,默認(rèn)false)
-
filter(optional,默認(rèn)true)
是否只返回符合當(dāng)前位置的詞語的完成列表,否則返回全部
-
caseInsensitive(optional,默認(rèn)false)
當(dāng)前位置的詞語和潛在完成列表是否采用大小寫敏感性比較
-
guess(optional,默認(rèn)true)
當(dāng)找不到匹配的完成結(jié)果時(shí),是否返回啟發(fā)式的建議
-
sort(optional,默認(rèn)true)
結(jié)果是否排序
-
expandWordForward(optional,默認(rèn)true)
true,鼠標(biāo)所在的整個(gè)變量名將被包含,false,只有指定位置前的文本內(nèi)容會(huì)被考慮
-
omitObjectPrototype(optional,默認(rèn)true)
是否忽略O(shè)bject.prototype的屬性
-
includeKeywords(optional,默認(rèn)false)
當(dāng)代碼完成發(fā)生在一個(gè)屬性上,是否包含javascript的關(guān)鍵字
-
inLiteral(optional,默認(rèn)true)
字面量上是否返回完成內(nèi)容
返回結(jié)果包含兩個(gè)屬性,start和end,表示完成的詞語的偏移量,isProperty是布爾類型,表示完成的是否為一個(gè)屬性或者一個(gè)變量,completions包含一組完成
-
-
define
詢問表達(dá)式的定義。
略。
-
documentation
略
-
refs
獲取一個(gè)變量或?qū)傩缘乃幸谩?/p>
file,end(required)
start(optional)
返回:一個(gè)對(duì)象,包含name屬性,變量或?qū)傩缘拿?,refs是一個(gè)數(shù)組,包含{file,start,end},如果是變量,將包含type:"global"或"local"
-
rename
重命名一個(gè)變量
file,end(required)
start(optional)
返回:一個(gè)對(duì)象,changes屬性是一個(gè)數(shù)組,該數(shù)組包含{file,start,end,text},客戶端需要根據(jù)這個(gè)結(jié)果做真正的修改。
-
properties
獲取一個(gè)對(duì)象的所有屬性名
略 -
files
獲取server當(dāng)前持有的文件
編程接口
基礎(chǔ)Server是沒有http交互也沒有配置文件的,其實(shí)現(xiàn)在lib/tern.js中。
該包提供了一個(gè)Server構(gòu)造器,通過它我們可以創(chuàng)建一個(gè)server對(duì)象。它使用一個(gè)對(duì)象作為配置,該配置包含的選項(xiàng)如下(都有默認(rèn)值):
-
defs(array of strings)
類型定義對(duì)象,加入到sever
-
plugins(object)
指定server需要加載的插件
-
ecmaVersion(number)
按ECMAScript哪個(gè)版本進(jìn)行解析。應(yīng)該選擇5或6,默認(rèn)6.
-
getFile(function)
為server提供一個(gè)獲取文件內(nèi)容的方式。如果async選項(xiàng)為false,該函數(shù)接收filename作為參數(shù),并返回一個(gè)字符串,或者接收一個(gè)filename參數(shù)和一個(gè)callback參數(shù),callback接收error信息作為第一個(gè)參數(shù),第二個(gè)參數(shù)為字符串類型的文件內(nèi)容。
-
async(bool)
指定getFile是否為異步,默認(rèn)為false.
fetchTimeout(number)
指定異步getFile最大等待時(shí)間,單位為毫秒。默認(rèn)1000。
Server對(duì)象擁有以下方法:
-
addFile(name:string,text?:string,parent?:string)
向server注冊(cè)一個(gè)文件。注意文件也可包含在請(qǐng)求中,如果需要通過這個(gè)方法加載一個(gè)依賴,就在第三個(gè)參數(shù)中指定文件名稱(如果Tern理解這個(gè)文件)。該文件將計(jì)入依賴預(yù)算。
-
delFile(name:string)
注銷一個(gè)文件。
-
request(doc:object,callback:fn(error,response))
執(zhí)行一個(gè)請(qǐng)求。doc是一個(gè)json文檔,其格式在JSON格式協(xié)議中有所描述。請(qǐng)求執(zhí)行完畢后,callback將得到執(zhí)行,如果有錯(cuò)誤發(fā)生將在第一個(gè)參數(shù)中傳入,返回內(nèi)容將以第二個(gè)參數(shù)傳入。
當(dāng)server并沒有配置為異步方式,callcack
-
flush(callback:fn())
強(qiáng)行讀取并解析所有文件,然后調(diào)用callback。
-
on(eventType:string,handler:fn())
注冊(cè)事件處理器
-
off(eventType:string,handler:fn())
注銷事件處理器
-
addDefs(defs:object,atFront?:bool)
添加類型定義,atFront表示是否添加在已有定義之前
-
deleteDefs(name:string)
刪除類型定義
-
loadPlugin(name:string,options?:object)
加載一個(gè)server plugin
Server會(huì)觸發(fā)以下類型的事件:
-
reset
當(dāng)server拋棄已有的分析并開始新的運(yùn)行狀態(tài)時(shí)
-
beforeLoad(file)
分析一個(gè)文件前,file是個(gè)對(duì)象包含{name,text,scope}屬性
-
afterLoad(file)
分析一個(gè)文件后
-
preParse(text,options)
在一個(gè)文件解析之前,將傳入給定的text和options
-
postParse(ast,text)
在一個(gè)文件解析之后,傳入ast樹和被解析的文件
-
preInfer(ast,scope)
在類型推斷之前,傳入ast樹和scope對(duì)象
-
postInfer(ast,scope)
在類型推斷之后
-
typeAt(file,end,expr,type)
在查找文件的指定點(diǎn)end處的類型后觸發(fā)
-
completion(file,query)
代碼完成開始時(shí)執(zhí)行,可以返回一個(gè)代碼完成結(jié)果來替換默認(rèn)算法