軽量 DSL
MPS コア言語を何年にもわたって進化させてきたため、IDE 統合のための言語記述 DSL の繰り返しパターンを認識するようになりました。概念的には、それらは、いくつかの高レベルのインターフェースを実装するプレーンクラスによって表現される高レベルの構造のように見え、動作しました。言語指向プログラミングの良い伝統では、これらのパターンを言語に反映し、プレーンな BaseLanguage クラスの上に薄い抽象化として再実装することにしました。このような抽象化を可能にするために、新しい軽量 DSL 言語が作成されました。
jetbrains.mps.baselanguage.lightweightdsl 言語を使用すると、内部 DSL を BaseLanguage クラスに埋め込むことができます。一般に、内部 DSL は、本格的な外部 DSL よりも開発が簡単で高速であり、通常、ホスト言語の構文を再利用し、周囲の非 DSL コードと緊密に統合されます。同様に、MPS 軽量 DSL は、単一のノードを定義した後 BaseLanguage ClassConcept またはそのサブコンセプトにノードを織ることによって作成することができます。
MPS 自体がいくつかの場所でこのメカニズムを利用しています。
単なる BaseLanguage クラスである MigrationScript の概念は、いくつかの追加のプロパティ、メンバー、カスタムメンバーを追加する MigrationDSLDescriptor によって拡張されます。
使用箇所の検索
インテンション
カスタム言語の側面
軽量 DSL をプレーンな BaseLanguage クラスに織り込むことも、ClassConcept を拡張する独自の概念に織り込むこともできます。
普通のクラスを拡張する
軽量 DSL 言語の背後にある中心的な考え方は、DSL 設計者が、オプションのメソッドとプロパティ、制約に依存する型、オプションのメソッドパラメーター、カスタムクラスメンバーなどの制約を持つインターフェースを定義できるようにすることです。 DSLDescriptor の 概念は、クラスの実装時に適用する必要がある制約付きインターフェースを体系化するノードを表します。例: 以下の DSLDescriptor インスタンスは calculateFoo() 方法とカスタム BuilderMember ノードだけでなく、クラスに numberOfFrames プロパティを織ります。
特定の DSLDescriptor をクラスで有効にするには、インテンションを介して行われる DSLAnnotation でアノテーションを付ける必要があります。
アノテーションが追加されるとすぐに、DSLDescriptor で定義されている必要な要素、またはプレースホルダーが指定されている要素がクラスに追加されます。必要な要素を削除すると、クラスにエラーが表示されます。
インテンションを使用して、必要な要素とプレースホルダーを 1 つのステップで追加し直すことができます。
標準のメソッドの実装アクション Ctrl+I は、必要なメソッドでも機能します。
DSLDescriptor を定義する
DSLDescriptor がクラスに追加できる要素には次の 4 つのタイプがあります。
プロパティ
メソッド
カスタムメンバー
イニシャライザー
これらはそれぞれ必須であり、欠落しているメンバーを表すようにプレースホルダーを定義でき、カスタムメンバーを複数としてマークして、この種類の複数のノードがクラスのメンバーになることができることを示すことができます。
Properties
プロパティには名前があり、string、int、または boolean 型にすることができます。プロパティは、weaved クラスの本格的なメンバーになり、このまたは他の DSLDescriptor を介して織り込まれたメンバーを含む他のメンバーからアクセスできます。
メソッド
メソッドは、軽量 DSL のユーザーがコードを挿入できるようにするための非常に便利な方法を提供します。DSLDescriptor は、拡張クラスが実装できる、または実装する必要のあるメソッドのメソッドシグネチャーを指定します。通常のメソッドとは異なり、戻り値の型とこれらのウィーブされたメソッドのパラメーターの型は、ホスト(拡張)クラスでの実際の使用箇所に基づいて決定できます。
依存型
依存型は、メソッドの戻り型またはパラメーター型に指定されている場合、特定のクラスのメソッドの実際の型を計算する方法を指定します。
条件付きメソッドパラメーター
メソッドは、条件付きとしてマークされたいくつかのパラメーターを持つことができるため、それらは提供された条件が満たされたときにだけユーザコードで見えるようになります。パラメーターを条件付きとしてマークするには、対応するインテンションを使用できます。
実際の条件はインスペクターで指定されています。
カスタムメンバー
プロパティもメソッドも必要な抽象化レベルを提供しない場合は、カスタムメンバーを使用して、わずかな追加作業で任意の概念を織り込むことができます。
CustomMemberDescriptor は、新しいメンバーとしてクラスに組み込まれる概念(この場合は BuilderMember)を指します。これを可能にするには、コンセプトは MemberInstance および ClassifierMember コンセプトインターフェースを実装し、オーバーライドする getDeclaration() メソッドから CustomMemberDescriptor を指す必要があります。
指定された概念のノード(または CustomMemberDescriptor が複数として定義されている場合は複数のノード)をホストクラスのメンバーとしてインスタンス化し、その中で編集できるようになりました。
イニシャライザー
イニシャライザー関数は、ホストクラスが作成されるか、DSLAnnotation でアノテーションが付けられるとすぐに、プログラムでホストクラスを拡張する機会を得ます。初期化子が呼び出されたときにノード(ホストクラス)自体がモデルに追加されていない可能性があるため、ノードと同様にモデルパラメーターが提供されます。smodel 言語をインポートすると、クラスとモデルを操作できます。通常、初期化子は、必要に応じて、インポートと使用言語を設定するか、織り込まれたメンバーのデフォルト値と実装を提供します。
カスタム ClassConcept サブコンセプトの強化
BaseLanguage クラスを直接拡張するのではなく、 ClassConcept クラスの特定のサブコンセプトを拡張する場合は、いくつかの詳細があります。これにより、外部 DSL と内部 DSL の利点を組み合わせることができます。目的の DSL でカスタマイズされた編集エクスペリエンス、専用のジェネレーター、特定の型システムルールが必要になった場合は、通常、プレーンな BaseLanguage クラスを使用する代わりに、 ClassConcept サブコンセプトを作成します。したがって、 ClassConcept のサブコンセプトを作成し、 AutoInitDSLClass を実装するようにします。
概念のノードが作成されるたび、DSL の中に織り込ま適切に DSLDescriptor 秒で定義された初期化子を呼び出すことによって初期化されますことを実装 AutoInitDSLClass を保証します。
AutoInitDSLClass インターフェースはまた、織りに特定 DSLDescriptor インスタンスを返す必要があり getDescriptor() メソッドをオーバーライドする実装概念を義務付け。
サンプル
Lightweight DSL の基本的な使い方を説明するサンプルは、MPS ディストリビューションにバンドルされている lightweightDSL サンプルプロジェクトにあります。
関連ページ:
カスタムアスペクト
構造、エディター、型システムなどの通常の言語アスペクトと並んで、言語生産者はカスタム言語アスペクト(たとえば、インタープリター、代替型システムなど)を作成し、言語ランタイムに生成してから実行することができます。コードからこれらの生成されたアスペクトを使用してください。カスタムアスペクトとは何ですか? :MPS の言語定義は、構造、エディター、型システム、ジェネレーター (1) などの側面のコレクションと考えることができます。言語の各アスペクトは、個別のアスペクトモデルで定義されます。例: 言語 L...
ドキュメントファセット
導入:ドキュメント言語を使用すると、言語構造をドキュメント化できます。ドキュメントは、情報ポップアップダイアログ (別名トゥーチップ) と専用のドキュメントツールウィンドウを通じて、言語の構造モデルのユーザーに即座に提供されます。さらに、ドキュメントは HTML javadoc スタイルのドキュメントとして生成することもできます。始め方:言語のドキュメントを有効にするのは非常に簡単です: 言語のモジュールプロパティに移動します。ファセットタブでドキュメントファセットを有効にします。生成されたド...