MPS 2025.1 ヘルプ

ジェネレーターユーザガイド Demo2

Generator ユーザーガイドデモ 2

このデモでは、Java Swing アプリケーションを再度生成しますが、前のデモ 1 とは異なり、今回は入力モデルごとに 1 つの Java アプリケーションになります(デモ 1 では、入力 XML ドキュメントごとに個別の Java アプリケーションを生成しました)。デモ 2 が作成する単一の Java アプリケーションには、入力モデルのすべての XML ドキュメントに記載されているすべてのコンポーネントが含まれます。

新しい言語

最初に少し技術的な設定を行う必要があります。

  • 新しい言語を作成する: 'generator_demo.demoLang2'

  • 言語プロパティダイアログで、'jetbrains.mps.sampleXML' および 'jetbrains.mps.baseLanguage' への拡張依存関係を追加します。

  • この言語の新しいジェネレーターが自動的に作成されていない場合は、作成します。詳細については、ジェネレーターユーザガイド Demo1 を参照してください。

生成するコードはデモ 1 のコードとほぼ同じであるため、demoLang1 ジェネレーターからアプリケーションクラステンプレートをコピーします。

  • demoLang1 のモデル「main @ generator」に移動します

  • プロジェクトツリーで「map_Document」テンプレートを選択し、クリップボードにコピーします

  • demoLang2 のモデル 'main @ generator' に戻り(ツリーでこのモデルを選択)、クリップボードから貼り付けます

  • 同様に、テンプレートスイッチ 'switch_JComponentByElementName' を demoLang1 から demoLang2 ジェネレーターモデルにコピーします

条件付きルートルール

MPS でのコード生成のプロセスは、一連のモデルからモデルへの変換と見なすことができます。ある言語の AST は、徐々に別の言語の概念で表現された AST に変換されます。各ステップで、ある言語の個々の概念が別の言語の概念に翻訳(縮小)されます。条件付きルートルールは、何もないところから新しいノードを作成するという点で、やや特殊です。入力モデルに元のノードがなくても、このルールで参照されているテンプレートを使用して、出力モデルに新しいルートノードを生成します。

  • demoLang2 ジェネレーターに移動し、エディターでマッピング構成 'main' を開きます

  • 新しい条件付きルートルールを追加する (キャレットが条件付きルートルールセクション内にあるときに、Insert または Enter を押します。)

  • 結果のクラスを生成するためにこのテンプレートが使用されるように、「map_Document」テンプレートへの参照を作成します

gdb2.png
  • 'map_Document' テンプレートを開き(エディターの参照で Control + <左クリック> または Cmd + <左クリック>)、変更されたコンテキストで機能するように少し調整します。

gdb3.png
  • テンプレートのヘッダーから「Document 」という記述を削除します。キャレットが「Document」という単語の上にあるときに Del キーを押します。(このテンプレートを条件付きルートルールで使用しています。これにより、テンプレートの入力としてドキュメントが渡されなくなりました。)

  • クラス名から property-macro を削除します。単一のクラスのみを取得するため、その名前をハードコードできます

  • 生成されたクラスの名前を「DemoApp」に変更します

  • SWITCH マクロのインスペクターを開き、Control + Space を 押して template_switch への参照を解決します。

ループマクロ

「DemoApp」テンプレートの SWITCH マクロは、入力に XML ドキュメントを必要とします。これは、デモ 1 でこのように実装したためです。次に、ドキュメントのルート要素を抽出し、それにテンプレートスイッチを適用します。ただし、入力モデルには複数のドキュメントが存在する可能性があります (実際、デモアプリにはボタンとラベルの 2 つがあります)。そのため、それらすべてを順番に徐々に処理し、適切な「container.add(null) 」を生成する必要があります。; " これらの各ドキュメントのステートメント。

SWITCH マクロに単一のドキュメントノードを提供するために、' container.add(..); をラップします。'LOOP マクロ内のステートメント:

  • テンプレートコードで、ステートメント 'container.add($SWITCH$[null]); を選択します。 ' (ステートメント内にキャレットを配置した状態で、Ctrl/Cmd+W を使用してブロック選択を展開します。)

  • Ctrl-Shift + M を押して、ノードマクロを追加します

  • 自動補完メニューから $LOOP$ を選択します (Ctrl+Space)

  • 以下のように、LOOP のマップノード関数にコードを入力します

gdb4.png

マップされたノード関数は、入力モデル内のすべてのドキュメントを検索し、これらのドキュメントシーケンスをジェネレーターに返します (return ステートメントは BaseLanguage では省略できます)。

次に、ジェネレーターはこのシーケンスを繰り返し、'container.add(..);' を作成します。各文書の文と徐々に SWITCH マクロへの入力ノードとして各文書を渡します。

以上です。最後のステップは、通常どおり、Shift-F9押してジェネレーターを作成することです。

最初のテストの実行

demoLang2 ジェネレーターをテストするには、デモ 1 とまったく同じ入力が必要ですが、生成時に異なる言語を「使用」する必要があります。

  • 「test_models」ソリューションの「test1」モデルに移動します (プロジェクトツリーで選択します)

  • ポップアップメニューでクローンモデルを選択します

  • 新しいモデル名を入力してください: 'generator_demo.test2'

  • 世代に関わる言語」セクションの「test2」モデルのプロパティダイアログで:

    • 「generator_demo.L1」言語を削除

    • 「generator_demo.L2」言語を追加

「test2」モデルを生成し、生成されたソースをプレビューします。

ルートルールを破棄

生成された出力には、Button.xml と Label.xml の 2 つの「生成された」XML ファイルも含まれていることに注意してください。MPS は、前のデモ 1 ではこれらの XML ファイルを生成しませんでした。このデモではなぜ生成しますか?

デモ 1 では、ルートマッピングルールを使用して入力ドキュメントから出力クラスへの明示的なマッピングを定義したため、入力は消費され、xml ファイルは生成されませんでした。

デモ 2 では、入力ドキュメント を出力ルートに明示的にマップしないため、テキスト生成フェーズまでモデルに残り、テキスト生成フェーズで xml ファイルに変換されます。

ドキュメントが出力モデルにコピーされないようにするために、ルートルールを破棄を使用します。

  • demoLang2 ジェネレーターに戻り、エディターでマッピング構成 'main' を開きます

  • 新しいルート破棄ルールを追加します - キャレットがルート破棄セクションにあるときに挿入を押します

  • ルールの適用の概念として「ドキュメント」を選択します

gdb5.png

プロジェクトをリビルドした後、出力で xml ファイルを取得しなくなります。