This guide is based on observations/examinations of the EMV2 and SecMF projects.
-
Setup an OSATE Dev environment and then File >> New >> Project >> Xtext Project
-
Set fields
Project name
,Language name
,Language Extensions
as appropriate for your annex -
Click next. Check
Create Feature
,Create Update Site
-
This will generate the mwe2 and xtext files
-
Modify the xtext grammar to use OSATE artifacts similar to what's in org.sireum.aadl.gumbo/src/org/sireum/aadl/gumbo/Gumbo.xtext
-
Modify the mwe2 to resemble org.sireum.aadl.gumbo/src/org/sireum/aadl/gumbo/GenerateGumbo.mwe2
-
Add the missing
Require-Bundle
projects (as appropriate) to the manifest similar to org.sireum.aadl.gumbo/META-INF/MANIFEST.MF -
Launch the launcher. E.g for GUMBO, click the down arrow next to the play/run button in the toolbar and select Generate Gumbo (gumbo) Language Infrastructure
-
After generation you'll need to add missing required bundles to the other projects (e.g. ui)
-
Add 'naming' and 'parsing' packages and add files similar to what's seen in
-
Add the parsing package artifacts as extensions as seen in org.sireum.aadl.gumbo/plugin.xml
-
If you've made changes to the grammar then regenerate via the launcher by clicking the down arrow next to the play/run button in the toolbar and select Generate Gumbo (gumbo) Language
-
Rerun your regression tests after changes. E.g. right click the project org.sireum.aadl.gumbo.tests and choose
Run as 'JUnit Plug-in Test'
Scopes need to be added for rules like the following:
FeatureElement returns FeatureElement:
feature=[aadl2::NamedElement|ID];
The scopes are added via reflected calls to org.sireum.aadl.gumbo/src/org/sireum/aadl/gumbo/scoping/GumboScopeProvider.xtend
Assuming the above rule is processed while visiting an OSATE thread, the following will get the classifier for the thread, and add a scope for all its features. These will then be used when OSATE needs to resolve the referenced symbol.
def SimpleScope scope_FeatureElement_feature(FeatureElement context, EReference reference) {
val classifier = context.getContainerOfType(Classifier)
(classifier.getAllFeatures +
if (classifier instanceof ComponentImplementation) {
classifier.allInternalFeatures
} else {
emptyList
}).scopeFor
}
NOTE: OSATE will lazily resolve symbols. So for example, navigating to the container holding a 'FeatureElement' using the debugger starting at the top level GumboSubclause might show the container pointing to a PropertyImpl. However, the PropertyImpl will be replaced with, for example, a DataPortImpl when the '.feature' field is accessed via a visitor/formatter/serializer/etc.
Adding something like the following can help determine what the method names are that will be called via reflection:
override protected Predicate<Method> getPredicate(EObject context, EReference reference) {
val method = super.getPredicate(context, reference)
println(method)
return method
}