Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "Papyrus-RT/Developer/Design/0.8/Codegen Extension"
m |
|||
Line 29: | Line 29: | ||
* <code>org.eclipse.papyrusrt.codegen.lang.cpp</code>: the meta-model of the target C++ subset. | * <code>org.eclipse.papyrusrt.codegen.lang.cpp</code>: the meta-model of the target C++ subset. | ||
# If not already open, open the new project's META-INF/MANIFEST.MF file. | # If not already open, open the new project's META-INF/MANIFEST.MF file. | ||
− | #:[[File:genext-1-new-plugin-proj.png]] | + | #:[[File:genext-1-new-plugin-proj-v2.png]] |
# Click on the "Dependencies" tab. | # Click on the "Dependencies" tab. | ||
− | #:[[File:genext-2-dep-tab.png]] | + | #:[[File:genext-2-dep-tab-v2.png]] |
# Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.cpp</code>, select it and click [OK]. | # Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.cpp</code>, select it and click [OK]. | ||
− | #:[[File:genext-3-add-dep.png]] | + | #:[[File:genext-3-add-dep-v2.png]] |
# Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.xtumlrt.common.model</code>, select it and click [OK]. | # Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.xtumlrt.common.model</code>, select it and click [OK]. | ||
# Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.lang.cpp</code>, select it and click [OK]. | # Click the [Add...] button, search for <code>org.eclipse.papyrusrt.codegen.lang.cpp</code>, select it and click [OK]. | ||
− | #:[[File:genext-4-deps-added.png]] | + | #:[[File:genext-4-deps-added-v2.png]] |
# Save. | # Save. | ||
'''Note''': you may add other dependencies that you need. | '''Note''': you may add other dependencies that you need. | ||
Line 42: | Line 42: | ||
In the Project Explorer navigate to the plug-in's source folder (usually called "src") and create a new class there. The new class must be a subclass of <code>org.eclipse.papyrusrt.codegen.cpp.AbstractCppGenerator</code>. | In the Project Explorer navigate to the plug-in's source folder (usually called "src") and create a new class there. The new class must be a subclass of <code>org.eclipse.papyrusrt.codegen.cpp.AbstractCppGenerator</code>. | ||
{{Note|You may extend the built-in generators found in <code>org.eclipse.papyrusrt.codegen.cpp.internal</code>, but beware that they are not part of the official API and their interface is subject to change. These generators are: | {{Note|You may extend the built-in generators found in <code>org.eclipse.papyrusrt.codegen.cpp.internal</code>, but beware that they are not part of the official API and their interface is subject to change. These generators are: | ||
+ | * <code>ArtifactGenerator</code> | ||
* <code>BasicClassGenerator</code> | * <code>BasicClassGenerator</code> | ||
+ | * <code>EnumGenerator</code> | ||
* <code>CapsuleGenerator</code> | * <code>CapsuleGenerator</code> | ||
* <code>SerializableClassGenerator</code> | * <code>SerializableClassGenerator</code> | ||
Line 151: | Line 153: | ||
# Open the plugin's META-INF/MANIFEST.MF file, and go to the "Extensions" tab: | # Open the plugin's META-INF/MANIFEST.MF file, and go to the "Extensions" tab: | ||
− | #:[[File:genext-5-ext-tab.png]] | + | #:[[File:genext-5-ext-tab-v2.png]] |
# Click [Add...] and search for the <code>generator</code> extension point from the <code>org.eclipse.papyrusrt.codegen.cpp</code> plugin: | # Click [Add...] and search for the <code>generator</code> extension point from the <code>org.eclipse.papyrusrt.codegen.cpp</code> plugin: | ||
− | #:[[File:genext-6-find-generator.png]] | + | #:[[File:genext-6-find-generator-v2.png]] |
#:After clicking [OK] it looks like this: | #:After clicking [OK] it looks like this: | ||
− | #:[[File:genext-7-generator-found.png]] | + | #:[[File:genext-7-generator-found-v2.png]] |
− | # Set the <code>type</code> to <code>ClassGenerator</code> | + | # Set the <code>type</code> to <code>ClassGenerator</code>, the <code>class</code> to <code>myproject.mygen.MyClassGenerator$Factory</code>, and the <code>priority</code> to <code>High</code> |
− | #:[[File:genext-8-set-type-class.png]] | + | #:[[File:genext-8-set-type-class-v2.png]] |
And it's done! When you execute PapyrusRT with your custom plugin, this generator will override the default generator for basic classes. | And it's done! When you execute PapyrusRT with your custom plugin, this generator will override the default generator for basic classes. | ||
Line 163: | Line 165: | ||
For other generator types, the <code>type</code> of the extension should be set accordingly. The types supported are the following: | For other generator types, the <code>type</code> of the extension should be set accordingly. The types supported are the following: | ||
+ | * <code>ArtifactGenerator</code> (for subclasses of <code>ArtifactGenerator</code>) | ||
+ | * <code>BehaviourGenerator</code> (for subclasses of <code>BehaviourGenerator</code> (not yet implemented)) | ||
* <code>ClassGenerator</code> (for subclasses of <code>BasicClassGenerator</code>) | * <code>ClassGenerator</code> (for subclasses of <code>BasicClassGenerator</code>) | ||
* <code>CapsuleGenerator</code> (for subclasses of <code>CapsuleGenerator</code>) | * <code>CapsuleGenerator</code> (for subclasses of <code>CapsuleGenerator</code>) | ||
+ | * <code>EnumGenerator</code> (for subclasses of <code>EnumGenerator</code>) | ||
* <code>ProtocolGenerator</code> (for subclasses of <code>ProtocolGenerator</code>) | * <code>ProtocolGenerator</code> (for subclasses of <code>ProtocolGenerator</code>) | ||
+ | * <code>SerializableClassGenerator</code> (for subclasses of <code>SerializableClassGenerator</code>) | ||
* <code>StateMachineGenerator</code> (for subclasses of <code>StateMachineGenerator</code>) | * <code>StateMachineGenerator</code> (for subclasses of <code>StateMachineGenerator</code>) | ||
* <code>StructureGenerator</code> (for subclasses of <code>CompositionGenerator</code>) | * <code>StructureGenerator</code> (for subclasses of <code>CompositionGenerator</code>) |
Revision as of 18:27, 25 February 2016
Contents
Extending the code generator
The PapyrusRT code generator can be extended using the Eclipse plugin extension mechanism. The org.eclipse.papyrusrt.codegen.cpp
plugin defines an extension point called generator
to provide generator classes. A plugin for a custom generator needs to define an extension linked to this generator
extension point, and specify a custom generator class implementing this extension. The custom generator must be a subclass of AbstractCppGenerator
, defined in the same org.eclipse.papyrusrt.codegen.cpp
plugin.
In the definition of the extension, the type must be one of the following:
-
ClassGenerator
-
CapsuleGenerator
-
ProtocolGenerator
-
StateMachineGenerator
-
StructureGenerator
The class associated to the extension must implement the AbstractCppGenerator.Factory
interface, which is used by the generator to create instances of each specific generator.
The following example describes the usual steps required to create a custom generator and provide the extension.
This assumes that you have installed a PapyrusRT development environment as described in Mars Development Environment.
Create a Plug-in Project
- Go to File → New → Other... → Plug-in Project
- Enter the name of the project and all relevant fields. In this example we will use the name "myproject.mygen"
Configure the new plug-in dependencies
The new plug-in needs at least the following three plug-ins:
-
org.eclipse.papyrusrt.codegen.cpp
: the code generator which provides the base generators and extension point. -
org.eclipse.papyrusrt.codegen.xtumlrt.common.model
: the meta-model of the intermediate representation (xtUMLrt) -
org.eclipse.papyrusrt.codegen.lang.cpp
: the meta-model of the target C++ subset.
- If not already open, open the new project's META-INF/MANIFEST.MF file.
- Click on the "Dependencies" tab.
- Click the [Add...] button, search for
org.eclipse.papyrusrt.codegen.cpp
, select it and click [OK]. - Click the [Add...] button, search for
org.eclipse.papyrusrt.codegen.xtumlrt.common.model
, select it and click [OK]. - Click the [Add...] button, search for
org.eclipse.papyrusrt.codegen.lang.cpp
, select it and click [OK]. - Save.
Note: you may add other dependencies that you need.
Create a generator class
In the Project Explorer navigate to the plug-in's source folder (usually called "src") and create a new class there. The new class must be a subclass of org.eclipse.papyrusrt.codegen.cpp.AbstractCppGenerator
.
In this example we are going to extend the BasicClassGenerator
. After creating the class, its source code should look like this:
package myproject.mygen; import org.eclipse.papyrusrt.codegen.cpp.CppCodePattern; import org.eclipse.papyrusrt.codegen.cpp.internal.BasicClassGenerator; import org.eclipse.papyrusrt.xtumlrt.common.Type; public class MyClassGenerator extends BasicClassGenerator { public MyClassGenerator(CppCodePattern cpp, Type element) { super(cpp, element); // TODO Auto-generated constructor stub } }
The generator needs to provide a factory class which the PapyrusRT code generator manager (GeneratorManager
and EclipseGeneratorManager
) will use to obtain instances of your generator. This factory must implement the AbstractCppGenerator.Factory
interface. The most natural location for this is within your own generator class:
package myproject.mygen; import org.eclipse.papyrusrt.codegen.cpp.AbstractCppGenerator; import org.eclipse.papyrusrt.codegen.cpp.CppCodePattern; import org.eclipse.papyrusrt.codegen.cpp.internal.BasicClassGenerator; import org.eclipse.papyrusrt.xtumlrt.common.StructuredType; import org.eclipse.papyrusrt.xtumlrt.common.Package; public class MyClassGenerator extends BasicClassGenerator { private StructuredType element; private Package context; public MyClassGenerator( CppCodePattern cpp, StructuredType element, Package context ) { super(cpp, element); this.element = element; this.context = context; } public static class Factory implements AbstractCppGenerator.Factory<StructuredType, Package> { @Override public AbstractCppGenerator create( CppCodePattern cpp, StructuredType element, Package context ) { return new MyClassGenerator( cpp, element, context ); } } @Override public boolean generate() { // The actual generation goes here. // This method uses this.element and may use this.context return false; } }
Several things to notice in this example. First, we added two fields, element
and context
of types StructuredType
and Package
.
The element
field will be assigned the source element from the intermediate representation (an xtUMLrt element). This is, the element for which we are generating code. In our example, the element will be a class, and classes are represented in xtUMLrt by StructuredType
objects.
The context
field will be assigned the appropriate context element. This depends on the particular element that we are interested in. For classes, the context is the (xtUMLrt) Package
in which the StructuredType
is defined. A custom code generator may use this or may choose to ignore it.
We also updated the constructor to assign the element
and context
fields.
We added an inner static class called Factory
, which implements the AbstractCppGenerator.Factory
interface. This class provides a factory method to create instances of the custom generator when the full generator is executed. The interface is a template, parametrized by the types of the element
and context
. The factory method is called create
, returns an instance of the custom generator, and expects three arguments:
-
CppCodePattern cpp
: the core interface to the C++ meta-model and the specific code patterns produced in that meta-model (see Papyrus-RT/Developer Guide/Codegen Details) -
StructuredType element
: the (xtUMLrt) element to be generated -
Package context
: the (xtUMLrt) context of the element
In our case, this factory method is quite simple. It just invokes the constructor.
Finally, we override the generate
method from AbstractCppGenerator
to provide our own logic. This method returns a boolean indicating the success or failure of the generation.
When extending the built-in generators, we can override other methods.
The generate
will use the cpp
instance, as well as any classes in the org.eclipse.papyrusrt.codegen.lang.cpp
package to create C++ elements. There is no need to explicitly generate text here. The cpp
instance will record all C++ elements created and after generate
has finished, the main generator will invoke cpp.write
to transform the C++ model into source C++ text files.
For example, we can make our custom generator create a C++ class with a single method called run
as follows:
@Override public boolean generate() { CppClass cls = cpp.getWritableCppClass( CppCodePattern.Output.BasicClass, element ); MemberFunction function = new MemberFunction( PrimitiveType.VOID, "run" ); function.add( new UserCode( "for (int i = 0; i < 100; i++) ;" )); cls.addMember( Visibility.PUBLIC, function ); return true; }
The first line creates a C++ class for the given element. The second creates a member function called "run", with return type "void" and no parameters. The third line adds a statement. In this case it is some fixed user code. The fourth line adds this function to the class created in the first line, with public visibility.
Defining the generator extension
Finally, we need to hook up our generator to the generator
extension point provided by org.eclipse.papyrusrt.codegen.cpp
.
- Open the plugin's META-INF/MANIFEST.MF file, and go to the "Extensions" tab:
- Click [Add...] and search for the
generator
extension point from theorg.eclipse.papyrusrt.codegen.cpp
plugin: - Set the
type
toClassGenerator
, theclass
tomyproject.mygen.MyClassGenerator$Factory
, and thepriority
toHigh
And it's done! When you execute PapyrusRT with your custom plugin, this generator will override the default generator for basic classes.
For other generator types, the type
of the extension should be set accordingly. The types supported are the following:
-
ArtifactGenerator
(for subclasses ofArtifactGenerator
) -
BehaviourGenerator
(for subclasses ofBehaviourGenerator
(not yet implemented)) -
ClassGenerator
(for subclasses ofBasicClassGenerator
) -
CapsuleGenerator
(for subclasses ofCapsuleGenerator
) -
EnumGenerator
(for subclasses ofEnumGenerator
) -
ProtocolGenerator
(for subclasses ofProtocolGenerator
) -
SerializableClassGenerator
(for subclasses ofSerializableClassGenerator
) -
StateMachineGenerator
(for subclasses ofStateMachineGenerator
) -
StructureGenerator
(for subclasses ofCompositionGenerator
)