Skip to content

MPS: Deps and Classpath

DomenikP edited this page Aug 2, 2016 · 2 revisions

Dependencies and Classpath in MPS

In this document, we describe the meaning and effect of different types of dependencies within MPS, including the effects on the applicable Java classpath. We describe both the expected state and all bugs deviating from the expectations, as of MPS version 3.1.4 (build #MPS-135.1441). We mention expected changes for version 3.2.

Table of Contents generated with DocToc

Overview

All content known to MPS is contained in its Modules Pool.

The Modules Pool is filled from Modules in the current Project and all Non-Project Sources.

MPS in general cares about dependencies between Modules. The dependencies on Models only constrain further the dependencies of the Modules.

There are two main types of Relations: Dependencies are needed for any reference to something in another Module. Used Languages are needed to use something defined in a language. We refer to Relations if we address both types.

Other types of dependencies on Modules include Java Stubs (in combination with Java Libraries), Java Source Stubs (in combination with Java Source Paths), Runtime Solutions and Accessory Models (only available for Languages), and Languages Engaged on Generation.

Build Models abstract Ant files to build and package Modules and IDEA Plugins. They contain a copy of the Relations defined in the Modules, and dependencies to other Build Models and IDEA Plugins.

Terminology and UI for Access

This section lists the main terms used in this document, including a brief description, their relation to other terms (also via document structure), and the place in the MPS IDE where to access it.

We capitalize all terms with specific meaning to MPS.

Settings

UI: File menu

All global and project settings.

IDE Settings (aka Global Settings)

Settings applied to all projects opened with this MPS installation. Stored in

Windows:
C:\Users\«username»\Application Settings\.MPS31
	
Linux:
~/MPS31

[AS]: is it ~/MPS31 or ~/.MPS31?

Mac:
~/Library/Application Support/MPS31
~/Library/Caches/MPS31
~/Library/Logs/MPS31
~/Library/Preferences/MPS31

Path Variables

UI: Entry in Settings Dialog

Variables pointing to some place in the file system. For any path selected in MPS contained within one of these Path Variables, the path is stored relative to the variable.

Known pre-defined Path Variables:

  • ${module} Containing Module
  • ${user.home} Current user home directory ???
  • ${language_descriptor} Directory containing the Language Module ?
  • ${solution_descriptor} Directory containing the Solution Module ?
  • ${project} Directory containing the Project
  • ${mps_home} Installation directory of this MPS installation

Do not point Path Variables to a sub-path of another Path Variable, as MPS will always apply the first (pre-defined before user-defined, user-defined in order of definition) one matching.

INVALID example:
Path Variable a --> /some/dir
Path Variable b --> /some/dir/below

Global Libraries

UI: Entry in Settings Dialog

Paths recursively scanned for Modules.

More info: Non-Project Sources, Path Variables, Project Libraries

(IDEA) Plugins

UI: Entry in Settings Dialog

A packaged set of contributions to the IntelliJ IDEA Platform, which MPS is based upon.

Contained in one of the following places:

  • ${mps_home}/plugins
  • «GlobalSettingsDir»/plugins

There are also other things called plugins, known as MPS Plugins, bearing no relationship to IDEA Plugins. However, MPS Plugins can be packaged into IDEA Plugins, just as any other content of MPS.

More info: Non-Project Sources, Global Settings, Path Variables, IDEA Plugin Module Settings, Plugin Disambiguation

Project Settings

UI: Entry in Settings Dialog

Settings applied to one project. Stored in ${project}/.mps/.

More info: Project, Path Variables

Project Libraries

UI: Entry in Settings Dialog

Paths recursively scanned for Modules.

More info: Non-Project Sources, Path Variables, Global Libraries

Modules Pool

UI: Second root entry in Logical View

All content known to MPS is contained in its Modules Pool. This Modules Pool is shared between all windows of the same MPS installation. In some future MPS version, every window should have its independent Modules Pool.

If a Module is contained more than once in the Modules Pool (eg. present both in the current Project and in a Global Library), the behavior is undefined (ie. will mess up badly, don't do this).

More info: Module

MPS Window

UI: If already open: Window menu; New: File menu, Open..., New Window

Every Project is contained in its own window.

More info: Project

Project

UI: First root entry in Logical View

Collection of Modules. A Module can be part of more than one Project. They can be added via "Project Paths" context menu entry of the Project.

Modules can be nested in folders. These folders are stored in the project, ie. the same Module can be in different folders inside different Projects. Folders are only for visual organization, they don't have any effect on storage location, generation or anything else.

More info: MPS Window, Module, Project Settings

Module

Unit of deployment and dependency for Something[^1] with defined relations to other Modules.

[^1]: "Something" denotes anything that can be contained in a Module.

More info: Modules Pool, Project

Types of Modules

Solution

UI: Entry below Project in Logical View; may be nested in folders

Standard container for Something.

More info: DevKit, Dependencies, Used Languages

Runtime Solution

Runtime Solutions are regular Solutions with additional semantic meaning: They are defined as Runtime Solution at the Runtime Language Settings. They contain Java code that should be available at run-time if the Language is used.

More info: Language

Language

UI: Entry below Project in Logical View; may be nested in folders

Container for defining a new Language within MPS. Also contains Generators, but this is mostly for historical reasons.

More info: Generator, DevKit, Runtime Solution, Runtime Language Settings, Used Languages Module Settings, Used Languages Model Settings, Aspects, Accessories Models, Utility Models, Plugin Disambiguation, Extends Language Scope, Implicit Generator Dependencies, Implicit Language Exports, Implicit Runtime Exports, Cyclic Dependencies, Used Languages

Generator

UI: Entry below Language in Logical View

Container for defining how to translate one kind of Nodes into another kind of Nodes.

More info: Language, Generator Priorities, Generator Models, Transient Models, Utility Models, Languages engaged on generation, Scope, Extends Generator Scope, Implicit Generator Dependencies, Implicit Runtime Exports, Used Languages, Executed Generators, Generated Relations

DevKit

UI: TODO

Collection of Solutions and Languages to be used in combination.

TODO: Extend

More info: Solution, Language

Module Settings

UI: Context menu of Module, Module Properties

Settings applicable to the Module.

Common Module Settings

UI: Tab in Module Properties dialog

Sources of Something. For all of them, we select or add the source type on the left-hand side and set its source on the right-hand side. The selected directory and all sub-directories are scanned for appropriate content.

  • (default)
    Model files edited in MPS

  • java_classes
    External contents of Java Classpath; contents of jar files are considered. MPS builds Java Model Stubs for all Java class files found in order to reference them inside MPS.

    To be able to compile code against these stubs, we need to add the jars to the Java Libraries as well.

  • obsolete
    As named. Don't use it.

  • java_source_stubs
    External Java source files. MPS should build Java Model Stubs from these, but does not do so currently (bug)

    In order to make MPS compile this code and compile other code against these stubs, we need to add the path to the Java Source Paths as well.

More info: Java Module Settings, Non-Project Sources, Path Variables

Dependencies Module Settings

UI: Tab in Module Properties dialog

Other Modules this Module has a reference to.

  • export
    Whether this Dependency should be re-exported.

    Available only for Dependencies in Default Scope.

  • Scope Scope of the Dependency.

    • Default
      Standard Scope. Only Option available for Solutions.

    • Extends
      Extends Scope. Only available for Languages and Generators.

      See below for a discussion of the meaning of Extends Scope.

More info: Export Flag, Model Dependencies, Dependencies

Used Languages Module Settings

UI: Tab in Module Properties dialog

Languages used in this Module.

See below for a discussion of the meaning of Language Used.

More info: Language, Model Used Langugaes

Java Module Settings

UI: Tab in Module Properties dialog

Settings concerning Java compilation of this Module.

  • Solution Kind
    Whether Java classes of Module (compilation results) should be available for ClassLoading. Such modules can contain MPS plugins in order to be notified about module ClassLoading initialization and de-initialization.

    If a Module is loaded automatically, it's scanned for MPS plugins to be started at their defined event.

    • None
      Module will not be loaded automatically.

    • Core plugin
      Module will be loaded automatically.

      The Module should not contain any references to the MPS editor, MPS UI, or MPS platform. Such module is intended to be compiled without MPS editor classes available in the classpath. On MPS startup time, editor classes can be unavailable within the classpath of such module.

      We currently don't know about any use case for this Solution Kind.

    • Editor plugin Module will be loaded automatically.

      The module should not contain any references to the (MPS UI ??), or MPS platform, as it's started before these are available.

      This Solution Kind should be selected if this plugin is required in Editor Tests.

    • Other plugin Module will be loaded automatically.

      The module should not add anything to MPS Editors, this might break Editor tests on the build server.

      Select this Solution Kind if we want this Module to be loaded automatically with no other restrictions.

  • Source Paths
    Paths containing Java source files to be compiled by MPS.

    The Path also needs to be added to java_source_stubs in order to be available as MPS models containing BaseLanguage concepts representing the content.

  • Libraries
    Paths containing Java classes and other resources available on the Java classpath during compilation.

    When we add something here, a dialog pops up asking about Model Roots. This dialog should add the appropriate entry to the Common Module Settings. However, this is currently broken (bug). Therefore, we need to create the java_classes entry on our own.

More info: Plugin Disambiguation

Facets Module Settings

UI: Tab in Module Properties dialog

Extensible list of facets available for a Module.

  • Idea Plugin
    Sets the parent Java classloader for this Module to the classloader of the IDEA Plugin referenced on the IDEA Plugin Module Settings.

  • Java
    Unused marker facet. Always checked.

  • tests
    Unused marker facet. Always checked.

More info: IDEA Plugin, Plugin Disambiguation

IDEA Plugin Module Settings

UI: Optional tab in Module Properties dialog

Settings for parent IDEA Plugin of this Module.

Needs to be activated on the Facets Module Settings.

  • Plugin ID
    ID of the parent IDEA plugin.

    parent means, this solution will be packaged as a part of the specified IDEA plugin. As a result the parent ClassLoader for the ModuleClassLoader of the corresponding solution will be a ClassLoader of specified IDEA plugin, so all classes packaged as a part of corresponding plugin will be available within ModuleClassLoader of this solution.

    On the development time one can run build script building complete IDEA plugin, deploy in into the current MPS instance using special Run configuration and continue developing a solution inside the current project. In this case actual solution content from the current project will be used. For more details see MPS Documentation, especially "Debugging the plugin" part.

More info: Plugin Disambiguation

Runtime Language Settings

UI: Tab in Module Properties dialog of Language

Settings for Solutions and Models with special meaning for the Language.

  • Runtime Solutions
    Solutions containing Java code that should be available at run-time if the Language is used.

  • Accessories Models
    Models containing Nodes that should be referable if the Language is used.

Refer to Implicit Exports of Runtime Language Settings for a discussion on the effects.

Generators priorities Generator Settings

UI: Tab in Module Properties dialog of Generator

The general mechanism of these settings is out of scope of this document. In our scope, we note that any other Generator referenced in these settings needs to be added to the Dependencies tab with Extends scope.

More info: Generator, Extends Scope for Generators

Model

UI: Entry below Module in Logical View; may be nested in folders

Container for model contents limiting dependencies to other Models within the boundaries of the containing Module.

Models can be nested in folders. Folders are only for visual organization, they don't have any effect on storage location, generation or any other aspect.

More info: Module

Types of Models

MPS knows several different types of Models. They differ in their semantics and sometimes presentation. They do not differ from a technical point of view.

Regular Models

UI: Entry below Solution in Logical View

Contains Root Nodes with no special semantics or presentation.

More info: Solution

Aspects

UI: Entry below Language in Logical View

Aspects are Models within a Language with a special meaning. They are recognized by their name.

More info: Language

Plugin Aspect

Although this Aspect adheres to the MPS Plugin Model naming convention, it should not be used as such. It should only be used to define MPS Extention Points (from Language jetbrains.mps.lang.extension).

More info: Plugin Disambiguation

Test Models

UI: Entry below Solution in a special folder named "tests" with special icon in Logical View

Model containing tests. Defined by @tests Stereotype.

More info: Test, Solution

Generator Models

UI: Entry with special icon below Generator in Logical View

Model containing Generator. Defined by @generator Stereotype.

Transient Models

UI: Last entry below Project in Logical View

Temporary Models produced during generation. Defined by @transient«someNumber» or @«someNumber» Stereotype.

More info: Generator

#####Accessories Model UI: Entry below Language in a special folder named "accessories" in Logical View or Entry below Solution in Logical View

Model specially selected by a Language. Nodes contained in these Models are implicitly available on the Java classpath and the Dependencies of any Model using this Language. A use case would be a default library of Concept instances to be available at any place the Language is used.

Accessories Models can be stored at two places: Either as Aspect of a Language (recommended), or as regular Model below a Solution. In both cases, the Model needs to added to Module Runtime Language Settings.

Utility Model

UI: Entry below Language in special folder named "util models" in Logical View

Contain code required in other parts of a Language or Generator, eg. if a Behavior method logic is too complex for inline implementation or a Generator needs to do complex model traversals. They should be created as regular Model within the Language.

More info: Language

Build Model

UI: Entry below Solution in Logical View

Contains Nodes from Build Language.

MPS Plugin Model

UI: Model within a Solution in Logical View

Contains MPS Plugins.

The model name needs to adhere to the naming convention «moduleName».plugin.

More info: Plugin Disambiguation

Model Stereotype

UI: Attached to the Model name, separated by "@"

A Model may have a Stereotype. To change, add, or remove a Stereotype, use the Rename Model Refactoring in the context menu of a Model.

Using custom Stereotypes has been reported to interfere with lots of MPS internals and thus is not advised to do.

MPS knows some predefined Stereotypes with special meaning:

Model Settings

UI: Context menu of Model, Model Properties

For both Dependencies and Used Languages, the settings on Models only restrict the settings from the containing Module.

Dependencies Model Settings

UI: Tab in Model Properties dialog

Other Models this Model contains references to.

More info: Module Dependencies, Dependencies

Used Languages Model Settings

UI: Tab in Model Properties dialog

Languages used in this Model.

See below for a discussion of the meaning of language used.

Any Used Language listed in a Model needs to be in the list of Used Languages of the containing Module.

Advanced Model Settings

UI: Tab in Model Properties dialog

Other settings for a Model.

  • Languages engaged on generation
    Generators contained in Languages listed here will be executed on this Model in any case.

More info: Executed Generators

Build Language

Abstracted Apache Ant files used to build and package MPS Modules outside the IDE.

Used in Build Models.

Can be executed within MPS via the "Run '«Build Model name»" context menu entry of the Build Model in Logical View.

Use Plugins

UI: Section within Build Model

Plugins to the Build Model language providing new entries for Build Models (eg. "generator options", "idea plugin"). These are not regular MPS Generators, but non-extendable plugins outputting Apache Ant XML.

Users may provide their own plugins.

Built-in plugins are:

  • java
    Support for pure Java

  • mps
    Support for MPS Modules

  • module-test
    Support for running tests including MPS Modules

More info: Plugin Disambiguation

Dependencies

UI: Section within Build Model

Scope import for all references to other Build Models.

Provides access to resulting artifacts of other Build Models.

IDEA Plugin Dependencies

UI: Section "project structure" in Build Model, subsection "idea plugin", subsection "dependencies"

Contents of IDEA plugin.xml depends tags.

This plugin will only be loaded if all dependencies listed here could be loaded before. The contents of dependencies are available for this IDEA plugin.

More info: IDEA Plugins, Plugin Disambiguation

Module Dependencies

UI: Section "mps group" in Build Model, subsection "solution"/"module", Inspector section "dependencies"

Copy of Relations of described Module.

More info: Module Dependencies, Module Used Languages

Runtime

Copy of Module Runtime Language Settings.

Jars

UI: Section "default layout" un Build Model

All jars included in any Java Module Settings need to be included somewhere in this section.

.java files (from Java Source Paths) need to be compiled as java sources inside corresponding build script and manually included into the resulting build layout: corresponding .class files should be jared, .java files should be places in corresponding location if they are referenced by java_source_stub model root.

MPS Plugins

MPS Plugins are automatically loaded according to the Solution Kind set in Java Module Settings.

MPS Plugins need to be contained in MPS Plugin Models.

More info: Plugin Disambiguation

StandalonePluginDescriptor

We need to add a StandalonePluginDescriptor (defined in Language jetbrains.mps.lang.plugin.standalone) as Root Node to any MPS Plugin Model using a Concept from Language jetbrains.mps.lang.plugin. Other concepts from Language jetbrains.mps.lang.plugin.standalone don't need a StandalonePluginDescriptor.

Plugin Disambiguation

The term "plugin" is used at various places throughout MPS. It describes very different things:

Non-Project Sources

Non-Project Sources are

These directories or Jar files are recursively scanned for *.mpl (Languages), *.msd(Solutions), and *.devkit (DevKit) files. If found, the corresponding content is added to the Modules Pool.

Java Classpath vs. Relations

Both the Java Classpath and the Relations of a Model are specified by the various settings on Models and Modules. However, these settings affect Classpath and Relations in a different way.

As a rule of thumb, the Classpath contains all Java classes reachable through any kind of relation, ie. the Classpath is populated generously. On the contrary, the Relations are populated reluctantly, ie. they need to be specified explicitly.

The Dependency Relations on Modules and Models are completely separated from the Used Language Relations on Modules and Models. Thus, no Dependency requires a Used Language or vice versa.

More info: Module Dependencies, Model Dependencies, Module Used Languages, Model Used Languages

Dependencies

By default, only Nodes present in the current Model can be referenced. Dependencies add other Models and Modules to be referenced from the current Model.

Models listed as Dependencies of Model A need to be contained within Modules listed in the Dependencies (including transitive entries) of the Module containing this Model. Example:

Module: ModuleA
	Model: ModelA.one
		Node: ModelA.one.alpha
	Model: ModelA.two
		Node: ModelA.two.alpha
	
Module: ModuleB [depends: ModuleA]
	Model: ModelB.one [depends: ModelA.one]
		Node: ModelB.one.alpha
			references: ModelA.one.alpha
			references: ModelA.two.alpha !!out of scope,
			                             !!as ModelB.one has
			                             !!no Dependency on 
			                             !!ModelA.two
Module: ModuleC
	Model: ModelB.one [depends: ModelA.one] !!out of scope,
	                                        !!as ModuleC has
	                                        !!no Dependency on
	                                        !!ModuleA

There is no way to mark a Model internal and hide it from outside access.

More info: Module Dependencies, Model Dependencies, Module Used Languages, Model Used Languages

Export Flag

Re-exports a Module Dependency to be used by Modules depending on this Module. Example:

Module: ModuleA
	Model: ModelA.one
		Node: ModelA.one.TheNode

Module: ModuleB [depends: ModuleA; export=true]

Module: ModuleC [depends: ModuleA]

Module: ModuleBeta [depends: ModuleB]
	Model: ModelBeta.one [depends: ModelA.one]
		Node: ModelBeta.one.TheOneNode
			references: ModelA.one.TheNode
	Model: ModelBeta.two
		Node: ModelBeta.two.TheTwoNode
			references: ModelA.one.TheNode !!out of scope,
			                               !!as ModelBeta.two has
			                               !!no Dependency on
			                               !!ModelA.one

Module: ModuleGamma [depends: ModuleC]
	Model: ModelGamma.one [depends: ModelA.one] !!out of scope,
	                                            !!as ModuleC
	                                            !!does not export
	                                            !!ModuleA

More info: Module Dependencies

Scope

Default Scope is available for all Module types (TODO: check for DevKits).

Extends Scope is a superset of Default Scope, ie. we never need to have both a Default Scope and an Extends Scope Dependency on another Module.

More info: Module Dependencies

Extends Scope for Languages

LanguageB (containing ConceptB) MUST extend LanguageA (containing ConceptA and ConceptInterfaceA), if and only if

  • ConceptB extends ConceptA or ConceptB implements ConceptInterfaceA
  • LanguageB defines a new Editor for ConceptA (but not if LanguageA only defines the Editor Hint)
  • LanguageB defines a new Editor Component for ConceptA
  • LanguageB uses an Editor Component defined in LanguageA
  • LanguageB defines a new Typesystem for ConceptA
  • LanguageB defines a Generator outputting ConceptA and LanguageA has a Runtime Solution

[AS]: Wrong (?): LanguageB uses an Editor Component defined in LanguageA

LanguageB SHOULD NOT extend LanguageA (but needs a Default Scope Dependency) if

  • LanguageB defines a new Intention for ConceptA
  • ConceptB defines a Child of Type ConceptA
  • ConceptB defines a Reference to Type ConceptA
  • ConceptB defines a behavior method Using Type ConceptA (eg. as return type, parameter type, or variable type)

LanguageB CANNOT define

  • a new Behavior for ConceptA
  • a new Constraint for ConceptA

To be precise, it is possible to remove all errors flagged on Behaviors and Constraints in LanguageB. However, they are not taken into account for ConceptA.

More info: Used Language, Module Dependencies, Language, Generator, Implicit Generator Dependencies, Runtime Solution

Extends Scope for Generators

GeneratorB (inside LanguageB, containing ConceptB) MUST extend GeneratorA (inside LanguageA, containing ConceptA), if and only if

  • GeneratorB defines a new Rule for ConceptA
  • GeneratorB extends a Switch from GeneratorA
  • GeneratorB defines a Generator Priority relative to GeneratorA

More info: Module Dependencies, Generator, Generator Priorities

Implicit Dependencies

Some Dependencies are added implicitly, ie. without being listed in the corresponding dialog.

Warning: Even if the Dependencies described below are established implicitly, they are not taken into account in every aspect of MPS. So if an error occurs, make sure we didn't rely on some implicit Dependency. If in doubt, make the Dependency explicit.

Implicit Dependencies inherited by a Generator from its Language

A Generator "inherits" some Dependencies from the Language it's defined in:

Except the case of generating a Concept of a Language that has a Runtime Solution (as described above), there is no requirement on the Language's Dependencies or Used Languages stemming from the Generator.

More info: Generator

Implicit Exports of Used Language and Language Structure Aspect

Both a Used Language and the Language Structure Aspect implicitly allow accessing the Language's Behavior methods. However, they not re-export the complete Behavior Aspect. For example, a BaseLanguage Class contained in the Behavior Aspect is not visible.

More info: Language

Implicit Exports of Runtime Language Settings

Runtime Solutions are

  • implicitly loaded into the Java classpath of any Module using this Language.
  • implicitly added to the Dependencies of the Generator contained in this Language.

Accessories Models are

  • implicitly loaded into the Dependencies of any Model using this Language.

    Accessory Models are not designed to keep any classes. This is "design-only" information. They should not affect Java class path anyhow.

TODO: [AS]: I believe they should be added to the dependencies of the generator module automatically. (if they are saved inside the same language they are visible for generator)

Neither Runtime Solutions nor Accessory Models constitute a Dependency from the Language to the referenced Solution or Model.

More info: Module Runtime Language Settings, Language, Generator

Cyclic Dependencies

Cyclic Dependencies between Modules should be avoided in general. They tend to render generation orders and other behavior non-deterministic. Languages are explicitly checked not to have a cyclic Extends Scope Dependency.

A special case are Runtime Solutions, Accessories Models, and Utility Models.

In contrast to Runtime Solutions, Utility Models are used while accessing a Behavior or running a Generator. Code within Runtime Solutions is used after the Generator ran from the generated code. Thus, a Runtime Solution SHOULD NOT use or reference the Language it's referred from. A Utility Model CAN use or reference the Language it's referred from.

Accessory Models CAN use or reference the Language they're referred from.

Used Languages

Model Used Languages need to be listed in the containing Module Used Languages.

There are no implicitly available Used Languages except described for Generators. Specifically, if LanguageB has an Extends Scope Dependency on LanguageA and ModuleC uses LanguageB, LanguageA is not a Used Language within ModuleC.

We MUST add LanguageA (containing ConceptA) to ModuleB's and contained ModelB's Used Languages if and only if

  • ModelB instantiates ConceptA within the IDE
  • ModelB executes Intentions from LanguageA
  • ModelB requires Typechecks from LanguageA
  • ModelB uses Editors from LanguageA by selecting an Editor Hint (but not if LanguageA only defines the Editor Hint)
  • ModuleB is a Generator and outputs instances of ConceptA

[AS]: not sure about: ModelB uses Editors from LanguageA by selecting an Editor Hint (but not if LanguageA only defines the Editor Hint)

More info: Language Extends Scope

Executed Generators

GeneratorA contained in LanguageA (containing ConceptA) will be executed for ModelS (contained in ModuleS) if and only if

For discussion, we establish a continued scenario:

(The Relations listed here are not complete in order to reduce clutter. The complete example is available.)

LanguageBase
	defines ConceptBase, ConceptBase2

SolutionBase
	contains ModelBase [using LanguageBase]
		contains NodeBase [instanceof ConceptBase]

SolutionBase doesn't change during generation, as LanguageBase does not define any Generators.

LanguageBaseGen
	contains GeneratorBase
		defines a rule for ConceptBase
		
SolutionBaseGen
	contains ModelBaseGen [using LanguageBase, LanguageBaseGen]
		contains NodeBase [instanceof ConceptBase]

SolutionBaseGen doesn't change during generation either, as it does not contain any instances from LanguageBaseGen, thus removing LanguageBaseGen from the list of applicable Generators, ending up with no Generators at all.

SolutionBaseGen2
	contains ModelBaseGen2 [using LanguageBase; engages LanguageBaseGen]
		contains NodeBase [instanceof ConceptBase]

SolutionBaseGen2 ends up with a transformed NodeBase, as Languages engaged in generation are never removed.

LanguageBaseGenExtends [extends LanguageBase]
	contains GeneratorBaseExtends
		defines a rule for ConceptBase2

SolutionBaseGenExtends
	contains ModelBaseGenExtends [using LanguageBase; engages LanguageBaseGenExtends]
		contains NodeBase [instanceof ConceptBase]
		contains NodeBase2 [instanceof ConceptBase2]

SolutionBaseGenExtends ends up with an unchanged NodeBase, but a transformed NodeBase2. GeneratorBaseExtends will be executed, because LanguageBaseGenExtends is listed in the Languages engaged in generation. However, the Dependencies of the Language are not considered for selecting the running Generators.

LanguageBaseGenExtends2 [extends LanguageBase]
	contains GeneratorBaseExtends2 [extends GeneratorBase]
		defines a rule for ConceptBase2

SolutionBaseGenExtends2
	contains ModelBaseGenExtends2 [using LanguageBase; engages LanguageBaseGenExtends2]
		contains NodeBase [instanceof ConceptBase]
		contains NodeBase2 [instanceof ConceptBase2]

In SolutionBaseGenExtends2 both NodeBase and NodeBase2 will be transformed, as LanguageBaseGenExtends2 is listed in the Languages engaged in generation and GeneratorBaseExtends2 extends GeneratorBase.

LanguageExtendsGen [extends LanguageBase]
	defines ConceptExtendsGen extending ConceptBase
	contains GeneratorExtendsGen
		defines a rule for ConceptExtendsGen

SolutionExtendsGen
	contains ModelExtendsGen [using LanguageBase, LanguageExtendsGen]
		contains NodeBase [instanceof ConceptBase]
		contains NodeExtendsGen [instanceof ConceptExtendsGen]

Only NodeExtendsGen will be transformed in SolutionExtendsGen, as the only active Generator is GeneratorExtendsGen (because we found an instance of ConceptExtendsGen contained in the same Language as the Generator), and the Generator does not extend any other applicable Generator.

LanguageExtendsGen2 [extends LanguageBase]
	defines ConceptExtendsGen2 extending ConceptBase
	contains GeneratorExtendsGen2 [extends GeneratorBase]
		defines a rule for ConceptExtendsGen2

SolutionExtendsGen2
	contains ModelExtendsGen2 [using LanguageBase, LanguageExtendsGen2]
		contains NodeBase [instanceof ConceptBase]
		contains NodeExtendsGen2 [instanceof ConceptExtendsGen2]

All nodes within SolutionExtendsGen2 will be transformed, as an instance of ConceptExtendsGen2 was found, and the generator GeneratorExtendsGen2 contained in the same language extends GeneratorBase.

Generated Relations

Relations on the output Model are defined only by the contents of the output Model that was created by the Generator. Thus,

  • all Languages providing the Concepts of generated instances are listed in the Used Languages
  • all Models referenced from the output Model are listed in the Dependencies

Additional Relations on anything else (source Module, source Model, Dependencies of the source Model, languages used in the source Model, Dependencies of applied Generators, languages used in applied Generators) are not added to the output Model. Implicit Dependencies apply as described.

Tests

Tests are regular or extended JUnit tests that can be executed within MPS or stand-alone.

Tests are contained in Test Models, defined by @tests Stereotype.

The Stereotype enables

As soon as we're using any concepts from language jetbrains.mps.lang.test, we need to have a TestInfo Root Node in the same model. The TestInfo node needs to refer to a Project to be used to execute the tests. This reference may not use a ${module}, ${language_descriptor}, ${solution_descriptor}, or ${project} built-in Path Variables. It needs to refer to a Project containing the test.

Recipes

This section lists all Relations required for a specific task.

If not specified otherwise, all Dependencies should be added

  • if no Dependency exists: With Default Scope and no Export flag
  • if a Dependency (no matter witch Scope and Export flag) exists: No change

MPS often creates the required Relations on Module level automatically if we add a Relation on Model level. However, this does not work in all cases, so double-check if the Module level Relation was created correctly if there are errors.

Use Java Type

ClassB inside ModelB inside ModuleB wants to create a variable of type ClassA inside ModelA inside ModuleA.

  • To ModelB, add Dependency to ModelA.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from ModuleB to ModuleA.

More info: Dependencies, Module Dependencies, Model Dependencies

Reuse (aka extend, reference) External Java Type

ClassB inside ModelB inside ModuleB extends ClassA inside ModelA inside ModuleA. ClassC inside ModelC inside ModuleC wants to use ClassB as simple as possible.

  • To ModuleB, add the Export Flag to the Dependency on ModuleA.
  • To ModelC, add Dependency to ModelB.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from ModuleC to ModuleB.

[AS]: Not sure we should add the Export Flag to the Dependency on ModuleA here.

More info: Dependencies, Export Flag, Module Dependencies, Model Dependencies

Create Concept Instance

Directly (aka root node) or indirectly (aka child node) within ModelB inside ModuleB, we want to create an instance of ConceptA inside LanguageA.

  • To ModelB, add Used Language to LanguageA.
    Even if MPS complains about the Used Language being "out of scope", click ok.
  • MPS will automatically add a Used Language from ModuleB to LanguageA.

More info: Used Languages, Module Used Languages, Model Used Languages

Use Intention

Make IntentionC defined in LanguageC for ConceptA inside LanguageA available in ModelB inside ModuleB.

  • To ModelB, add Used Language to LanguageC.
    Even if MPS complains about the Used Language being "out of scope", click ok.
  • MPS will automatically add a Used Language from ModuleB to LanguageC.

More info: Used Languages, Module Used Languages, Model Used Languages

Use Typesystem Rule

Make TypesystemRuleC defined in LanguageC for ConceptA inside LanguageA available in ModelB inside ModuleB.

  • To ModelB, add Used Language to LanguageC.
    Even if MPS complains about the Used Language being "out of scope", click ok.
  • MPS will automatically add a Used Language from ModuleB to LanguageC.

More info: Used Languages, Module Used Languages, Model Used Languages

Use alternate Editor with Hint

Make EditorC defined in LanguageC for ConceptA inside LanguageA using HintDdefined in LanguageD available in ModelB inside ModuleB.

  • To ModelB, add Used Language to LanguageC.
    Even if MPS complains about the Used Language being "out of scope", click ok.
  • MPS will automatically add a Used Language from ModuleB to LanguageC.

More info: Used Languages, Module Used Languages, Model Used Languages

Assure Generator is Executed for a Model

Assure GeneratorC defined in LanguageC for ConceptA inside LanguageA is executed for ModelB inside ModuleB.

  • To ModelB, add LanguageC to Languages engaged on generation.
  • To ModuleB, add Used Language to LanguageC.

More info: Executed Generators, Generators

Use node<SomeConcept> Type

ClassB inside ModelB inside ModuleB wants to create a variable of type node<ConceptA> inside LanguageA.

  • To ModelB, add Dependency to LanguageA.structure.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from ModuleB to LanguageA.

More info: Dependencies, Implicit Language Exports, Module Dependencies, Model Dependencies

Call Behavior Method

ClassB inside ModelB inside ModuleB wants to call Behavior method opA inside ConceptA inside LanguageA.

  • To ModelB, add Dependency to LanguageA.structure.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from ModuleB to LanguageA.

Note: We could also add a Dependency from ModelB to LanguageA.behavior. However, as we need to depend on LanguageA.structure anyways (to be able to access the type), the recipe presented above is preferred.

More info: Dependencies, Implicit Language Exports, Language Extends Scope, Module Dependencies, Model Dependencies

Use Concept as Child or Reference

ConceptB inside LanguageB wants to have a child or reference of type ConceptA inside LanguageA.

  • To LanguageB.structure, add Dependency to LanguageA.structure.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Used Language from LanguageB to LanguageA.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Extend Concept or Implement ConceptInterface

ConceptB inside LanguageB wants to extend / implement ConceptA / ConceptInterfaceA inside LanguageA.

  • To LanguageB.structure, add Dependency to LanguageA.structure.
    Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.
  • Make sure the Dependency from LanguageBto LanguageA has Extends Scope, either by setting it manually or by using the Intention on the error appearing on ConceptB.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Create Editor

LanguageB wants to define a new editor for EditorHintC defined in LanguageC for ConceptA inside LanguageA.

  • To LanguageB.editor, add Dependency to LanguageC.editor.
  • To LanguageB.editor, add Dependency to LanguageA.structure. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageC.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.
  • Make sure the Dependency from LanguageBto LanguageA has Extends Scope.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Create Editor Component

LanguageB wants to define a new Editor Component for ConceptA inside LanguageA.

  • To LanguageB.editor, add Dependency to LanguageA.structure. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.
  • Make sure the Dependency from LanguageBto LanguageA has Extends Scope.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Use Editor Component

LanguageB wants to use EditorComponentC defined in LanguageC for ConceptA inside LanguageA.

  • To LanguageB.editor, add Dependency to LanguageC.editor.
  • To LanguageB.editor, add Dependency to LanguageA.structure. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageC.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.
  • Make sure the Dependency from LanguageBto LanguageC has Extends Scope.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Create Typesystem Rule

LanguageB wants to define a new Typesystem Rule for ConceptA inside LanguageA.

  • To LanguageB.typesystem, add Dependency to LanguageA.structure. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.
  • Make sure the Dependency from LanguageBto LanguageA has Extends Scope.

Note: The overrides flag in Typesystem Rules is not related to Dependencies. This flag specifies if Typesystem Rules of Concepts extended by the applicable Concept are evaluated.

Example:

  • ConceptX extends ConceptY extends ConceptZ
  • ConceptZ defines Typesystem Rule ConceptZTypeRule
  • ConceptY defines Typesystem Rule ConceptYTypeRule1[override=true] and ConceptYTypeRule2[override=false]
  • ConceptX defines Typesystem Rule ConceptXTypeRule[override=false]

Then:

  • For ConceptZ, Typesystem Rule ConceptZTypeRule is evaluated.

  • For ConceptY, Typesystem Rules ConceptYTypeRule1 and ConceptYTypeRule2 are evaluated.
    ConceptZTypeRule is not evaluated, as at least one Rule for ConceptY defines [override=true].

  • For ConceptX, Typesystem Rules ConceptYTypeRule1, ConceptYTypeRule2 and
    ConceptXTypeRule are evaluated.
    ConceptYTypeRule1 and ConceptYTypeRule2 are included because no Rule for ConceptX defines [override=true].
    ConceptZTypeRuleis not evaluated because the search for Rules in extended Concepts stops at the first concept having at least one Rule defining [override=true].

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Create Intention

LanguageB wants to define a new Intention for ConceptA inside LanguageA.

  • To LanguageB.intentions, add Dependency to LanguageA.structure. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from LanguageB to LanguageA.

More info: Language Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies

Create Generator

Create Generator includes

  • Create new Root Mapping
  • Create new Reduction Rule
  • Create new Switch

GeneratorB inside LanguageB wants to create a Generator transforming ConceptA inside LanguageA into ConceptC inside LanguageC.

  • To GeneratorB.main@generator, add Dependency to LanguageA.structure.
  • To GeneratorB.main@generator, add Used Language to LanguageC. Even if MPS complains about the Dependency or Used Language being "out of scope", click ok.
  • Don't forget to sort your generator into the generation process by defining some Generator Priority.
  • MPS will automatically add a Dependency from GeneratorB to LanguageA.
  • MPS will automatically add a Used Language from GeneratorB to GeneratorA.
  • If LanguageC defines a Runtime Solution: To LanguageB, add Extends Scope Dependency to LanguageC.

More info: Language Extends Scope, Generator Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies, Module Used Languages, Model Used Languages

Extend Generator

Extend Generator includes

  • Assure another Generator is always executed if this Generator is executed
  • Create new Reduction Rule to be used in another Generator
  • Create a new Switch entry for a Switch in another Generator

GeneratorB inside LanguageB wants to extend GeneratorA inside LanguageA.
GeneratorA transforms ConceptC inside LanguageC into ConceptD inside LanguageD.
GeneratorB transforms ConceptE inside LanguageE into ConceptF inside LanguageF.

  • To GeneratorB.main@generator, add Dependency to GeneratorA.main@generator. Even if MPS complains about the Dependency being "out of scope", click ok.
  • MPS will automatically add a Dependency from GeneratorB to GeneratorA.
  • Make sure the Dependency from GeneratorBto GeneratorA has Extends Scope.

More info: Language Extends Scope, Generator Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies, Module Used Languages, Model Used Languages

Generate Java Class extending a Base Class

GeneratorB inside LanguageB wants to transform ConceptA inside LanguageA into a ConceptAJavaClass extending ConceptAJavaClassBase inside ModelC inside SolutionC.

  • To GeneratorB.main@generator, add Dependency to LanguageA.structure.
  • To GeneratorB.main@generator, add Dependency to ModelC.
  • To GeneratorB.main@generator, add Used Language to BaseLanguage. Even if MPS complains about the Dependency or Used Language being "out of scope", click ok.
  • Don't forget to sort your generator into the generation process by defining some Generator Priority.
  • MPS will automatically add a Dependency from GeneratorB to LanguageA.
  • MPS will automatically add a Dependency from GeneratorB to SolutionC.
  • MPS will automatically add a Used Language from GeneratorB to BaseLanguage.
  • To LanguageB, add Extends Scope Dependency to BaseLanguage (because BaseLanguage defines a Runtime Solution).
  • To LanguageB, add Runtime Solution to SolutionC.

More info: Runtime Solutions, Language Extends Scope, Generator Extends Scope, Used Language, Dependencies, Module Dependencies, Model Dependencies, Module Used Languages, Model Used Languages

Define Runtime Solution

LanguageB wants to use SolutionA as Runtime Solution.

  • To LanguageB, add Runtime Solution to SolutionA.

Note: We don't need any other Relation, specifically, no Dependency from LanguageB to SolutionA.

More info: Runtime Solutions, Dependencies

Define Accessories Model (aka make Concept Instances available everywhere a Langauge is Used)

BuiltInNodeA as Instance of BuiltInConcept inside LanguageA should be available to be referenced anywhere LanguageA is a Used Language.

  • Create AccessoryModel as Aspect in LanguageA
  • To AccessoryModel, add Used Language to LanguageA.
  • Create BuiltInNodeA inside AccessoryModel.
  • To LanguageA, add Accessory Model to AccessoryModel (if not present already).

Note: We don't need any other Relation, specifically, no Dependency from LanguageA to AccessorySolution.

More info: Accessories Model, Dependencies

Create Utility Model (aka create complex implementations for Behavior Methods or Generators)

complexBehavior() defined for ConceptA inside LanguageA needs ComplexBehaviorInternalJavaClass for its implementation.

or

GeneratorA inside LanguageA needs ComplexGeneratorInternalJavaClass for its execution (eg. for a complex condition or macro).

  • Create BehaviorUtilityModel / GeneratorUtilityModel as regular Model within LanguageA.
  • To BehaviorUtilityModel / GeneratorUtilityModel, add Used Language to BaseLanguage.
  • Create ComplexBehaviorInternalJavaClass / ComplexBehaviorInternalJavaClass within BehaviorUtilityModel / GeneratorUtilityModel.
  • To LanguageA.behavior / GeneratorA.main@generator add Dependency to BehaviorUtilityModel / GeneratorUtilityModel

More info: Utility Model, Dependencies

TODO: IDEA Plugins, MPS Plugins, External Classes, External Sources