jscomplete-vim ちょっと賢くした(Addtive, Multiplicative Operator編 + α)

ちょっとずつ賢くしてます。

+-*/%演算子の演算を少し加えた。
ただし、数値の演算はかなり適当というか、Vim script に NaN がなく、演算が失敗する時は 0 が返る仕様っぽいため、JavaScriptでは NaN が返るような演算でも 0 を返す仕様(バグ)になっている。数値の演算はプライオリティが低いと見なして現在は放置。

よって、

var o = {
  NaN: "OK",
};
o[10 * "a"]._
//          ↑カーソル位置

の様なのは現状はまだ無理。

+αの修正

まず、jscomplete-vimがどんなことをやっているか書こう。
目標は適切なプロパティ名の補完にある。んで、プロパティ名が必要そうな場面は、.[がある時になる。最終的にはグローバルオブジェクトのプロパティも補完対象にするつもりだが、まだ実装には仕込んでいない。まあともかく、.[がある時に補完を開始するわけだ。

だいたいの流れとしては以下の様な感じ

  1. カーソル位置から後方に式をパースしてトークンリストを得る
  2. トークンリストの実行
    • 変数(ビルトイン以外のIdentifier)があれば、その変数定義を探してパース等
  3. 最終的に何のオブジェクトであるかを判別し、補完リストを返す

んで、最初のトークンリストを得るところが問題。
開始すると、カーソル位置から.[があるところまでをプロパティ名の一部と見なして変数に補完しておく。
次に、.[より前、後方にとなるトークンのリストを得ようと試みる。このLeft-Hand-Side Expressionとなる部分まで。

後方へ見ていくわけだが、例えば以下の様なコードを考えてみよう。

{
  // Statement List
} (new Date)._
//           ↑カーソル位置
  1. BlockStatement
    1. StetementList
  2. ExpressionStatement
    1. Expression(Group)
      1. NewExpression
      2. PrimaryExpression

という構成だ。

ここで、必要なのはExpression(Group)部分以降となる。}が区切りとなるわけだが、常に区切ってしまってよいか?
下記別例の様に否である。

var func = function(){
}
(new Date)._
//         ↑カーソル位置

この場合は、function(){...}(new Date)になる。
普通はこんな書き方はしないわけだけど、可能な限り正しくパースするには考慮する必要があり、}を単純に区切りとしてはいけないことが分かる。}はBlockStatementの終了にもなるし、ObjectLiteralかもしれないし、FunctionLiteralの一部かもしれないわけだ。

この辺りの考慮が不完全(まだ完全じゃない気がする)だったので、もう少しマシな感じに修正した。