トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

scala-refactoring

[Scala]

scala-refactoring

Scalaのソースコードをリファクタリングするためのライブラリensimeを修正するために必要な知識が全然ないので、ドキュメントを読んでいく。

  公式のドキュメント

Rename
名称変更
Extract Local
展開
Inline Local
内包
Extract Method
関数の展開
Organize Imports
import編成、import編成は現在のファイル内のimportステートメントをきれいにします。しかしこの機能は未使用のimportを削除したり、コンパイルに必要なimportを追加したりはしません。
Move Class
クラス移動

  実装サンプル

すべて、 scala-refactoring より

    • 4. Tool Integration の翻訳になる

4. ツールの結合

この章では、実装済みのrefactoringsがどのように他のソフトウェアに結合されうるのか、そして現在のScala IDE for Eclipseにどのように統合されているのかを見ていこうと思います。

  • 4.1. 依存関係

リファクタリングのライブラリはScalaのコンパイラのみに依存します、サードパーティーのライブラリは使われていません。しかし、またどんなユーザーインターフェースも持っていません。つまり、シームレスなツールの結合には、結合する側のツールによってそれが実装される必要があるということです。 IDEへの組み込みを行うにあたり、リファクタリングの実装はそれ自身のコンパイラがソースコードをパースしチェックするようなインスタンスは生成しません。これはたいていすでにIDEによってなされており、そのようなことをすれば二度手間になり明らかにリファクタリングの処理が遅くなってしまうでしょう。 プロジェクトのコンパイル単位にアクセスするために、Refactoring trait (すべての実装が継承する)はコンパイラのインスタンスの抽象メンバをもちます:

  trait Refactoring extends . . . {
  val global: scala.tools.nsc.interactive.Global
  . . .
  }

リファクタリング自体の実装のインスタンスを作るには、コンパイラへの参照が提供される必要があります。自動テストのためにこれがどのようになされたのか、章5のp.71に説明されています。説明としては、章3のp.39の始めのほうでそれぞれの段階でのリファクタリングが実演されています。というのは、次のページの図4.1にてユーザとIDE、そしてリファクタリングライブラリの間でのシーケンスがビジュアル化されています。prepareperform メソッドは MutliStageRefactoring という抽象クラスの一部で必要とされるパラメーターです。(p.63の図4.2を見よ) 

  • 4.2. ライブラリの結合

どのようにしてリファクタリングが組み込まれるかをちゃんとした例をもって示します: リファクタリングのエディタはp.63の図4.3で示されます。詳細な手順を以下に示していきます。

    • 図4.1 あとは省略

ファイルが存在しません。

名称変更のリファクタリングのみのための例です、しかしほかの処理もあとから結合可能です。以下のコードはアクションリスナーにおいて実行されます。最初に私たちはrefactoringのオブジェクトを生成しなければいけない。

val refactoring = new Rename with CompilerProvider with GlobalIndexes {
  val ast = treeFrom(editor.getText)
  val index = GlobalIndex(ast)
}

この例中にあるコンパイラとはCompilerProvider traitから提供されているもので、これはまたtreeFromメソッド(StringをTreeのインスタンスに変換するもの)を渡してくれます。私たちはこれを自分自身で行わなければならない、なぜならエディタはコードをパースすることがまだできないからで、実際のIDEにリファクタリングを組み込んだとしたらまた違ったものになるでしょう。

名称変更のリファクタリングはさらにプログラム全体のインデックスを必要とします。そこで私たちはGlobalIndexesという、トレイト(これはASTからインデックスを構築します)を使用します。(2.2章のp11を見よ)

多くのリファクタリングは動かすためにソースコードの選択が必要です。Selection トレイトは2つの実装があります、FileSelectionTreeSelectionです。選択が何によってもたらされるかによって、どちらかを使うほうが簡単でしょう。私たちは今回はエディタの選択範囲からFileSelectionを作ります。

val selection: refactoring.Selection = {
  val file = refactoring.ast.pos.source.file
  val from = editor.getSelectionStart
  val to = editor.getSelectionEnd
  new refactoring.FileSelection(file, from, to)
}

選択範囲が与えられることで、私たちはリファクタリングの最初の段階を宣言できます => prepare メソッドです。

prepare を呼び出すと Either[PreparationError, PreparationResult] が返ります、ですので私たちは結果を展開するかエラーであれば処理を停止しなければならない(…名称変更のリファクタリングのエラーの原因はたいてい不適切な選択によるものです)。

val preparationResult = refactoring.prepare(selection) match {
  case Left(refactoring.PreparationError(error)) =>
    showError(error)
    return
  case Right(r) => r
}

preparerationResultの結果は選択したリファクタリングの実際の型によります。名称変更の場合、名称変更したいものの木構造をふくんだものが単純に返ります。次にリファクタリングを実行しましょう、これには必要なパラメータを通す必要があります。それは新しい名称です。新しい名称を入力するダイアログを開くaskName関数です。

val refactoringParameters = {
  val selectedName = preparationResult.selectedTree.symbol.nameString
  askNewName(selectedName)
}

リファクタリングを実行することは、多くのパラメーターを通し、成功の際変更のリストが戻ること以外、準備することととても似ています。

val changes: List[Change] =
  refactoring.perform(selection, preparationResult, refactoringParameters) match {
    case Left(refactoring.RefactoringError(error)) =>
      showError(error)
      return
    case Right(r) => r
  }

私たちのエディタでは、変更を単純にファイルに適用します、その際はChange.applyChangesを使用します。実際のエディタでは、ユーザは変更を適用する前に提示された変更を確認するチャンスがあるべきです。・・・(以下略、残りに関しては英文をご確認願います)

  • 4.3. Scala IDE for Eclipseとの結合
お名前: コメント: