MPS 2020.1 ヘルプ

マイグレーション

言語が公開され、ユーザーがそれを使い始めた後、言語の作者は言語定義へのさらなる変更に注意しなければなりません。特に、概念を削除したり、プロパティ、子、概念への参照を追加および削除すると、前の言語バージョンと次の言語バージョンの間に互換性がなくなります。次の言語バージョンに更新すると、言語のユーザーに影響があります。自分のモデルが言語定義と一致しなくなり、適切なエラーがモデルから報告されるためです。

MPS はプロジェクトで使用されている言語のバージョンを追跡し、言語の使用箇所を最新のバージョンにアップグレードするための自動移行を提供します。言語設計者は、メンテナンス " 移行 " コードを作成してユーザーコードに対して自動的に実行し、言語定義に加えられた変更に準拠するようにユーザーコードを変更することができます。これは言語の移行と呼ばれます。

完全な言語の移行ストーリーには、いくつかの側面があります。

  • 言語設計者は、ユーザーコードを移行するためのスクリプトを作成し、言語とバンドルすることができます。

  • MPS はクライアントコードで使用されている言語バージョンを自動的に追跡します

  • MPS は、ユーザーのプロジェクトがすべての言語変更で最新であることを制御します

  • MPS は必要に応じて必要な移行を実行します

MPS では、2 種類の移行方法があります。

  • 言語の移行 - 次のバージョンの言語定義に準拠するようにプロジェクトをアップグレードするマイグレーション。各言語の移行は、言語定義のバージョンに関連付けられています。

  • プロジェクトのマイグレーション - これらは言語の使用箇所によって引き起こされるのではなく、代わりにそれら自身が実行されるべき条件を定義します。これらの移行は常にプロジェクト全体に適用されます。

言語バージョン

言語は、モジュール定義(.mpl)ファイルにバージョン番号を格納します。この数字は、言語の「マイグレーション」の側面で新しいマイグレーションが作成されたときに増加します。

言語を使用するモジュールには、モジュール(.msd、.mpl)ファイル内の使用されている各言語参照に関連付けられたバージョン番号が含まれています。これらはモジュールによって使用される言語バージョンを表します。このモジュールに対して対応する移行を実行して新しい言語バージョンに移行すると、番号が変わります。

言語のバージョン番号は、言語の Properties ダイアログで手動で表示および変更できます。

Migrationx1003

利用可能な 2 つの番号があることに注意してください。

  • 言語バージョン - 言語の構造が変わるたびに更新されます

  • モジュールバージョン - モジュール内のノードへの参照が移行されるたびに更新されます。ノードの移動など、ソースを持つモジュールで移行を実行する場合は、移行が必要です。移行は参照または依存するモジュールで実行されます。モジュールバージョンはそれを追跡します。

移行アシスタント

現在開いているプロジェクト内のモジュールが、現在存在しているものよりも古い言語のバージョンを参照していることを MPS が検出すると、移行アシスタントが実行されます。プロジェクトを最新バージョンの言語に更新するためにマイグレーションを実行するかどうかをユーザーにプロンプトします。

Migration1003

実行される移行の詳細リストがユーザーに提示されます。

Migration1

If the user triggers the migration, the project is fully migrated: In case of problems preventing the migration, a list of problems together with the list of not migrated code is presented to the user.

言語の移行を定義する

言語定義のマイグレーションの側面では、マイグレーション移行クラスとして定義されています。移行クラスは、jetbrains.mps.lang.migration 言語で定義されている MigrationScript 概念のノードです。

Migration1001

言語の番号と移行

  • 各移行スクリプトの名前には番号が付いています

  • 各移行スクリプトは from version プロパティを定義します

新しい移行スクリプトが作成されると、言語バージョンが 1 増加し、移行の fromVersion フィールドがその言語バージョンの古い値に設定されます。作成された移行スクリプトは、古いバージョンから新しいバージョンへの移行を 実行していると言えます。

言語の番号と移行のヒントとコツ

  • 移行を見逃すことはできません。言語にバージョン X とバージョン Y からの移行が含まれている場合は、X と Y の間の各バージョンの移行も含まれているはずです。一部のバージョンで移行が見つからない場合、これはバージョン X から移行できないことを意味します。そのような言語の生成はエラーで終わるでしょう。

  • 言語のすべての移行を保存する必要はありません。一部の言語が「公開」されていて、古い移行の一部を削除する必要がある場合は、削除することもできます。残りのマイグレーションの from バージョンは、範囲 A..B を形成するはずです。ここで、A は任意の古いバージョンで、B = <現在のバージョン> - 1 です。

  • マイグレーションが誤って作成され、公開されていない(つまり、自分のプロジェクトで実行したユーザーがいない)場合は、自由に削除できます。移行を削除した後、言語のコンテキストメニューから言語のバージョンを修正を実行します - このアクションにより、言語のバージョンを最後の移行のバージョンと同期させることができます。これをするとき十分気をつける

Migration1002

移行のしくみ

Migrationx1002

マイグレーションによって提供される可能性があるいくつかのオプションの要素があります。

  • 実行後 - 移行スクリプト間に順序付けの制約を設ける

  • 注釈データを生成する - このスクリプトによって生成され、後の移行スクリプトによって消費される可能性がある移行データを保持するために使用される ConceptDeclaration を指定します。

  • 注釈データが必要 - 以前のマイグレーションスクリプトによって生成されたマイグレーションデータを表すために使用される ConceptDeclaration を指定します。また、この移行スクリプト内でデータを表すための論理名をデータに付けます。

  • データを生成する (非推奨) - 移行データを転送する従来の変種は、ノード注釈の代わりに外部ファイルを使用します。

  • データが必要です (非推奨) - 移行データの転送の従来の変種。

  • description - スクリプトのわかりやすい説明文

  • execute メソッド - 各マイグレーションは execute() メソッドを定義します。これはユーザーモデルの実際のモデル変換を実行します。この方法は、パラメーターとしてユーザモジュールを受け取り、必要な注釈データセクション内の定義された要素を参照することができます。

データ本番と消費

移行スクリプト間でデータを渡す機能は、移行プロセス分割するのに役立ちます。たとえば、ある移行スクリプトは古い概念から新しい概念にノードを移行しますが、次の移行スクリプトは新しいノードを指すように元のノードへのすべての参照を移行します。これが機能するためには、最初のスクリプトは新旧のノードの ID を格納し、生成されたデータとしてマッピングを公開する必要があります。2 番目の移行スクリプトは、必要なデータとしてデータを消費します。古いノードへの参照を更新する必要があるたびに、データは新しいノードの ID を見つけるために使用されます。技術的には、データを生成することは、データが関連する場所に十分近い任意のノードに、データを含む特別な属性を単に接続することです。注釈がモデル全体に関連しているために注釈を配置する特定の場所がない場合、データノードは現在のモデルの新しいルートとしてアタッチされます。

データを含むノードを生成する移行スクリプトは、そのようなノードの概念を宣言し、モデルにそのような注釈をそれぞれ挿入するために putData () 構造を使用する必要があります

producedata

データを含むノードは、データが生成されたモジュールに応じて、他のモジュールで実行されている他の移行スクリプトによって取得できます。

requiredata

移行スクリプトの順序

注釈データ必要とし、注釈データセクションを生成することによって表現される移行スクリプト間の暗黙の依存関係は、移行スクリプトの正しい順序付けに注意を払うでしょう。スクリプトがいくつかのモジュールを移行するとき、このモジュールとそのすべての依存関係のために保存されたデータを使うことができるため、消費するスクリプトはモジュールのすべての依存関係で必要なすべてのプロデューサーを走らせた後に初めてモジュールの移行を始めます。これらの依存関係を明示的に表現する必要はありません。

しかし、他のスクリプトが同じモジュールに対して実行された後でのみ(依存関係に注意を払わずに)あるスクリプトを実行する必要がある場合、そのような順序付け制約は execute after セクションを通して表現できます。たとえば、あるプロパティがある概念からその概念(別の言語で宣言されている)に移動された場合、移行は 2 つの移行スクリプトで表すことができます。サブコンセプトに適用可能な最初のスクリプトは、古い非推奨プロパティから新しいプロパティにプロパティ値をコピーします。2 番目のスクリプトはスーパーコンセプトに適用でき、サブコンセプトのインスタンスではないスーパーコンセプトのそのようなインスタンスの新しいプロパティをデフォルト値で開始します。そして、2 番目のスクリプトが、移動されたプロパティの値に応じて他の初期化を行うとしましょう。2 番目のスクリプトは最初のスクリプトの後にのみ実行し、すべてのモジュールで実行する必要があります。

移行を定義するための言語

jetbrains.mps.lang.migration 言語は、移行スクリプトに固有のすべての概念を定義しています。マイグレーションを定義するときには、BaseLanguage 言語と jetbrains.mps.lang.smodel および .query 言語を一緒に使用してモデルを操作することができます。ofType <モデル> 構成要素は、渡された SModule:に含まれるモデルを取得するのに特に役立ちます。

sequence<SModel> models = m.getModels();&nbsp; models.ofType<model>.selectMany({~model => model.nodes(BaseDocComment); }).forEach({~node => ... });

通常の移行では、最初に移行アスペクトモデルを移行から除外し、次に移行が必要なノードをスキャンします。新しいノードが作成され、古いノードの値と子で初期化されます。その後、古いノードが新しいノードに置き換えられます。新しいノードの ID を古いノードの ID の値に設定すると、ターゲットを失うことなくこのノードへの参照を移行できます。

void execute(SModule m) { sequence<model> models = ((sequence<model>) m.getModels()).where({~it => !it.isAspectModel(migration); }); models.selectMany({~m => m.nodes(OldComponent); }).forEach({~oldNode => node<NewComponent> newNode = <NEW component $( oldNode.name )$ {>; *( oldNode.member )* ((SNode) newNode/).setId(((SNode) oldNode/).getNodeId()); oldNode.replace with(newNode); }); }

概略図

  1. 変換は何らかのノードに適用されます。その結果、古いノードへの参照(No で呼び出し)と新しいノード(Nn)への参照があります。

  2. No の子孫の ID は自動的に保持されます。もし変換された子孫ノードが変換後の出力ノードの子孫である場合、すでに同じ ID を持ちます。

  3. No:MPS の ID は、No が出力ノードの子孫であるかどうかを決定します。
    1. もしそうなら、すでに No を指している参照のターゲットを持っています。(これは「折り返し」の場合です - 変換の結果として、ノードは別のノードに「折り返されます」。)

    2. いいえの場合、Nn は No の ID を取得します。(これは、ノードの概念を変更した場合ですが、古いノードは新しいものと意味的に同じです。)

  4. 包含モデルでは、No は Nn に置き換えられます。

コンセプト交換

言語設計者が言語の概念を削除して、おそらく新しい概念に置き換えることにした場合、言語の概念定義をすぐに言語から削除しないでください。代わりに、この概念を最初に非推奨にし、ユーザーコードを非推奨の概念から移行するための移行スクリプトを提供する必要があります。

廃止予定のコンセプトは、廃止予定のコンセプトの後のバージョンでは完全に削除できます(ただし、削除する必要はありません)。廃止予定のコンセプトを参照している移行スクリプトも削除されました。

プロジェクト移行の定義

プロジェクトの移行は通常、言語開発者ではなく、MPS チームがモデルファイル形式の変更、モジュールの依存関係システム、その他のプロジェクト全体のことを記述するために使用します。

プロジェクトの移行はプロジェクト全体に対して実行されるため、プロジェクトの一部が変更された場合に MPS 開発者がどのように移行するのかを考えるのは MPS 開発者の責任です。たとえば、ユーザーは VCS から自分のプロジェクトを更新できます。この場合、プロジェクトが一度移行されたことを知るだけでは不十分な場合があります。更新されたモジュールはまだ移行する必要があるかもしれません。
MPS はプロジェクトの移行が実行される順序を保証するものではないため、基本的には相互に依存するプロジェクトの移行を書くことはできません。

それにもかかわらず、ユーザーは独自のプロジェクト移行を書くことができます。プロジェクト移行のための特別な言語はないため、それらは基本的に Java / BaseLanguage クラスとして書かれており、plugin.xml を通して提供されています。それで、すでに MPS プラグインを既に持っていて、その中にプロジェクト移行を書くとさらに仮定します。

プロジェクトの移行がソリューションで記述されている場合、このソリューションではソリューションのプロパティダイアログファセットタブIdeaPlugin を有効にし、アイデアプラグインタブでプラグイン ID を設定する必要があります。

新しいプロジェクト移行の追加

  • ProjectMigration インターフェースを実装する移行用のクラスを作成します。ほとんどの場合、BaseProjectMigration クラスから継承すると便利です。

  • 新しいマイグレーションに貢献する ApplicationComponent を作成してください。plugin.xml に登録することを忘れないでください

  • ProjectMigrationsRegistry.addProjectMigration() メソッドを使用して、作成した ApplicationComponent からすべてのプロジェクト移行に貢献します

プロジェクト移行からのデータの保存

プロジェクト移行では MigrationProperties プロジェクトコンポーネントを使用してデータを永続化できます。永続化されたデータはプロジェクトの .mps フォルダーに格納されるため、VCS を介してプロジェクトの開発者間で共有されます。

マルチブランチ

複数のブランチを使用するプロジェクトを移行することには、さらにいくつかの課題があります。詳細については分岐を伴う移行の使用のドキュメントをチェックしてください。

移行 Ant タスク

Ant スクリプトからプロジェクト内のすべてのマイグレーションを実行するための Ant タスクがあります。このタスクは、移行の自動テストやプロジェクトが移行されたかどうかの確認に使用できます。

このタスクでは MPS ホームパスを以下のように設定する必要があります

  1. mpshome タスク属性を定義しますか、

  2. mps_home 環境プロパティを定義しますか、

  3. mps.home 環境プロパティを定義する - これが推奨する方法です

ホームパスは、build.txt ファイルを含むフォルダーへのパスです。例: Mac OS ではこれは "/ Contents /" で終わります

リポジトリの内容は <repository> タグを使用して指定できます。

Screen Shot 2017 10 25 at 20 56 56

If a plugin is needed for a project to migrate, this can be specified in the <migrate> ant task: The corresponding plugin will be enabled, together with its dependencies.

MigratePlugins

サンプル

マイグレーションを定義する方法の具体例については、MPS にバンドルされているマイグレーションのサンプルプロジェクトを調べましょう。相互に相互接続された 2 つの単純な言語を移行するための移行スクリプトが表示されます。一方はデータを使用して 2 つの移行スクリプト間で移行されたノードに関する情報を渡し、もう一方はノード ID の操作に依存します。

ローカルヒストリービューでの移行による変更

移行はローカル履歴機能と連携します。

lh1

After running migrations, it's possible to review all the changes made to the project by each of the migration: Open the Local History view for the project's folder, a module or a model, select any two changes and press Ctrl + D to see the difference.

lh2
lh3

ローカルヒストリービューと差分ダイアログから、変更または変更のグループを元に戻すこともできます。

IntelliJ IDEA の移行アシスタント

IntelliJ IDEA プラグインは言語の移行も実行できます。MPS 自体と同様に、移行アシスタントは IDEA プロジェクトのモデルを、現在インストールされている使用言語のバージョンと一致するように更新します。

IDEA Migration1

非推奨コードの発見

非推奨は、ある言語の次のバージョンのいずれかで要素が削除されることを言語のユーザーに示すための推奨メカニズムです。MPS は、ユーザーが廃止予定のコードを排除するのに役立ついくつかの便利なファインダーを提供します。廃止予定の使用箇所の検索は廃止予定の要素のすべての用法を見つけることができます。検出された使用箇所のレポートでは、コード削除の予定バージョンごとにエントリがグループ化されています。これにより、その深刻度を認識し、排除することを優先することが容易になります。

Migx