Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorHenrik Rentz-Reichert2018-04-30 12:37:58 -0400
committerHenrik Rentz-Reichert2018-06-08 07:53:10 -0400
commit29873f1151bb915cf3044f21deca9c756d3f95e0 (patch)
treedfb65025ce0f630a188baf879d0fd27c5e412cc9 /tests
parentd1dab866b5986c7e9ec36cdc1d9c9a6fde6d73c4 (diff)
downloadorg.eclipse.etrice-29873f1151bb915cf3044f21deca9c756d3f95e0.tar.gz
org.eclipse.etrice-29873f1151bb915cf3044f21deca9c756d3f95e0.tar.xz
org.eclipse.etrice-29873f1151bb915cf3044f21deca9c756d3f95e0.zip
Bug 534211 - unify Detail Code parsing
new scanner, parser and linker for detail code including tests * the scanner is tokenizing the text * the parser creates an AST * the linker associates Room objects to the AST nodes in a context dependent way * unit tests for scanner, parser and linker * a detail code translator is provided with a slightly changed interface to the translation provider Change-Id: I84075b6618dc0cedcec6e8da73520bf0a7bcaf90
Diffstat (limited to 'tests')
-rw-r--r--tests/org.eclipse.etrice.core.genmodel.tests/org.eclipse.etrice.core.genmodel.tests.launch2
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/META-INF/MANIFEST.MF3
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/src-gen/org/eclipse/etrice/core/room/tests/RoomInjectorProvider.java8
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/FormatterTest.xtend8
-rw-r--r--tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestNames.xtend2
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/.classpath8
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/.gitignore4
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/.project34
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/META-INF/MANIFEST.MF24
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/build.properties5
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/models/DetailCodes.room103
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/models/Types.room13
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.behavior184
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.structure70
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/org.eclipse.etrice.dctools.tests - plugin-test.launch47
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/DCToolsTestsActivator.java21
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestConstants.xtend62
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCLinker.xtend642
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCParser.xtend408
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCScanner.xtend304
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCTranslator.xtend163
-rw-r--r--tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TranslationProviderForTests.xtend125
-rw-r--r--tests/org.eclipse.etrice.etunit.converter.tests/org.eclipse.etrice.etunit.converter.tests.launch2
-rw-r--r--tests/org.eclipse.etrice.generator.tests/org.eclipse.etrice.generator.tests.launch2
-rw-r--r--tests/org.eclipse.etrice.generator.tests/src/org/eclipse/etrice/generator/base/TestDetailCodeTranslator.java12
-rw-r--r--tests/org.eclipse.etrice.ui.behavior.tests/org.eclipse.etrice.ui.behavior.tests.launch2
-rw-r--r--tests/org.eclipse.etrice.ui.structure.tests/org.eclipse.etrice.ui.structure.tests.launch2
28 files changed, 2246 insertions, 21 deletions
diff --git a/tests/org.eclipse.etrice.core.genmodel.tests/org.eclipse.etrice.core.genmodel.tests.launch b/tests/org.eclipse.etrice.core.genmodel.tests/org.eclipse.etrice.core.genmodel.tests.launch
index 06c1560bc..abf91faa4 100644
--- a/tests/org.eclipse.etrice.core.genmodel.tests/org.eclipse.etrice.core.genmodel.tests.launch
+++ b/tests/org.eclipse.etrice.core.genmodel.tests/org.eclipse.etrice.core.genmodel.tests.launch
@@ -29,7 +29,7 @@
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.core.genmodel.tests"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-XX:PermSize=32m&#13;&#10;-XX:MaxPermSize=256m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
<booleanAttribute key="run_in_ui_thread" value="false"/>
diff --git a/tests/org.eclipse.etrice.core.room.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.etrice.core.room.tests/META-INF/MANIFEST.MF
index 249e68142..936985085 100644
--- a/tests/org.eclipse.etrice.core.room.tests/META-INF/MANIFEST.MF
+++ b/tests/org.eclipse.etrice.core.room.tests/META-INF/MANIFEST.MF
@@ -14,7 +14,8 @@ Require-Bundle: org.eclipse.etrice.core.room;bundle-version="1.1.1",
org.eclipse.osgi;bundle-version="3.6.0",
org.eclipse.xtext;bundle-version="2.6.0",
org.eclipse.core.runtime;bundle-version="3.6.0",
- org.eclipse.emf.ecore
+ org.eclipse.emf.ecore,
+ org.eclipse.xtext.testing;bundle-version="2.13.0"
Bundle-Activator: org.eclipse.etrice.core.CoreTestsActivator
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.etrice.core
diff --git a/tests/org.eclipse.etrice.core.room.tests/src-gen/org/eclipse/etrice/core/room/tests/RoomInjectorProvider.java b/tests/org.eclipse.etrice.core.room.tests/src-gen/org/eclipse/etrice/core/room/tests/RoomInjectorProvider.java
index cccecc6f5..4c7560546 100644
--- a/tests/org.eclipse.etrice.core.room.tests/src-gen/org/eclipse/etrice/core/room/tests/RoomInjectorProvider.java
+++ b/tests/org.eclipse.etrice.core.room.tests/src-gen/org/eclipse/etrice/core/room/tests/RoomInjectorProvider.java
@@ -6,10 +6,10 @@ package org.eclipse.etrice.core.room.tests;
import org.eclipse.etrice.core.RoomRuntimeModule;
import org.eclipse.etrice.core.RoomStandaloneSetup;
-import org.eclipse.xtext.junit4.GlobalRegistries;
-import org.eclipse.xtext.junit4.GlobalRegistries.GlobalStateMemento;
-import org.eclipse.xtext.junit4.IInjectorProvider;
-import org.eclipse.xtext.junit4.IRegistryConfigurator;
+import org.eclipse.xtext.testing.GlobalRegistries;
+import org.eclipse.xtext.testing.GlobalRegistries.GlobalStateMemento;
+import org.eclipse.xtext.testing.IInjectorProvider;
+import org.eclipse.xtext.testing.IRegistryConfigurator;
import com.google.inject.Guice;
import com.google.inject.Injector;
diff --git a/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/FormatterTest.xtend b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/FormatterTest.xtend
index 2a710a92d..35044f72e 100644
--- a/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/FormatterTest.xtend
+++ b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/FormatterTest.xtend
@@ -8,9 +8,9 @@ import java.util.regex.Pattern
import org.eclipse.core.runtime.FileLocator
import org.eclipse.emf.common.util.URI
import org.eclipse.etrice.core.room.tests.RoomInjectorProvider
-import org.eclipse.xtext.junit4.InjectWith
-import org.eclipse.xtext.junit4.XtextRunner
-import org.eclipse.xtext.junit4.formatter.FormatterTester
+import org.eclipse.xtext.testing.InjectWith
+import org.eclipse.xtext.testing.XtextRunner
+import org.eclipse.xtext.testing.formatter.FormatterTestHelper
import org.junit.Test
import org.junit.runner.RunWith
@@ -19,7 +19,7 @@ import static org.junit.Assert.assertNotEquals
@RunWith(XtextRunner)
@InjectWith(RoomInjectorProvider)
-class FormatterTest extends FormatterTester {
+class FormatterTest extends FormatterTestHelper {
// does not work with comments or ccstring
val patterns = #[
diff --git a/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestNames.xtend b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestNames.xtend
index bc7f587b7..002cfd17d 100644
--- a/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestNames.xtend
+++ b/tests/org.eclipse.etrice.core.room.tests/src/org/eclipse/etrice/core/TestNames.xtend
@@ -38,7 +38,7 @@ class TestNames extends TestBase {
if(it instanceof AbstractValidationDiagnostic){
val obj = it.sourceEObject
var nameError = nameErrorMap.get(obj)
- if(nameError == null) nameError = false
+ if(nameError === null) nameError = false
nameErrorMap.put(obj, (nameError || it.isNameErrorMessage))
}
]
diff --git a/tests/org.eclipse.etrice.dctools.tests/.classpath b/tests/org.eclipse.etrice.dctools.tests/.classpath
new file mode 100644
index 000000000..428337e56
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="xtend-gen"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tests/org.eclipse.etrice.dctools.tests/.gitignore b/tests/org.eclipse.etrice.dctools.tests/.gitignore
new file mode 100644
index 000000000..1a7726dc2
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/.gitignore
@@ -0,0 +1,4 @@
+bin
+*._trace
+*.smap
+*.xtendbin
diff --git a/tests/org.eclipse.etrice.dctools.tests/.project b/tests/org.eclipse.etrice.dctools.tests/.project
new file mode 100644
index 000000000..fecccdd43
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.etrice.dctools.tests</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
+ </natures>
+</projectDescription>
diff --git a/tests/org.eclipse.etrice.dctools.tests/.settings/org.eclipse.jdt.core.prefs b/tests/org.eclipse.etrice.dctools.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..0c68a61dc
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/tests/org.eclipse.etrice.dctools.tests/META-INF/MANIFEST.MF b/tests/org.eclipse.etrice.dctools.tests/META-INF/MANIFEST.MF
new file mode 100644
index 000000000..b410cf21b
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,24 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Expressions UI Tests
+Bundle-SymbolicName: org.eclipse.etrice.dctools.tests;singleton:=true
+Bundle-Version: 1.1.1.qualifier
+Automatic-Module-Name: org.eclipse.etrice.expressions.ui.tests
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-Vendor: Eclipse eTrice
+Require-Bundle: org.junit;bundle-version="4.12.0",
+ org.eclipse.jface.text;bundle-version="3.12.2",
+ org.eclipse.core.runtime;bundle-version="3.13.0",
+ org.eclipse.emf.ecore;bundle-version="2.13.0",
+ com.google.guava,
+ org.eclipse.etrice.dctools,
+ org.eclipse.osgi,
+ org.eclipse.xtext.xbase.lib,
+ org.eclipse.xtend.lib,
+ org.eclipse.xtend.lib.macro,
+ org.eclipse.etrice.core.fsm,
+ org.eclipse.etrice.core.room,
+ org.eclipse.etrice.core.room.tests
+Bundle-ActivationPolicy: lazy
+Bundle-Activator: org.eclipse.etrice.dctools.tests.DCToolsTestsActivator
+
diff --git a/tests/org.eclipse.etrice.dctools.tests/build.properties b/tests/org.eclipse.etrice.dctools.tests/build.properties
new file mode 100644
index 000000000..d8e2f0e92
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/build.properties
@@ -0,0 +1,5 @@
+source.. = src/,\
+ xtend-gen/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/tests/org.eclipse.etrice.dctools.tests/models/DetailCodes.room b/tests/org.eclipse.etrice.dctools.tests/models/DetailCodes.room
new file mode 100644
index 000000000..a153e50a9
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/models/DetailCodes.room
@@ -0,0 +1,103 @@
+RoomModel DCParserTests {
+
+ import room.basic.types.* from "Types.room"
+
+ async ActorClass AC {
+ Interface {
+ Port prt: PC
+ Port replPrt[2]: PC
+
+ Port dataPort: PCData
+ }
+ Structure {
+ external Port prt
+ external Port replPrt
+ external Port dataPort
+
+ Attribute p[2]: Point
+ Attribute pt: Point
+ Attribute c: Circle
+ }
+ Behavior {
+ Operation distance(p1: Point, p2: Point): float64 '''
+ return p1.distance(p2);
+ '''
+
+ StateMachine {
+ State first {
+ entry '''
+ prt.start();
+
+ Point lpt = new Point(1,2);
+ prt.result(lpt);'''
+ }
+ State second {
+ entry '''
+ double d = c.diameter();
+ d = p[0].distance(p[1]);
+ d = distance(p[0], p[1]);
+ d = c.c.x;
+ '''
+ exit '''
+ replPrt[0].start();
+ replPrt.start();
+ prt[0].start();
+ '''
+ }
+ Transition init0: initial -> first
+ Transition tr0: first -> second {
+ triggers {
+ <circle: prt>
+ }
+ action '''transitionData.west().distance(transitionData.c);'''
+ }
+ State third
+ Transition tr1: second -> third {
+ guard '''true'''
+ action '''pt.set(dataPort.point);'''
+ }
+ }
+ }
+ }
+
+ datadriven ProtocolClass PCData {
+ incoming {
+ Message point(Point)
+ }
+ }
+
+ ProtocolClass PC {
+ incoming {
+ Message point(Point)
+ Message circle(Circle)
+ }
+ outgoing {
+ Message start()
+ Message result(Point)
+ }
+ }
+
+ DataClass Circle {
+ Operation diameter(): float64 '''
+ return 2*r;
+ '''
+ Operation west(): Point '''
+ return new Point(c.x + r, c.y);
+ '''
+ Operation isInside(other: Point): boolean '''
+ return c.distance(other) < r;
+ '''
+ Attribute r: float64
+ Attribute c: Point
+ }
+
+ DataClass Point {
+ Operation distance(other: Point): float64 '''
+ double dx = x - other.x;
+ double dy = y - other.y;
+ return Math.sqrt(dx*dx + dy*dy);
+ '''
+ Attribute x: float64
+ Attribute y: float64
+ }
+}
diff --git a/tests/org.eclipse.etrice.dctools.tests/models/Types.room b/tests/org.eclipse.etrice.dctools.tests/models/Types.room
new file mode 100644
index 000000000..b27d100f4
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/models/Types.room
@@ -0,0 +1,13 @@
+RoomModel room.basic.types {
+
+ PrimitiveType boolean: ptBoolean -> 'boolean' (Boolean) default 'false'
+ PrimitiveType char: ptCharacter -> 'char' (Char) default ''
+ PrimitiveType int8: ptInteger -> 'byte' (Byte) default '0'
+ PrimitiveType int16: ptInteger -> 'short' (Short) default '0'
+ PrimitiveType int32: ptInteger -> 'int' (Integer) default '0'
+ PrimitiveType int64: ptInteger -> 'long' (Long) default '0'
+ PrimitiveType float32: ptReal -> 'float' (Float) default '0'
+ PrimitiveType float64: ptReal -> 'double' (Double) default '0'
+ PrimitiveType string: ptCharacter -> 'String' (String) default ''
+
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.behavior b/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.behavior
new file mode 100644
index 000000000..2164fa1e3
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.behavior
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="ASCII"?>
+<pi:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:al="http://eclipse.org/graphiti/mm/algorithms" xmlns:pi="http://eclipse.org/graphiti/mm/pictograms" visible="true" gridUnit="10" diagramTypeId="room.behavior" name="Behavior of AC" pictogramLinks="//@link //@children.0/@link //@children.0/@children.1/@link //@children.0/@children.2/@link //@children.0/@children.3/@link //@connections.0/@link //@connections.1/@link //@children.0/@children.4/@link //@connections.2/@link" verticalGridUnit="10" version="0.14.0">
+ <graphicsAlgorithm xsi:type="al:Rectangle" background="//@colors.1" foreground="//@colors.0" lineWidth="1" transparency="0.0" width="1000" height="1000"/>
+ <link>
+ <businessObjects href="../DetailCodes.room#ActorClass:AC"/>
+ </link>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="sg"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="880" height="580" x="40" y="40">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" background="//@colors.1" foreground="//@colors.2" lineWidth="4" transparency="0.5" width="800" height="500" x="40" y="40" cornerHeight="20" cornerWidth="20"/>
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" foreground="//@colors.2" lineWidth="4" filled="false" transparency="0.0" width="800" height="500" x="40" y="40" cornerHeight="20" cornerWidth="20"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#StateGraph:AC$sg"/>
+ </link>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="800" height="80" y="40" font="//@fonts.1" horizontalAlignment="ALIGNMENT_RIGHT" verticalAlignment="ALIGNMENT_TOP" value="/"/>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="state"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="120" height="90" x="187" y="150">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" background="//@colors.3" foreground="//@colors.2" lineWidth="1" transparency="0.0" width="60" height="30" x="30" y="30" cornerHeight="20" cornerWidth="20">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="15" height="8" x="35" y="3" cornerHeight="5" cornerWidth="5"/>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="true" transparency="0.0" x="30" y="24">
+ <points x="-3" y="-3"/>
+ <points x="-3" y="3"/>
+ <points x="-11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="3" y="-3"/>
+ <points x="3" y="3"/>
+ <points x="11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="-2" y="-3"/>
+ <points x="-2" y="3"/>
+ <points x="2" y="3"/>
+ <points x="2" y="-3"/>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#SimpleState:AC$first"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" outgoingConnections="//@connections.1" incomingConnections="//@connections.0"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="60" height="30" x="30" y="30" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="first"/>
+ </children>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="state"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="120" height="90" x="457" y="281">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" background="//@colors.3" foreground="//@colors.2" lineWidth="1" transparency="0.0" width="60" height="30" x="30" y="30" cornerHeight="20" cornerWidth="20">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="15" height="8" x="35" y="3" cornerHeight="5" cornerWidth="5"/>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="true" transparency="0.0" x="30" y="24">
+ <points x="-3" y="-3"/>
+ <points x="-3" y="3"/>
+ <points x="-11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="true" transparency="0.0" x="30" y="24">
+ <points x="3" y="-3"/>
+ <points x="3" y="3"/>
+ <points x="11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="-2" y="-3"/>
+ <points x="-2" y="3"/>
+ <points x="2" y="3"/>
+ <points x="2" y="-3"/>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#SimpleState:AC$second"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" outgoingConnections="//@connections.2" incomingConnections="//@connections.1"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="60" height="30" x="30" y="30" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="second"/>
+ </children>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="ini"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="40" height="40" x="90" y="77">
+ <graphicsAlgorithmChildren xsi:type="al:Ellipse" background="//@colors.1" foreground="//@colors.2" lineWidth="2" transparency="0.0" width="20" height="20" x="10" y="10"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#StateGraph:AC$sg"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" outgoingConnections="//@connections.0"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" background="//@colors.4" foreground="//@colors.4" lineWidth="1" filled="false" transparency="0.0" width="40" height="20" y="10" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="I"/>
+ </children>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="state"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="120" height="90" x="560" y="91">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" background="//@colors.3" foreground="//@colors.2" lineWidth="1" transparency="0.0" width="60" height="30" x="30" y="30" cornerHeight="20" cornerWidth="20">
+ <graphicsAlgorithmChildren xsi:type="al:RoundedRectangle" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="15" height="8" x="35" y="3" cornerHeight="5" cornerWidth="5"/>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="-3" y="-3"/>
+ <points x="-3" y="3"/>
+ <points x="-11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="3" y="-3"/>
+ <points x="3" y="3"/>
+ <points x="11" y="3"/>
+ </graphicsAlgorithmChildren>
+ <graphicsAlgorithmChildren xsi:type="al:Polygon" foreground="//@colors.2" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" x="30" y="24">
+ <points x="-2" y="-3"/>
+ <points x="-2" y="3"/>
+ <points x="2" y="3"/>
+ <points x="2" y="-3"/>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithmChildren>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#SimpleState:AC$third"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" incomingConnections="//@connections.2" referencedGraphicsAlgorithm="//@children.0/@children.4/@graphicsAlgorithm/@graphicsAlgorithmChildren.0"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="60" height="30" x="30" y="30" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="third"/>
+ </children>
+ </children>
+ </children>
+ <connections xsi:type="pi:FreeFormConnection" visible="true" active="true" start="//@children.0/@children.3/@anchors.0" end="//@children.0/@children.1/@anchors.0">
+ <properties key="obj-type" value="trans"/>
+ <graphicsAlgorithm xsi:type="al:Polyline" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0"/>
+ <link>
+ <businessObjects href="../DetailCodes.room#InitialTransition:AC$initial"/>
+ </link>
+ <connectionDecorators visible="true" locationRelative="true" location="1.0">
+ <graphicsAlgorithm xsi:type="al:Polygon" background="//@colors.1" foreground="//@colors.2" lineWidth="1" filled="true" transparency="0.0">
+ <points x="-15" y="5"/>
+ <points/>
+ <points x="-15" y="-5"/>
+ </graphicsAlgorithm>
+ </connectionDecorators>
+ <connectionDecorators visible="true" active="true" locationRelative="true" location="0.5">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" x="10" font="//@fonts.0" value="init"/>
+ </connectionDecorators>
+ </connections>
+ <connections xsi:type="pi:FreeFormConnection" visible="true" active="true" start="//@children.0/@children.1/@anchors.0" end="//@children.0/@children.2/@anchors.0">
+ <properties key="obj-type" value="trans"/>
+ <graphicsAlgorithm xsi:type="al:Polyline" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0"/>
+ <link>
+ <businessObjects href="../DetailCodes.room#TriggeredTransition:AC$tr0"/>
+ </link>
+ <connectionDecorators visible="true" locationRelative="true" location="1.0">
+ <graphicsAlgorithm xsi:type="al:Polygon" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="true" transparency="0.0">
+ <points x="-15" y="5"/>
+ <points/>
+ <points x="-15" y="-5"/>
+ </graphicsAlgorithm>
+ </connectionDecorators>
+ <connectionDecorators visible="true" active="true" locationRelative="true" location="0.5">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" x="10" font="//@fonts.0" value="tr0: &lt;circle:prt>"/>
+ </connectionDecorators>
+ </connections>
+ <connections xsi:type="pi:FreeFormConnection" visible="true" active="true" start="//@children.0/@children.2/@anchors.0" end="//@children.0/@children.4/@anchors.0">
+ <properties key="obj-type" value="trans"/>
+ <graphicsAlgorithm xsi:type="al:Polyline" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0"/>
+ <link>
+ <businessObjects href="../DetailCodes.room#GuardedTransition:AC$tr1"/>
+ </link>
+ <connectionDecorators visible="true" locationRelative="true" location="1.0">
+ <graphicsAlgorithm xsi:type="al:Polygon" background="//@colors.2" foreground="//@colors.2" lineWidth="1" filled="true" transparency="0.0">
+ <points x="-15" y="5"/>
+ <points/>
+ <points x="-15" y="-5"/>
+ </graphicsAlgorithm>
+ </connectionDecorators>
+ <connectionDecorators visible="true" active="true" locationRelative="true" location="0.5">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" x="10" font="//@fonts.0" value="tr1: guard {true}"/>
+ </connectionDecorators>
+ </connections>
+ <colors red="227" green="238" blue="249"/>
+ <colors red="255" green="255" blue="255"/>
+ <colors/>
+ <colors red="200" green="200" blue="200"/>
+ <colors red="100" green="100" blue="100"/>
+ <fonts name="Arial" size="8"/>
+ <fonts name="Arial" size="9" bold="true"/>
+</pi:Diagram>
diff --git a/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.structure b/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.structure
new file mode 100644
index 000000000..54817afc0
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/models/diagrams/DCParserTests.AC.structure
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="ASCII"?>
+<pi:Diagram xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:al="http://eclipse.org/graphiti/mm/algorithms" xmlns:pi="http://eclipse.org/graphiti/mm/pictograms" visible="true" gridUnit="10" diagramTypeId="room.structure" name="Structure of AC" pictogramLinks="//@link //@children.0/@link //@children.0/@children.0/@link //@children.0/@children.1/@link //@children.0/@children.2/@link" verticalGridUnit="10" version="0.14.0">
+ <graphicsAlgorithm xsi:type="al:Rectangle" background="//@colors.1" foreground="//@colors.0" lineWidth="1" transparency="0.0" width="1000" height="1000"/>
+ <link>
+ <businessObjects href="../DetailCodes.room#ActorClass:AC"/>
+ </link>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="cls"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="880" height="580" x="40" y="40">
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" background="//@colors.1" foreground="//@colors.2" lineWidth="1" lineVisible="false" transparency="0.5" width="800" height="500" x="40" y="40"/>
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" foreground="//@colors.2" lineWidth="4" filled="false" transparency="0.0" width="800" height="500" x="40" y="40"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#ActorClass:AC"/>
+ </link>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="port"/>
+ <properties key="inherited" value="false"/>
+ <properties key="item-kind" value=""/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="80" height="80" x="379" y="500">
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" background="//@colors.2" foreground="//@colors.2" lineWidth="2" transparency="0.0" width="40" height="40" x="20" y="20"/>
+ <graphicsAlgorithmChildren xsi:type="al:Ellipse" background="//@colors.1" foreground="//@colors.1" lineWidth="2" transparency="0.0" width="20" height="20" x="30" y="30"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#Port:AC$prt"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" referencedGraphicsAlgorithm="//@children.0/@children.0/@graphicsAlgorithm/@graphicsAlgorithmChildren.0"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="80" height="20" y="60" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="prt"/>
+ </children>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="port"/>
+ <properties key="inherited" value="false"/>
+ <properties key="item-kind" value="M"/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="80" height="80" x="374">
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" background="//@colors.1" foreground="//@colors.2" lineWidth="2" transparency="0.0" width="40" height="40" x="25" y="15"/>
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" background="//@colors.2" foreground="//@colors.2" lineWidth="2" transparency="0.0" width="40" height="40" x="20" y="20"/>
+ <graphicsAlgorithmChildren xsi:type="al:Ellipse" background="//@colors.1" foreground="//@colors.1" lineWidth="2" transparency="0.0" width="20" height="20" x="30" y="30"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#Port:AC$replPrt"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" referencedGraphicsAlgorithm="//@children.0/@children.1/@graphicsAlgorithm/@graphicsAlgorithmChildren.1"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="80" height="20" font="//@fonts.0" horizontalAlignment="ALIGNMENT_CENTER" value="replPrt"/>
+ </children>
+ </children>
+ <children xsi:type="pi:ContainerShape" visible="true" active="true">
+ <properties key="obj-type" value="port"/>
+ <properties key="inherited" value="false"/>
+ <properties key="item-kind" value=""/>
+ <graphicsAlgorithm xsi:type="al:Rectangle" lineWidth="1" filled="false" lineVisible="false" transparency="0.0" width="80" height="80" x="800" y="214">
+ <graphicsAlgorithmChildren xsi:type="al:Rectangle" background="//@colors.2" foreground="//@colors.2" lineWidth="2" transparency="0.0" width="40" height="40" x="20" y="20"/>
+ <graphicsAlgorithmChildren xsi:type="al:Ellipse" background="//@colors.1" foreground="//@colors.1" lineWidth="2" transparency="0.0" width="20" height="20" x="30" y="30"/>
+ </graphicsAlgorithm>
+ <link>
+ <businessObjects href="../DetailCodes.room#Port:AC$dataPort"/>
+ </link>
+ <anchors xsi:type="pi:ChopboxAnchor" referencedGraphicsAlgorithm="//@children.0/@children.2/@graphicsAlgorithm/@graphicsAlgorithmChildren.0"/>
+ <children visible="true">
+ <graphicsAlgorithm xsi:type="al:Text" foreground="//@colors.2" lineWidth="1" filled="false" transparency="0.0" width="80" height="20" y="60" font="//@fonts.0" horizontalAlignment="ALIGNMENT_RIGHT" value="dataPort"/>
+ </children>
+ </children>
+ </children>
+ <colors red="227" green="238" blue="249"/>
+ <colors red="255" green="255" blue="255"/>
+ <colors/>
+ <fonts name="Arial" size="8"/>
+</pi:Diagram>
diff --git a/tests/org.eclipse.etrice.dctools.tests/org.eclipse.etrice.dctools.tests - plugin-test.launch b/tests/org.eclipse.etrice.dctools.tests/org.eclipse.etrice.dctools.tests - plugin-test.launch
new file mode 100644
index 000000000..0d1aa7c91
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/org.eclipse.etrice.dctools.tests - plugin-test.launch
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="append.args" value="true"/>
+<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="true"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="true"/>
+<stringAttribute key="deselected_workspace_plugins" value="my.etrice.generator,my.etrice.generator.launch,org.eclipse.etrice.abstractexec.behavior,org.eclipse.etrice.abstractexec.behavior.tests,org.eclipse.etrice.core.common.tests,org.eclipse.etrice.core.common.ui,org.eclipse.etrice.core.config,org.eclipse.etrice.core.config.tests,org.eclipse.etrice.core.config.ui,org.eclipse.etrice.core.etmap.tests,org.eclipse.etrice.core.etmap.ui,org.eclipse.etrice.core.etphys.tests,org.eclipse.etrice.core.etphys.ui,org.eclipse.etrice.core.fsm.tests,org.eclipse.etrice.core.fsm.ui,org.eclipse.etrice.core.genmodel.fsm.tests,org.eclipse.etrice.core.genmodel.tests,org.eclipse.etrice.core.room.ui,org.eclipse.etrice.doc,org.eclipse.etrice.etunit.converter,org.eclipse.etrice.etunit.converter.tests,org.eclipse.etrice.generator.c,org.eclipse.etrice.generator.config,org.eclipse.etrice.generator.cpp,org.eclipse.etrice.generator.doc,org.eclipse.etrice.generator.fsmtest,org.eclipse.etrice.generator.fsmtest.tests,org.eclipse.etrice.generator.fsmtest.ui,org.eclipse.etrice.generator.gnuplot,org.eclipse.etrice.generator.java,org.eclipse.etrice.generator.launch,org.eclipse.etrice.generator.launch.c,org.eclipse.etrice.generator.launch.cpp,org.eclipse.etrice.generator.launch.java,org.eclipse.etrice.generator.tests,org.eclipse.etrice.generator.ui,org.eclipse.etrice.generator.ui.cdt,org.eclipse.etrice.modellib.java,org.eclipse.etrice.runtime.java,org.eclipse.etrice.runtime.java.aspects,org.eclipse.etrice.ui.base.tests,org.eclipse.etrice.ui.behavior,org.eclipse.etrice.ui.behavior.actioneditor,org.eclipse.etrice.ui.behavior.fsm,org.eclipse.etrice.ui.behavior.tests,org.eclipse.etrice.ui.commands,org.eclipse.etrice.ui.common,org.eclipse.etrice.ui.common.base,org.eclipse.etrice.ui.runtime,org.eclipse.etrice.ui.structure,org.eclipse.etrice.ui.structure.tests"/>
+<booleanAttribute key="includeOptional" value="true"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.etrice.dctools.tests"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.etrice.dctools.tests"/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.dctools.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.8"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.platform.ide"/>
+<booleanAttribute key="run_in_ui_thread" value="true"/>
+<stringAttribute key="selected_target_plugins" value="com.google.guava*21.0.0.v20170206-1425@default:default,com.google.inject.multibindings@default:false,com.google.inject@default:default,com.ibm.icu@default:default,com.jcraft.jsch@default:default,com.jcraft.jzlib@default:default,de.itemis.xtext.antlr@default:default,javax.annotation@default:default,javax.inject@default:default,javax.servlet*3.1.0.v201410161800@default:default,javax.xml@default:default,org.antlr.generator@default:default,org.antlr.runtime*4.3.0.v201502022030@default:default,org.apache.ant@default:default,org.apache.batik.css*1.8.0.v20170214-1941@default:default,org.apache.batik.util*1.8.0.v20170214-1941@default:default,org.apache.commons.cli@default:default,org.apache.commons.io@default:default,org.apache.commons.jxpath@default:default,org.apache.commons.lang@default:default,org.apache.commons.logging@default:default,org.apache.felix.gogo.command@default:default,org.apache.felix.gogo.runtime@default:default,org.apache.log4j@default:default,org.apache.lucene.analyzers-common@default:default,org.apache.lucene.analyzers-smartcn@default:default,org.apache.lucene.core*6.1.0.v20170814-1820@default:default,org.apache.lucene.misc@default:default,org.apache.xml.resolver@default:default,org.eclipse.ant.core@default:default,org.eclipse.ant.launching@default:default,org.eclipse.ant.ui@default:default,org.eclipse.compare.core@default:default,org.eclipse.compare@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.externaltools@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.net.win32.x86_64@default:false,org.eclipse.core.net@default:default,org.eclipse.core.resources.win32.x86_64@default:false,org.eclipse.core.resources@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.debug.ui@default:default,org.eclipse.e4.core.commands@default:default,org.eclipse.e4.core.contexts@default:default,org.eclipse.e4.core.di.annotations@default:default,org.eclipse.e4.core.di.extensions.supplier@default:default,org.eclipse.e4.core.di.extensions@default:default,org.eclipse.e4.core.di@default:default,org.eclipse.e4.core.services@default:default,org.eclipse.e4.emf.xpath@default:default,org.eclipse.e4.ui.bindings@default:default,org.eclipse.e4.ui.css.core@default:default,org.eclipse.e4.ui.css.swt.theme@default:default,org.eclipse.e4.ui.css.swt@default:default,org.eclipse.e4.ui.di@default:default,org.eclipse.e4.ui.model.workbench@default:default,org.eclipse.e4.ui.services@default:default,org.eclipse.e4.ui.widgets@default:default,org.eclipse.e4.ui.workbench.addons.swt@default:default,org.eclipse.e4.ui.workbench.renderers.swt@default:default,org.eclipse.e4.ui.workbench.swt@default:default,org.eclipse.e4.ui.workbench3@default:default,org.eclipse.e4.ui.workbench@default:default,org.eclipse.emf.codegen.ecore@default:default,org.eclipse.emf.codegen@default:default,org.eclipse.emf.common.ui@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.change@default:default,org.eclipse.emf.ecore.edit@default:default,org.eclipse.emf.ecore.editor@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.emf.edit.ui@default:default,org.eclipse.emf.edit@default:default,org.eclipse.emf.mwe.core@default:default,org.eclipse.emf.mwe.utils@default:default,org.eclipse.emf.mwe2.language@default:default,org.eclipse.emf.mwe2.launch@default:default,org.eclipse.emf.mwe2.lib@default:default,org.eclipse.emf.mwe2.runtime@default:default,org.eclipse.emf@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.bidi@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.equinox.frameworkadmin@default:default,org.eclipse.equinox.http.jetty@default:default,org.eclipse.equinox.http.servlet@default:default,org.eclipse.equinox.p2.artifact.repository@default:default,org.eclipse.equinox.p2.core@default:default,org.eclipse.equinox.p2.director.app@default:default,org.eclipse.equinox.p2.director@default:default,org.eclipse.equinox.p2.engine@default:default,org.eclipse.equinox.p2.garbagecollector@default:default,org.eclipse.equinox.p2.jarprocessor@default:default,org.eclipse.equinox.p2.metadata.repository@default:default,org.eclipse.equinox.p2.metadata@default:default,org.eclipse.equinox.p2.operations@default:default,org.eclipse.equinox.p2.publisher.eclipse@default:default,org.eclipse.equinox.p2.publisher@default:default,org.eclipse.equinox.p2.repository.tools@default:default,org.eclipse.equinox.p2.repository@default:default,org.eclipse.equinox.p2.touchpoint.eclipse@default:default,org.eclipse.equinox.p2.ui@default:default,org.eclipse.equinox.p2.updatesite@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.security.ui@default:default,org.eclipse.equinox.security.win32.x86_64@default:false,org.eclipse.equinox.security@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.eclipse.help.base@default:default,org.eclipse.help.ui@default:default,org.eclipse.help@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.jdt.core.manipulation@default:default,org.eclipse.jdt.core@default:default,org.eclipse.jdt.debug.ui@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.jdt.junit.core@default:default,org.eclipse.jdt.junit.runtime@default:default,org.eclipse.jdt.junit@default:default,org.eclipse.jdt.launching@default:default,org.eclipse.jdt.ui@default:default,org.eclipse.jetty.http@default:default,org.eclipse.jetty.io@default:default,org.eclipse.jetty.security@default:default,org.eclipse.jetty.server@default:default,org.eclipse.jetty.servlet@default:default,org.eclipse.jetty.util@default:default,org.eclipse.jface.databinding@default:default,org.eclipse.jface.text@default:default,org.eclipse.jface@default:default,org.eclipse.ltk.core.refactoring@default:default,org.eclipse.ltk.ui.refactoring@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.eclipse.pde.build@default:default,org.eclipse.pde.core@default:default,org.eclipse.pde.launching@default:default,org.eclipse.pde.ui@default:default,org.eclipse.search@default:default,org.eclipse.swt.win32.win32.x86_64@default:false,org.eclipse.swt@default:default,org.eclipse.team.core@default:default,org.eclipse.team.ui@default:default,org.eclipse.text@default:default,org.eclipse.ui.cheatsheets@default:default,org.eclipse.ui.console@default:default,org.eclipse.ui.editors@default:default,org.eclipse.ui.externaltools@default:default,org.eclipse.ui.forms@default:default,org.eclipse.ui.ide@default:default,org.eclipse.ui.intro@default:default,org.eclipse.ui.navigator.resources@default:default,org.eclipse.ui.navigator@default:default,org.eclipse.ui.trace@default:default,org.eclipse.ui.views.log@default:default,org.eclipse.ui.views.properties.tabbed@default:default,org.eclipse.ui.views@default:default,org.eclipse.ui.win32@default:false,org.eclipse.ui.workbench.texteditor@default:default,org.eclipse.ui.workbench@default:default,org.eclipse.ui@default:default,org.eclipse.update.configurator@3:true,org.eclipse.xpand@default:default,org.eclipse.xtend.lib.macro@default:default,org.eclipse.xtend.lib@default:default,org.eclipse.xtend.typesystem.emf@default:default,org.eclipse.xtend@default:default,org.eclipse.xtext.builder.standalone@default:default,org.eclipse.xtext.builder@default:default,org.eclipse.xtext.common.types.edit@default:default,org.eclipse.xtext.common.types.ui@default:default,org.eclipse.xtext.common.types@default:default,org.eclipse.xtext.ecore@default:default,org.eclipse.xtext.generator@default:default,org.eclipse.xtext.ide@default:default,org.eclipse.xtext.junit4@default:default,org.eclipse.xtext.logging@default:false,org.eclipse.xtext.smap@default:default,org.eclipse.xtext.testing@default:default,org.eclipse.xtext.ui.codetemplates.ide@default:default,org.eclipse.xtext.ui.codetemplates.ui@default:default,org.eclipse.xtext.ui.codetemplates@default:default,org.eclipse.xtext.ui.shared@default:default,org.eclipse.xtext.ui.testing@default:default,org.eclipse.xtext.ui@default:default,org.eclipse.xtext.util@default:default,org.eclipse.xtext.xbase.ide@default:default,org.eclipse.xtext.xbase.junit@default:default,org.eclipse.xtext.xbase.lib@default:default,org.eclipse.xtext.xbase.ui@default:default,org.eclipse.xtext.xbase@default:default,org.eclipse.xtext.xtext.generator@default:default,org.eclipse.xtext@default:default,org.hamcrest.core@default:default,org.junit@default:default,org.objectweb.asm*6.0.0.v20180116-1719@default:default,org.sat4j.core@default:default,org.sat4j.pb@default:default,org.slf4j.api@default:default,org.slf4j.impl.log4j12@default:false,org.tukaani.xz@default:default,org.w3c.css.sac@default:default,org.w3c.dom.events@default:default,org.w3c.dom.smil@default:default,org.w3c.dom.svg@default:default"/>
+<stringAttribute key="selected_workspace_plugins" value="org.eclipse.etrice.core.common@default:default,org.eclipse.etrice.core.etmap@default:default,org.eclipse.etrice.core.etphys@default:default,org.eclipse.etrice.core.fsm@default:default,org.eclipse.etrice.core.genmodel.fsm@default:default,org.eclipse.etrice.core.genmodel@default:default,org.eclipse.etrice.core.room.tests@default:default,org.eclipse.etrice.core.room@default:default,org.eclipse.etrice.expressions.ui.tests@default:default,org.eclipse.etrice.expressions.ui@default:default,org.eclipse.etrice.generator.fsm@default:default,org.eclipse.etrice.generator@default:default,org.eclipse.etrice.logging@default:false"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<stringAttribute key="templateConfig" value="${target_home}\configuration\config.ini"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="false"/>
+</launchConfiguration>
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/DCToolsTestsActivator.java b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/DCToolsTestsActivator.java
new file mode 100644
index 000000000..a9c153105
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/DCToolsTestsActivator.java
@@ -0,0 +1,21 @@
+package org.eclipse.etrice.dctools.tests;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.eclipse.core.runtime.Plugin;
+
+public class DCToolsTestsActivator extends Plugin implements BundleActivator {
+
+ private static DCToolsTestsActivator instance = null;
+
+ public static DCToolsTestsActivator getInstance() {
+ return instance;
+ }
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+
+ instance = this;
+ }
+}
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestConstants.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestConstants.xtend
new file mode 100644
index 000000000..8a38916a8
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestConstants.xtend
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2018 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+interface TestConstants {
+
+ static val TEST_STRING = "\"some test string\""
+ static val TEST_C_COMMENT = "/* comment */"
+ static val TEST_C_COMMENT2 = "/* comment\n\tnext line */"
+ static val TEST_CPP_COMMENT = "// cpp comment"
+ static val TEST_EMPTY_ROUND_BRACKET = "()"
+ static val TEST_EMPTY_CURLY_BRACKET = "{}"
+ static val TEST_EMPTY_SQUARE_BRACKET = "[]"
+ static val CONTENTS1 = "/* comment */"
+ static val CONTENTS2 = "/* another comment */"
+ static val CONTENTS3 = "/* third comment */"
+ static val TEST_EMPTY_ROUND_BRACKET_W_CONTENTS1 = "(" + CONTENTS1 + ")"
+ static val TEST_NESTED_BRACKETS = "(" + CONTENTS1 + "(" + CONTENTS2 + ")" + CONTENTS3 + ")"
+ static val TEST_IDENTIFIER = "someIdentifier_123_name"
+ static val TEST_ARRAY_ACCESS = "array[]"
+ static val TEST_OPERATION_CALL = "foo()"
+ static val TEST_MEMBER_ACCESS = "field.member"
+ static val TEST_ARRAY_MEMBER_ACCESS = "field[1+2].member"
+ static val TEST_ARRAY_MEMBER_ACCESS_AND_CALL = TEST_ARRAY_MEMBER_ACCESS + ".op()"
+ static val TEST_SPACY_ARRAY_MEMBER_ACCESS_AND_CALL = "field [ 1 + 2 ]\n\t. member . op ( )"
+ static val TEST_CODE = "DC var = new DC(); port.message(var);"
+ static val TEST_CODE1 = "field.member1.member2[3].operation(x+4)"
+ static val TEST_CODE2 = '''
+ sendPort.ping(x /* comment */);
+ ping.ping(1);
+ // comment
+ int local = 0;
+ foo(foo(123+456+x)*2+foo(local));
+ /* foo(i) */
+ String t = "foo(i)";
+ '''
+ static val TEST_CODE3 = '''
+ int result = 1;
+ for (int i=0; i<10; ++i) {
+ if (i>=5) {
+ result = result * 3;
+ }
+ result = foo(result*2);
+ }
+ '''
+
+ // incomplete sequences
+ static val TEST_UNCLOSED_STRING = "\"the closing quotes are missing"
+ static val TEST_UNCLOSED_BRACKETS = "(/* the closing round bracket is missing*/"
+ static val TEST_UNCLOSED_NESTED_BRACKETS = "((/* nested */)/* the outer closing round bracket is missing*/"
+ static val TEST_INCOMPLETE_FEATURE_CALL = "field.member."
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCLinker.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCLinker.xtend
new file mode 100644
index 000000000..b5fab53d0
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCLinker.xtend
@@ -0,0 +1,642 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.etrice.core.TestBase
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.MessageData
+import org.eclipse.etrice.core.room.ProtocolClass
+import org.eclipse.etrice.core.room.RoomModel
+import org.eclipse.etrice.core.room.RoomPackage
+import org.eclipse.etrice.core.room.StandardOperation
+import org.eclipse.etrice.core.room.VarDecl
+import org.eclipse.etrice.core.room.util.RoomHelpers
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.ast.DCLinker
+import org.eclipse.etrice.dctools.fsm.ast.DCParser
+import org.junit.Before
+import org.junit.Test
+
+import static org.hamcrest.CoreMatchers.*
+import static org.junit.Assert.*
+import org.eclipse.etrice.core.fsm.fSM.FSMPackage
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.etrice.core.room.Message
+import org.eclipse.etrice.core.room.ActorClass
+import org.eclipse.etrice.core.room.DataClass
+
+class TestDCLinker extends TestBase {
+
+ Resource res = null;
+ RoomModel model
+ val extension RoomHelpers roomHelpers = new RoomHelpers
+
+ @Before
+ def void SetUp() {
+ prepare(DCToolsTestsActivator.getInstance.bundle)
+ res = getResource("DetailCodes.room")
+ assertNotNull(res)
+ assertFalse(res.contents.empty)
+ assertTrue(res.contents.head instanceof RoomModel)
+ model = res.contents.head as RoomModel
+ }
+
+// detail code:
+// double dx = x - other.x;
+// double dy = y - other.y;
+// return Math.sqrt(dx*dx + dy*dy);
+
+// AST:
+//DCAstMatchNode
+// DCAstOtherNode 'double' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dx'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'x' --> Attribute
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '-' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'other' --> VarDecl
+// DCAstPeriodNode
+// DCAstIdentifierNode 'x' --> Attribute
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstOtherNode 'double' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dy'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'y' --> Attribute
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '-' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'other' --> VarDecl
+// DCAstPeriodNode
+// DCAstIdentifierNode 'y' --> Attribute
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstOtherNode 'return' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'Math'
+// DCAstPeriodNode
+// DCAstOperationCallNode 'sqrt()'
+// DCAstIdentifierNode 'sqrt'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dx'
+// DCAstOtherNode '*' OTHER
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dx'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '+' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dy'
+// DCAstOtherNode '*' OTHER
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'dy'
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//
+//' WHITESPACE
+ @Test
+ def void testDataClassOperationWithAttributesAndVarDecl() {
+ // we want to test the distance operation of data class Point
+ val dc = model.dataClasses.filter[name=="Point"].head
+ val op = dc.operations.filter[name=="distance"].head
+ val code = op.detailCode.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(op.detailCode)
+ ast.visit(linker)
+
+ ast.print
+
+ assertTrue(ast.c(5).c(0).linkedObject instanceof Attribute)
+ var att = ast.c(5).c(0).linkedObject as Attribute
+ assertThat(att.name, is("x"))
+
+ assertTrue(ast.c(8).c(0).linkedObject instanceof VarDecl)
+ val vd = ast.c(8).c(0).linkedObject as VarDecl
+ assertThat(vd.name, is("other"))
+
+ assertTrue(ast.c(8).c(2).linkedObject instanceof Attribute)
+ att = ast.c(8).c(2).linkedObject as Attribute
+ assertThat(att.name, is("x"))
+ }
+
+// detail code:
+// return c.distance(other) < r;
+
+// AST:
+//DCAstMatchNode
+// DCAstOtherNode 'return' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'c' --> Attribute
+// DCAstPeriodNode
+// DCAstOperationCallNode 'distance()' --> StandardOperation
+// DCAstIdentifierNode 'distance'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'other' --> VarDecl
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '<' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'r' --> Attribute
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//
+//' WHITESPACE
+ @Test
+ def void testDataClassOperationWithOperationCall() {
+ // we want to test the isInside operation of data class Circle
+ val dc = model.dataClasses.filter[name=="Circle"].head
+ val op = dc.operations.filter[name=="isInside"].head
+ val code = op.detailCode.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(op, RoomPackage.Literals.OPERATION__DETAIL_CODE)
+ ast.visit(linker)
+
+ ast.print
+
+ var lo = ast.c(2).c(0).linkedObject
+ assertTrue(lo instanceof Attribute)
+ var att = lo as Attribute
+ assertThat(att.name, is("c"))
+
+ lo = ast.c(2).c(2).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ var sop = lo as StandardOperation
+ assertThat(sop.name, is("distance"))
+
+ lo = ast.c(2).c(2).c(1).c(0).c(0).c(0).linkedObject
+ assertTrue(lo instanceof VarDecl)
+ var vd = lo as VarDecl
+ assertThat(vd.name, is("other"))
+ }
+
+// detail code:
+// transitionData.west().distance(transitionData.c);
+
+// AST:
+//DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'transitionData' --> MessageData
+// DCAstPeriodNode
+// DCAstOperationCallNode 'west()' --> StandardOperation
+// DCAstIdentifierNode 'west'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstPeriodNode
+// DCAstOperationCallNode 'distance()' --> StandardOperation
+// DCAstIdentifierNode 'distance'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'transitionData' --> MessageData
+// DCAstPeriodNode
+// DCAstIdentifierNode 'c' --> Attribute
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+ @Test
+ def void testTransitionData() {
+ // we want to test the action code of tr0
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val tr = ac.stateMachine.transitions.filter[name=="tr0"].head
+ val code = tr.action.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val pc = model.protocolClasses.filter(ProtocolClass).filter[name=="PC"].head
+ val msg = pc.incomingMessages.filter[name=="circle"].head
+ val md = msg.data
+ val linker = new DCLinker(tr.action, md)
+ ast.visit(linker)
+
+ ast.print
+
+ var lo = ast.c(0).c(0).linkedObject
+ assertTrue(lo instanceof MessageData)
+
+ lo = ast.c(0).c(2).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ var sop = lo as StandardOperation
+ assertThat(sop.name, is("west"))
+
+ lo = ast.c(0).c(4).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ sop = lo as StandardOperation
+ assertThat(sop.name, is("distance"))
+
+ lo = ast.c(0).c(4).c(1).c(0).c(0).c(0).linkedObject
+ assertTrue(lo instanceof MessageData)
+
+ lo = ast.c(0).c(4).c(1).c(0).c(0).c(2).linkedObject
+ assertTrue(lo instanceof Attribute)
+ var att = lo as Attribute
+ assertThat(att.name, is("c"))
+ }
+
+// detail code:
+// prt.start();
+//
+// Point pt = new Point(1,2);
+// prt.result(pt);'''
+
+// AST:
+//DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'prt' --> Port
+// DCAstPeriodNode
+// DCAstOperationCallNode 'start()' --> Message
+// DCAstIdentifierNode 'start'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'Point'
+// DCAstWhitespaceNode ' '
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'pt'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstOtherNode 'new' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstOperationCallNode 'Point()'
+// DCAstIdentifierNode 'Point'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode '1' NUMBER
+// DCAstOtherNode ',' OTHER
+// DCAstOtherNode '2' NUMBER
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'prt' --> Port
+// DCAstPeriodNode
+// DCAstOperationCallNode 'result()' --> Message
+// DCAstIdentifierNode 'result'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'pt'
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+ @Test
+ def void testPortMessage() {
+ // we want to test the entry code of state 'first'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="first"].head
+ val code = st.entryCode.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(st.entryCode)
+ ast.visit(linker)
+
+ ast.print
+
+ var lo = ast.c(0).c(0).linkedObject
+ assertTrue(lo instanceof Port)
+ var p = lo as Port
+ assertThat(p.name, is("prt"))
+
+ lo = ast.c(0).c(2).linkedObject
+ assertTrue(lo instanceof Message)
+ var m = lo as Message
+ assertThat(m.name, is("start"))
+
+ lo = ast.c(12).c(0).linkedObject
+ assertTrue(lo instanceof Port)
+ p = lo as Port
+ assertThat(p.name, is("prt"))
+
+ lo = ast.c(12).c(2).linkedObject
+ assertTrue(lo instanceof Message)
+ m = lo as Message
+ assertThat(m.name, is("result"))
+ }
+
+// detail code:
+// double d = c.diameter();
+// d = p[0].distance(p[1]);
+// d = distance(p[0], p[1]);
+// d = c.c.x;
+
+// AST:
+//DCAstMatchNode
+// DCAstOtherNode 'double' KEYWORD
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'd'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'c' --> Attribute
+// DCAstPeriodNode
+// DCAstOperationCallNode 'diameter()' --> StandardOperation
+// DCAstIdentifierNode 'diameter'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'd'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'p[]' --> Attribute
+// DCAstIdentifierNode 'p'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '0' NUMBER
+// DCAstPeriodNode
+// DCAstOperationCallNode 'distance()' --> StandardOperation
+// DCAstIdentifierNode 'distance'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'p[]' --> Attribute
+// DCAstIdentifierNode 'p'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '1' NUMBER
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'd'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstOperationCallNode 'distance()' --> StandardOperation
+// DCAstIdentifierNode 'distance'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'p[]' --> Attribute
+// DCAstIdentifierNode 'p'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '0' NUMBER
+// DCAstOtherNode ',' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'p[]' --> Attribute
+// DCAstIdentifierNode 'p'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '1' NUMBER
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'd'
+// DCAstWhitespaceNode ' '
+// DCAstOtherNode '=' OTHER
+// DCAstOtherNode ' ' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'c' --> Attribute
+// DCAstPeriodNode
+// DCAstIdentifierNode 'c' --> Attribute
+// DCAstPeriodNode
+// DCAstIdentifierNode 'x' --> Attribute
+// DCAstWhitespaceNode '
+//
+//'
+ @Test
+ def void testActorClassAttributes() {
+ // we want to test the entry code of state 'first'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="second"].head
+ val code = st.entryCode.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(st, FSMPackage.Literals.STATE__ENTRY_CODE)
+ ast.visit(linker)
+
+ ast.print
+
+ var lo = ast.c(5).c(0).linkedObject
+ assertTrue(lo instanceof Attribute)
+ var a = lo as Attribute
+ assertThat(a.name, is("c"))
+
+ lo = ast.c(5).c(2).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ var op = lo as StandardOperation
+ assertThat(op.name, is("diameter"))
+ var dc = model.dataClasses.filter[name=="Circle"].head
+ val circleOp = dc.operations.filter[name=="diameter"].head
+ assertThat(op, is(circleOp))
+
+ lo = ast.c(11).c(0).linkedObject
+ assertTrue(lo instanceof Attribute)
+ a = lo as Attribute
+ assertThat(a.name, is("p"))
+
+ lo = ast.c(11).c(2).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ op = lo as StandardOperation
+ assertThat(op.name, is("distance"))
+ dc = model.dataClasses.filter[name=="Point"].head
+ val pointOp = dc.operations.filter[name=="distance"].head
+ assertThat(op, is(pointOp))
+
+ lo = ast.c(17).c(0).linkedObject
+ assertTrue(lo instanceof StandardOperation)
+ op = lo as StandardOperation
+ assertThat(op.name, is("distance"))
+ val actorOp = ac.operations.filter[name=="distance"].head
+ assertThat(op, is(actorOp))
+
+ lo = ast.c(23).c(0).linkedObject
+ assertTrue(lo instanceof Attribute)
+ a = lo as Attribute
+ assertThat(a.name, is("c"))
+ assertTrue(a.eContainer instanceof ActorClass)
+
+ lo = ast.c(23).c(2).linkedObject
+ assertTrue(lo instanceof Attribute)
+ a = lo as Attribute
+ assertThat(a.name, is("c"))
+ assertTrue(a.eContainer instanceof DataClass)
+ assertThat((a.eContainer as DataClass).name, is("Circle"))
+
+ lo = ast.c(23).c(4).linkedObject
+ assertTrue(lo instanceof Attribute)
+ a = lo as Attribute
+ assertThat(a.name, is("x"))
+ assertTrue(a.eContainer instanceof DataClass)
+ assertThat((a.eContainer as DataClass).name, is("Point"))
+ }
+
+// detail code:
+// replPrt[0].start();
+// replPrt.start();
+// prt[0].start();
+
+// AST:
+//DCAstMatchNode
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'replPrt[]' --> Port
+// DCAstIdentifierNode 'replPrt'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '0' NUMBER
+// DCAstPeriodNode
+// DCAstOperationCallNode 'start()' --> Message
+// DCAstIdentifierNode 'start'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstIdentifierNode 'replPrt' --> Port
+// DCAstPeriodNode
+// DCAstOperationCallNode 'start()' --> Message
+// DCAstIdentifierNode 'start'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//' WHITESPACE
+// DCAstFeatureCallNode
+// DCAstArrayAccessNode 'prt[]'
+// DCAstIdentifierNode 'prt'
+// DCAstBracketNode []
+// DCAstMatchNode
+// DCAstOtherNode '0' NUMBER
+// DCAstPeriodNode
+// DCAstOperationCallNode 'start()'
+// DCAstIdentifierNode 'start'
+// DCAstBracketNode ()
+// DCAstMatchNode
+// DCAstOtherNode ';' STATEMENT_SEP
+// DCAstOtherNode '
+//
+//' WHITESPACE
+ @Test
+ def void testReplPortMessage() {
+ // we want to test the exit code of state 'second'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="second"].head
+ val code = st.exitCode.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val linker = new DCLinker(st, FSMPackage.Literals.STATE__ENTRY_CODE)
+ ast.visit(linker)
+
+ ast.print
+
+ // array access to replicated port
+ var lo = ast.c(0).c(0).linkedObject
+ assertTrue(lo instanceof Port)
+ var p = lo as Port
+ assertThat(p.name, is("replPrt"))
+
+ lo = ast.c(0).c(2).linkedObject
+ assertTrue(lo instanceof Message)
+ var m = lo as Message
+ assertThat(m.name, is("start"))
+
+ // broadcast through replicated port (scalar access)
+ lo = ast.c(3).c(0).linkedObject
+ assertTrue(lo instanceof Port)
+ p = lo as Port
+ assertThat(p.name, is("replPrt"))
+
+ lo = ast.c(3).c(2).linkedObject
+ assertTrue(lo instanceof Message)
+ m = lo as Message
+ assertThat(m.name, is("start"))
+
+ // a non replicated port with array access shouldn't be linked
+ lo = ast.c(6).c(0).linkedObject
+ assertThat(lo, is(nullValue))
+ }
+
+ @Test
+ def void testDataPortGetterAndAttributeSetter() {
+ // we want to test the action code of tr1
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val tr = ac.stateMachine.transitions.filter[name=="tr1"].head
+ val code = tr.action.detailCode
+
+ // parse
+ val parser = new DCParser(DCLanguage.JAVA_LANGUAGE)
+ val ast = parser.parse(code)
+
+ // link
+ val pc = model.protocolClasses.filter(ProtocolClass).filter[name=="PCData"].head
+ val msg = pc.incomingMessages.filter[name=="point"].head
+ val md = msg.data
+ val linker = new DCLinker(tr.action, md)
+ ast.visit(linker)
+
+ ast.print
+ }
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCParser.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCParser.xtend
new file mode 100644
index 000000000..df0e392ab
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCParser.xtend
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2018 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.fsm.ast.DCParser
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstArrayAccessNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstBracketNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstFeatureCallNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstIdentifierNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstMatchNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstOperationCallNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstOtherNode
+import org.eclipse.etrice.dctools.fsm.ast.nodes.DCAstPeriodNode
+import org.eclipse.etrice.dctools.fsm.ast.util.DCAstPrinter
+import org.junit.Before
+import org.junit.Test
+
+import static org.eclipse.etrice.dctools.tests.TestConstants.*
+import static org.hamcrest.CoreMatchers.*
+import static org.junit.Assert.*
+
+class TestDCParser {
+
+ DCParser parser
+
+ @Before
+ def void createParser() {
+ parser = new DCParser(DCLanguage.C_LANGUAGE)
+ }
+
+ @Test
+ def void testString() {
+ testSingleOther("testString", TEST_STRING)
+ }
+
+ @Test
+ def void testCComment() {
+ testSingleOther("testCComment", TEST_C_COMMENT)
+ }
+
+ @Test
+ def void testCComment2() {
+ testSingleOther("testCComment2", TEST_C_COMMENT2)
+ }
+
+ @Test
+ def void testCppComment() {
+ testSingleOther("testCppComment", TEST_CPP_COMMENT)
+ }
+
+ @Test
+ def void testEmptyRoundBracket() {
+ testBracketExpression(TEST_EMPTY_ROUND_BRACKET, DCAstBracketNode.BracketType.ROUND)
+ }
+
+ @Test
+ def void testEmptyCurlyBracket() {
+ testBracketExpression(TEST_EMPTY_CURLY_BRACKET, DCAstBracketNode.BracketType.CURLY)
+ }
+
+ @Test
+ def void testEmptySquareBracket() {
+ testBracketExpression(TEST_EMPTY_SQUARE_BRACKET, DCAstBracketNode.BracketType.SQUARE)
+ }
+
+ @Test
+ def void testRoundBracketWithContents() {
+ testBracketExpression(TEST_EMPTY_ROUND_BRACKET_W_CONTENTS1, DCAstBracketNode.BracketType.ROUND, CONTENTS1)
+ }
+
+ @Test
+ def void testNestedBrackets() {
+ val result = parser.parse(TEST_NESTED_BRACKETS)
+ assertNotNull(result)
+
+ // we have a single bracket expression
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+
+ // it is a bracket node
+ assertTrue(node instanceof DCAstBracketNode)
+ assertTrue((node as DCAstBracketNode).type==DCAstBracketNode.BracketType.ROUND)
+
+ // which has one child
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+
+ // which is a match node
+ assertTrue(node instanceof DCAstMatchNode)
+
+ // which has three children
+ assertThat(node.children.size, is(3))
+
+ // first child is a comment
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstOtherNode)
+ assertEquals((node as DCAstOtherNode).text, CONTENTS1)
+
+ // third child is a comment
+ node = node.parent.children.get(2)
+ assertTrue(node instanceof DCAstOtherNode)
+ assertEquals((node as DCAstOtherNode).text, CONTENTS3)
+
+ // middle child is a bracket
+ node = node.parent.children.get(1)
+ assertTrue(node instanceof DCAstBracketNode)
+ assertTrue((node as DCAstBracketNode).type==DCAstBracketNode.BracketType.ROUND)
+
+ // which has one child
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+
+ // which is a match node
+ assertTrue(node instanceof DCAstMatchNode)
+
+ // which has one child
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+
+ // which is a comment
+ assertTrue(node instanceof DCAstOtherNode)
+ assertEquals((node as DCAstOtherNode).text, CONTENTS2)
+
+ prettyPrint("testNestedBrackets", TEST_NESTED_BRACKETS, result, 7, 8)
+ }
+
+ @Test
+ def void testIdentifier() {
+ val result = parser.parse(TEST_IDENTIFIER)
+ assertNotNull(result)
+
+ // we have a feature
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+ assertTrue(node instanceof DCAstFeatureCallNode)
+
+ // it is an identifier node
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstIdentifierNode)
+ assertThat((node as DCAstIdentifierNode).identifier, is(TEST_IDENTIFIER))
+
+ prettyPrint("testIdentifier", TEST_IDENTIFIER, result, 1, 3)
+ }
+
+ @Test
+ def void testArrayAccess() {
+ val result = parser.parse(TEST_ARRAY_ACCESS)
+ assertNotNull(result)
+
+ // we have a feature
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+ assertTrue(node instanceof DCAstFeatureCallNode)
+
+ // with an array access
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstArrayAccessNode)
+
+ // with two children
+ assertThat(node.children.size, is(2))
+
+ // an identifier
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstIdentifierNode)
+
+ // and a bracket
+ node = node.parent.children.get(1)
+ assertTrue(node instanceof DCAstBracketNode)
+
+ prettyPrint("testArrayAccess", TEST_ARRAY_ACCESS, result, 3, 6)
+ }
+
+ @Test
+ def void testOperationCall() {
+ val result = parser.parse(TEST_OPERATION_CALL)
+ assertNotNull(result)
+
+ // we have a feature
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+ assertTrue(node instanceof DCAstFeatureCallNode)
+
+ // with an operation call
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstOperationCallNode)
+
+ // with two children
+ assertThat(node.children.size, is(2))
+
+ // an identifier
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstIdentifierNode)
+
+ // and a bracket
+ node = node.parent.children.get(1)
+ assertTrue(node instanceof DCAstBracketNode)
+
+ prettyPrint("testOperationCall", TEST_OPERATION_CALL, result, 3, 6)
+ }
+
+ @Test
+ def void testMemberAccess() {
+ val result = parser.parse(TEST_MEMBER_ACCESS)
+ assertNotNull(result)
+
+ // we have a feature
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+ assertTrue(node instanceof DCAstFeatureCallNode)
+
+ // with identifier period identifier
+ assertThat(node.children.size, is(3))
+
+ // identifier node
+ node = node.children.get(0)
+ assertTrue(node instanceof DCAstIdentifierNode)
+
+ // period node
+ node = node.parent.children.get(1)
+ assertTrue(node instanceof DCAstPeriodNode)
+
+ // identifier node
+ node = node.parent.children.get(2)
+ assertTrue(node instanceof DCAstIdentifierNode)
+
+ prettyPrint("testMemberAccess", TEST_MEMBER_ACCESS, result, 3, 5)
+ }
+
+ @Test
+ def void testArrayMemberAccess() {
+ val result = parser.parse(TEST_ARRAY_MEMBER_ACCESS)
+ assertNotNull(result)
+
+ prettyPrint("testArrayMemberAccess", TEST_ARRAY_MEMBER_ACCESS, result, 8, 11)
+ }
+
+ @Test
+ def void testArrayMemberAccessAndCall() {
+ val result = parser.parse(TEST_ARRAY_MEMBER_ACCESS_AND_CALL)
+ assertNotNull(result)
+
+ prettyPrint("testArrayMemberAccessAndCall", TEST_ARRAY_MEMBER_ACCESS_AND_CALL, result, 12, 16)
+ }
+
+ @Test
+ def void testSpacyArrayMemberAccessAndCall() {
+ val result = parser.parse(TEST_SPACY_ARRAY_MEMBER_ACCESS_AND_CALL)
+ assertNotNull(result)
+
+ prettyPrint("testSpacyArrayMemberAccessAndCall", TEST_SPACY_ARRAY_MEMBER_ACCESS_AND_CALL, result, 23, 27)
+ }
+
+ @Test
+ def void testCode() {
+ val result = parser.parse(TEST_CODE)
+ assertNotNull(result)
+
+ prettyPrint("testCode", TEST_CODE, result, 20, 29)
+ }
+
+ @Test
+ def void testCode1() {
+ val result = parser.parse(TEST_CODE1)
+ assertNotNull(result)
+
+ prettyPrint("testCode", TEST_CODE1, result, 15, 20)
+ }
+
+ @Test
+ def void testCode2() {
+ val result = parser.parse(TEST_CODE2)
+ assertNotNull(result)
+
+ prettyPrint("testCode2", TEST_CODE2, result, 59, 76)
+ }
+
+ @Test
+ def void testCode3() {
+ val result = parser.parse(TEST_CODE3)
+ assertNotNull(result)
+
+ prettyPrint("testCode3", TEST_CODE3, result, 69, 81)
+ }
+
+ @Test
+ def void testUnclosedString() {
+ val result = parser.parse(TEST_UNCLOSED_STRING)
+ assertNotNull(result)
+
+ prettyPrint("testUnclosedString", TEST_UNCLOSED_STRING, result, 1, 2)
+ }
+
+ @Test
+ def void testUnclosedNestedBrackets() {
+ val result = parser.parse(TEST_UNCLOSED_NESTED_BRACKETS)
+ assertNotNull(result)
+
+ prettyPrint("testUnclosedNestedBrackets", TEST_UNCLOSED_NESTED_BRACKETS, result, 6, 7)
+ }
+
+ @Test
+ def void testIncompleteFeatureCall() {
+ val result = parser.parse(TEST_INCOMPLETE_FEATURE_CALL)
+ assertNotNull(result)
+
+ prettyPrint("testIncompleteFeatureCall", TEST_INCOMPLETE_FEATURE_CALL, result, 4, 6)
+ }
+
+ /*
+ * helper methods
+ */
+ private def prettyPrint(String method, String orig, DCAstMatchNode node, int nTokes, int nNodes) {
+ val printer = new DCAstPrinter
+ node.visit(printer)
+
+ println("<<<" + method)
+ println("tree: ")
+ node.print
+ println(nNodes + " nodes, " + nTokes + " tokens")
+ println("orig: '" + orig + "'")
+ println("ast: '" + printer.text + "'")
+ println(method + ">>>")
+
+ assertEquals(orig, printer.text)
+ assertThat(node.totallyReadTokens, is(nTokes))
+ assertThat(node.countNodes, is(nNodes))
+ }
+
+ private def void testBracketExpression(String test, DCAstBracketNode.BracketType bt) {
+ testBracketExpression(test, bt, null)
+ }
+
+ private def void testBracketExpression(String test, DCAstBracketNode.BracketType bt, String contents) {
+ val result = parser.parse(test)
+ assertNotNull(result)
+
+ // we have only a bracket expression
+ assertThat(result.children.size, is(1))
+ var node = result.children.get(0)
+
+ // it is a bracket node
+ assertTrue(node instanceof DCAstBracketNode)
+ assertTrue((node as DCAstBracketNode).type==bt)
+
+ // which has one child
+ assertThat(node.children.size, is(1))
+ node = node.children.get(0)
+
+ // which is a match node
+ assertTrue(node instanceof DCAstMatchNode)
+
+ if (contents===null) {
+ // which is empty
+ assertThat(node.children.size, is(0))
+ }
+ else {
+ // which has a single sub node
+ assertThat(node.children.size, is(1))
+
+ // which is Other with contents
+ testOther(node.children.get(0), contents)
+ }
+ }
+
+ private def testSingleOther(String method, String test) {
+ val result = parser.parse(test)
+ assertNotNull(result)
+
+ prettyPrint(method, test, result, 1, 2)
+
+ // only one Other expression
+ assertThat(result.children.size, is(1))
+
+ testOther(result.children.get(0), test)
+ }
+
+ private def testOther(DCAstNode node, String contents) {
+ // which is an Other node
+ assertTrue(node instanceof DCAstOtherNode)
+
+ // with the test text as contents
+ assertEquals((node as DCAstOtherNode).text, contents)
+ }
+
+ private def int countNodes(DCAstNode node) {
+ var sum = 1
+
+ for (child : node.children) {
+ sum += child.countNodes
+ }
+
+ return sum
+ }
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCScanner.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCScanner.xtend
new file mode 100644
index 000000000..96b4913b4
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCScanner.xtend
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2018 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.fsm.ast.DCScanner
+import org.junit.Before
+import org.junit.Test
+import org.eclipse.etrice.dctools.fsm.ast.internal.DCBracketToken.BracketKind
+import org.eclipse.etrice.dctools.fsm.ast.internal.DCToken.Kind
+
+import static org.eclipse.etrice.dctools.tests.TestConstants.*
+import static org.hamcrest.CoreMatchers.*
+import static org.junit.Assert.*
+import org.eclipse.etrice.dctools.fsm.ast.internal.DCBracketToken
+import org.eclipse.etrice.dctools.fsm.ast.internal.DCToken
+
+class TestDCScanner {
+
+ DCScanner scanner
+
+ @Before
+ def void createScanner() {
+ scanner = new DCScanner(DCLanguage.C_LANGUAGE)
+ }
+
+ @Test
+ def void testString() {
+ val tokens = scanner.scan(TEST_STRING)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.STRING))
+ }
+
+ @Test
+ def void testCComment() {
+ val tokens = scanner.scan(TEST_C_COMMENT)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testCComment2() {
+ val tokens = scanner.scan(TEST_C_COMMENT2)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testCppComment() {
+ val tokens = scanner.scan(TEST_CPP_COMMENT)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testEmptyRoundBracket() {
+ testBracketExpression(TEST_EMPTY_ROUND_BRACKET, BracketKind.LEFT_ROUND, BracketKind.RIGHT_ROUND)
+ }
+
+ @Test
+ def void testEmptyCurlyBracket() {
+ testBracketExpression(TEST_EMPTY_CURLY_BRACKET, BracketKind.LEFT_CURLY, BracketKind.RIGHT_CURLY)
+ }
+
+ @Test
+ def void testEmptySquareBracket() {
+ testBracketExpression(TEST_EMPTY_SQUARE_BRACKET, BracketKind.LEFT_SQUARE, BracketKind.RIGHT_SQUARE)
+ }
+
+ @Test
+ def void testRoundBracketWithContents() {
+ val tokens = testBracketExpression(TEST_EMPTY_ROUND_BRACKET_W_CONTENTS1, BracketKind.LEFT_ROUND, BracketKind.RIGHT_ROUND, 1)
+ assertThat(tokens.get(1).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testNestedBrackets() {
+ val tokens = scanner.scan(TEST_NESTED_BRACKETS)
+ assertThat(tokens.size, is(7))
+ testBracketToken(tokens.get(0).token, BracketKind.LEFT_ROUND)
+ assertThat(tokens.get(1).token.kind, is(Kind.COMMENT))
+ testBracketToken(tokens.get(2).token, BracketKind.LEFT_ROUND)
+ assertThat(tokens.get(3).token.kind, is(Kind.COMMENT))
+ testBracketToken(tokens.get(4).token, BracketKind.RIGHT_ROUND)
+ assertThat(tokens.get(5).token.kind, is(Kind.COMMENT))
+ testBracketToken(tokens.get(6).token, BracketKind.RIGHT_ROUND)
+ }
+
+ @Test
+ def void testIdentifier() {
+ val tokens = scanner.scan(TEST_IDENTIFIER)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testArrayAccess() {
+ val tokens = scanner.scan(TEST_ARRAY_ACCESS)
+ assertThat(tokens.size, is(3))
+ assertThat(tokens.get(0).token.kind, is(Kind.IDENTIFIER))
+ testBracketToken(tokens.get(1).token, BracketKind.LEFT_SQUARE)
+ testBracketToken(tokens.get(2).token, BracketKind.RIGHT_SQUARE)
+ }
+
+ @Test
+ def void testOperationCall() {
+ val tokens = scanner.scan(TEST_OPERATION_CALL)
+ assertThat(tokens.size, is(3))
+ assertThat(tokens.get(0).token.kind, is(Kind.IDENTIFIER))
+ testBracketToken(tokens.get(1).token, BracketKind.LEFT_ROUND)
+ testBracketToken(tokens.get(2).token, BracketKind.RIGHT_ROUND)
+ }
+
+ @Test
+ def void testMemberAccess() {
+ val tokens = scanner.scan(TEST_MEMBER_ACCESS)
+ assertThat(tokens.size, is(3))
+ assertThat(tokens.get(0).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(1).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(2).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testArrayMemberAccess() {
+ val tokens = scanner.scan(TEST_ARRAY_MEMBER_ACCESS)
+ assertThat(tokens.size, is(8))
+ assertThat(tokens.get(0).token.kind, is(Kind.IDENTIFIER))
+ testBracketToken(tokens.get(1).token, BracketKind.LEFT_SQUARE)
+ assertThat(tokens.get(2).token.kind, is(Kind.NUMBER))
+ assertThat(tokens.get(3).token.kind, is(Kind.OTHER))
+ assertThat(tokens.get(4).token.kind, is(Kind.NUMBER))
+ testBracketToken(tokens.get(5).token, BracketKind.RIGHT_SQUARE)
+ assertThat(tokens.get(6).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(7).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testArrayMemberAccessAndCall() {
+ val tokens = scanner.scan(TEST_ARRAY_MEMBER_ACCESS_AND_CALL)
+ assertThat(tokens.size, is(12))
+
+ var pos = 0
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_SQUARE)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.NUMBER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.OTHER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.NUMBER))
+ testBracketToken(tokens.get(pos++).token, BracketKind.RIGHT_SQUARE)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_ROUND)
+ testBracketToken(tokens.get(pos++).token, BracketKind.RIGHT_ROUND)
+ }
+
+ @Test
+ def void testSpacyArrayMemberAccessAndCall() {
+ val tokens = scanner.scan(TEST_SPACY_ARRAY_MEMBER_ACCESS_AND_CALL)
+ assertThat(tokens.size, is(23))
+
+ var pos = 0
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_SQUARE)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.NUMBER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.OTHER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.NUMBER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ testBracketToken(tokens.get(pos++).token, BracketKind.RIGHT_SQUARE)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_ROUND)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.WHITESPACE))
+ testBracketToken(tokens.get(pos++).token, BracketKind.RIGHT_ROUND)
+ }
+
+ @Test
+ def void testCode() {
+ val tokens = scanner.scan(TEST_CODE)
+ assertThat(tokens.size, is(20))
+
+ var pos = 0
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testCode1() {
+ val tokens = scanner.scan(TEST_CODE1)
+ assertThat(tokens.size, is(15))
+
+ var pos = 0
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testCode2() {
+ val tokens = scanner.scan(TEST_CODE2)
+ assertThat(tokens.size, is(59))
+
+ assertThat(tokens.get(19).token.kind, is(Kind.KEYWORD))
+ assertThat(tokens.get(34).token.kind, is(Kind.NUMBER))
+ }
+
+ @Test
+ def void testCode3() {
+ val tokens = scanner.scan(TEST_CODE3)
+ assertThat(tokens.size, is(69))
+
+ assertThat(tokens.get(6).token.kind, is(Kind.NUMBER))
+ assertThat(tokens.get(7).token.kind, is(Kind.STATEMENT_SEP))
+ assertThat(tokens.get(19).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(29).token.kind, is(Kind.BRACKET))
+ assertThat(tokens.get(34).token.kind, is(Kind.IDENTIFIER))
+ }
+
+ @Test
+ def void testUnclosedString() {
+ val tokens = scanner.scan(TEST_UNCLOSED_STRING)
+ assertThat(tokens.size, is(1))
+ assertThat(tokens.get(0).token.kind, is(Kind.STRING))
+ }
+
+ @Test
+ def void testUnclosedBrackets() {
+ val tokens = scanner.scan(TEST_UNCLOSED_BRACKETS)
+ assertThat(tokens.size, is(2))
+
+ var pos = 0
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_ROUND)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testUnclosedNestedBrackets() {
+ val tokens = scanner.scan(TEST_UNCLOSED_NESTED_BRACKETS)
+ assertThat(tokens.size, is(5))
+
+ var pos = 0
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_ROUND)
+ testBracketToken(tokens.get(pos++).token, BracketKind.LEFT_ROUND)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.COMMENT))
+ testBracketToken(tokens.get(pos++).token, BracketKind.RIGHT_ROUND)
+ assertThat(tokens.get(pos++).token.kind, is(Kind.COMMENT))
+ }
+
+ @Test
+ def void testIncompleteFeatureCall() {
+ val tokens = scanner.scan(TEST_INCOMPLETE_FEATURE_CALL)
+ assertThat(tokens.size, is(4))
+
+ var pos = 0
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.IDENTIFIER))
+ assertThat(tokens.get(pos++).token.kind, is(Kind.PERIOD))
+ }
+
+ /*
+ * helper methods
+ */
+ private def testBracketExpression(String test, BracketKind left, BracketKind right) {
+ testBracketExpression(test, left, right, 0)
+ }
+
+ private def testBracketExpression(String test, BracketKind left, BracketKind right, int nInnerTokens) {
+ val tokens = scanner.scan(test)
+
+ assertThat(tokens.size, is(2+nInnerTokens))
+ testBracketToken(tokens.get(0).token, left)
+ testBracketToken(tokens.get(1+nInnerTokens).token, right)
+
+ return tokens
+ }
+
+ private def testBracketToken(DCToken t, BracketKind k) {
+ assertThat(t.kind, is(Kind.BRACKET))
+ assertTrue(t instanceof DCBracketToken)
+ var bt = t as DCBracketToken
+ assertThat(bt.bracketKind, is(k))
+ }
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCTranslator.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCTranslator.xtend
new file mode 100644
index 000000000..e9a2863d3
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TestDCTranslator.xtend
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+import org.eclipse.emf.ecore.resource.Resource
+import org.eclipse.etrice.core.TestBase
+import org.eclipse.etrice.core.room.RoomModel
+import org.eclipse.etrice.core.room.util.RoomHelpers
+import org.junit.Before
+import static org.junit.Assert.*
+import static org.hamcrest.CoreMatchers.*
+import org.junit.Test
+import org.eclipse.etrice.dctools.fsm.ast.DCLanguage
+import org.eclipse.etrice.dctools.ast.DCTranslator
+import org.eclipse.etrice.core.fsm.fSM.DetailCode
+
+class TestDCTranslator extends TestBase {
+
+ Resource res = null;
+ RoomModel model
+ TranslationProviderForTests provider
+ DCTranslator translator
+ val extension RoomHelpers roomHelpers = new RoomHelpers
+
+ @Before
+ def void SetUp() {
+ prepare(DCToolsTestsActivator.getInstance.bundle)
+ res = getResource("DetailCodes.room")
+ assertNotNull(res)
+ assertFalse(res.contents.empty)
+ assertTrue(res.contents.head instanceof RoomModel)
+ model = res.contents.head as RoomModel
+ provider = new TranslationProviderForTests
+ translator = new DCTranslator(DCLanguage.C_LANGUAGE, provider)
+ }
+
+ @Test
+ def void testPortMessage() {
+ // we want to test the entry code of state 'first'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="first"].head
+
+ val translated = translator.getTranslatedCode(st.entryCode)
+ printResult("testPortMessage", st.entryCode, translated)
+
+ // check the translation count
+ assertThat(provider.attributeCount, is(0))
+ assertThat(provider.operationCount, is(0))
+ assertThat(provider.messageTextCount, is(2))
+
+ // check the two translated parts
+ assertThat(translated, startsWith("PC_start(prt);"))
+ assertThat(translated, containsString("\nPC_result(prt, lpt);"))
+
+ // and the result should not contain a null string
+ assertThat(translated, not(containsString("null")))
+ }
+
+ @Test
+ def void testReplPortMessage() {
+ // we want to test the exit code of state 'second'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="second"].head
+
+ val translated = translator.getTranslatedCode(st.exitCode)
+ printResult("testReplPortMessage", st.exitCode, translated)
+
+ // check the translation count
+ assertThat(provider.attributeCount, is(0))
+ assertThat(provider.operationCount, is(0))
+ assertThat(provider.messageTextCount, is(2))
+
+ // check the two translated parts
+ assertThat(translated, startsWith("PC_start(replPrt, 0);"))
+ assertThat(translated, containsString("\nPC_start_broadcast(replPrt);"))
+
+ // and the result should not contain a null string
+ assertThat(translated, not(containsString("null")))
+ }
+
+ @Test
+ def void testActorClassAttributes() {
+ // we want to test the entry code of state 'first'
+ val ac = model.actorClasses.filter[name=="AC"].head
+ val st = ac.stateMachine.states.filter[name=="second"].head
+
+ val translated = translator.getTranslatedCode(st.entryCode)
+ printResult("testActorClassAttributes", st.entryCode, translated)
+
+ // check the translation count
+ assertThat(provider.attributeCount, is(8))
+ assertThat(provider.operationCount, is(3))
+ assertThat(provider.messageTextCount, is(0))
+
+ // check the translated parts
+ assertThat(translated, startsWith("double d = diameter(c(globalScopeSelf));"))
+ assertThat(translated, containsString("\nd = distance(p(globalScopeSelf, 0), p(globalScopeSelf, 1));"))
+ assertThat(translated, containsString("\nd = distance(globalScopeSelf, p(globalScopeSelf, 0), p(globalScopeSelf, 1));"))
+ assertThat(translated, containsString("\nd = x(c(c(globalScopeSelf)));"))
+ }
+
+ @Test
+ def void testDataClassOperationWithAttributesAndVarDecl() {
+ // we want to test the distance operation of data class Point
+ val dc = model.dataClasses.filter[name=="Point"].head
+ val op = dc.operations.filter[name=="distance"].head
+
+ val translated = translator.getTranslatedCode(op.detailCode)
+ printResult("testDataClassOperationWithAttributesAndVarDecl", op.detailCode, translated)
+
+ // check the translation count
+ assertThat(provider.attributeCount, is(4))
+ assertThat(provider.operationCount, is(0))
+ assertThat(provider.messageTextCount, is(0))
+
+ // check the two translated parts
+ assertThat(translated, startsWith("double dx = x(globalScopeSelf)- x(other);"))
+ assertThat(translated, containsString("\ndouble dy = y(globalScopeSelf)- y(other);"))
+
+ // and the result should not contain a null string
+ assertThat(translated, not(containsString("null")))
+ }
+
+ @Test
+ def void testDataClassOperationWithOperationCall() {
+ // we want to test the isInside operation of data class Circle
+ val dc = model.dataClasses.filter[name=="Circle"].head
+ val op = dc.operations.filter[name=="isInside"].head
+
+ val translated = translator.getTranslatedCode(op.detailCode)
+ printResult("testDataClassOperationWithOperationCall", op.detailCode, translated)
+
+ // check the translation count
+ assertThat(provider.attributeCount, is(2))
+ assertThat(provider.operationCount, is(1))
+ assertThat(provider.messageTextCount, is(0))
+
+ // check the translated part
+ assertThat(translated, startsWith("return distance(c(globalScopeSelf), other)< r(globalScopeSelf);"))
+
+ // and the result should not contain a null string
+ assertThat(translated, not(containsString("null")))
+ }
+
+ private def printResult(String test, DetailCode dc, String translated) {
+ println("<<<" + test)
+ println("orig:")
+ println(dc.detailCode)
+ println("translated:")
+ println(translated)
+ println(test + ">>>")
+ }
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TranslationProviderForTests.xtend b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TranslationProviderForTests.xtend
new file mode 100644
index 000000000..807942ef7
--- /dev/null
+++ b/tests/org.eclipse.etrice.dctools.tests/src/org/eclipse/etrice/dctools/tests/TranslationProviderForTests.xtend
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2011 protos software gmbh (http://www.protos.de).
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * CONTRIBUTORS:
+ * Henrik Rentz-Reichert (initial contribution)
+ *
+ *******************************************************************************/
+
+package org.eclipse.etrice.dctools.tests
+
+import org.eclipse.etrice.dctools.ast.ITranslationProvider
+import org.eclipse.etrice.core.room.Attribute
+import org.eclipse.etrice.core.room.Operation
+import org.eclipse.etrice.core.room.InterfaceItem
+import org.eclipse.etrice.core.room.Message
+import org.eclipse.etrice.core.room.EnumLiteral
+import org.eclipse.etrice.core.fsm.fSM.AbstractInterfaceItem
+import org.eclipse.etrice.core.room.PortOperation
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.etrice.core.fsm.fSM.DetailCode
+import org.eclipse.etrice.core.room.Port
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtend.lib.annotations.AccessorType
+
+class TranslationProviderForTests implements ITranslationProvider {
+
+ @Accessors(AccessorType.PUBLIC_GETTER)
+ var messageTextCount = 0
+
+ @Accessors(AccessorType.PUBLIC_GETTER)
+ var attributeCount = 0
+
+ @Accessors(AccessorType.PUBLIC_GETTER)
+ var operationCount = 0
+
+ override setContainerClass(EObject container) {
+ // unused
+ }
+
+ //-- members
+
+ override translateMembers() {
+ true
+ }
+
+ override getAttributeGetter(Attribute att, String instance, String index, String orig) {
+ attributeCount++
+ val slf = if (instance===null) "globalScopeSelf" else instance
+ val allArgs = slf + index.append
+ att.name + "(" + allArgs + ")"
+ }
+
+ override getAttributeSetter(Attribute att, String instance, String index, String value, String orig) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ override getOperationText(Operation op, String instance, String args, String orig) {
+ operationCount++
+ val slf = if (instance===null) "globalScopeSelf" else instance
+ val allArgs = slf + args.append
+ op.name + "(" + allArgs + ")"
+ }
+
+ override getInterfaceItemMessageText(AbstractInterfaceItem item, EObject msg, String ifitem, String args, String index, String orig) {
+ if (msg instanceof Message) {
+ if (item instanceof Port) {
+ messageTextCount++
+ val protocol = item.protocol
+ val allArgs = item.name + index.append + args.append
+ if (index===null && item.multiplicity!=1) {
+ protocol.name + "_" + msg.name + "_broadcast(" + allArgs + ")"
+ }
+ else {
+ protocol.name + "_" + msg.name + "(" + allArgs + ")"
+ }
+ }
+ else {
+ orig
+ }
+ }
+ else {
+ orig
+ }
+ }
+
+ override getInterfaceItemMessageValue(InterfaceItem item, Message msg, String orig) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ override getInterfaceItemOperationText(AbstractInterfaceItem item, PortOperation op, String instance, String args, String orig) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ //-- enums
+
+ override translateEnums() {
+ true
+ }
+
+ override getEnumText(EnumLiteral literal) {
+ throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ }
+
+ //-- tags
+
+ override translateTags() {
+ true
+ }
+
+ override translateTag(String tag, DetailCode code) {
+ return TAG_START+"?"+tag+"?"+TAG_END;
+ }
+
+ private def append(String args) {
+ if (args!==null && !args.trim.empty)
+ ", " + args
+ else
+ ""
+ }
+
+} \ No newline at end of file
diff --git a/tests/org.eclipse.etrice.etunit.converter.tests/org.eclipse.etrice.etunit.converter.tests.launch b/tests/org.eclipse.etrice.etunit.converter.tests/org.eclipse.etrice.etunit.converter.tests.launch
index cd546f2fd..41bb14a77 100644
--- a/tests/org.eclipse.etrice.etunit.converter.tests/org.eclipse.etrice.etunit.converter.tests.launch
+++ b/tests/org.eclipse.etrice.etunit.converter.tests/org.eclipse.etrice.etunit.converter.tests.launch
@@ -29,7 +29,7 @@
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.etunit.converter.tests"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-XX:PermSize=32m&#13;&#10;-XX:MaxPermSize=256m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.8"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.platform.ide"/>
<booleanAttribute key="run_in_ui_thread" value="false"/>
diff --git a/tests/org.eclipse.etrice.generator.tests/org.eclipse.etrice.generator.tests.launch b/tests/org.eclipse.etrice.generator.tests/org.eclipse.etrice.generator.tests.launch
index 45e384c45..f1ea3ff66 100644
--- a/tests/org.eclipse.etrice.generator.tests/org.eclipse.etrice.generator.tests.launch
+++ b/tests/org.eclipse.etrice.generator.tests/org.eclipse.etrice.generator.tests.launch
@@ -33,7 +33,7 @@
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
<booleanAttribute key="run_in_ui_thread" value="false"/>
-<stringAttribute key="selected_target_plugins" value="com.google.guava@default:default,com.google.inject@default:default,com.ibm.icu@default:default,javax.inject@default:default,javax.xml@default:default,org.antlr.runtime@default:default,org.apache.commons.cli@default:default,org.apache.commons.io@default:default,org.apache.commons.lang@default:default,org.apache.commons.logging@default:default,org.apache.log4j@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources.win32.x86_64@default:false,org.eclipse.core.resources@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.emf.codegen.ecore@default:default,org.eclipse.emf.codegen@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.emf.mwe.core@default:default,org.eclipse.emf.mwe.utils@default:default,org.eclipse.emf.mwe2.runtime@default:default,org.eclipse.emf@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.jdt.annotation*2.1.0.v20160418-1457@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.jdt.core@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.jdt.launching@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi@-1:true,org.eclipse.text@default:default,org.eclipse.xpand@default:default,org.eclipse.xtend.lib.macro@default:default,org.eclipse.xtend.lib@default:default,org.eclipse.xtend.typesystem.emf@default:default,org.eclipse.xtend@default:default,org.eclipse.xtext.common.types@default:default,org.eclipse.xtext.ecore@default:default,org.eclipse.xtext.generator@default:default,org.eclipse.xtext.logging@default:false,org.eclipse.xtext.smap@default:default,org.eclipse.xtext.util@default:default,org.eclipse.xtext.xbase.lib@default:default,org.eclipse.xtext.xtext.generator@default:default,org.eclipse.xtext@default:default,org.hamcrest.core@default:default,org.junit@default:default,org.objectweb.asm@default:default"/>
+<stringAttribute key="selected_target_plugins" value="com.google.guava*15.0.0.v201403281430@default:default,com.google.guava*21.0.0.v20170206-1425@default:default,com.google.inject@default:default,com.ibm.icu@default:default,javax.inject@default:default,javax.xml@default:default,org.antlr.runtime*3.2.0.v201101311130@default:default,org.antlr.runtime*4.3.0.v201502022030@default:default,org.apache.commons.cli@default:default,org.apache.commons.io@default:default,org.apache.commons.lang@default:default,org.apache.commons.logging@default:default,org.apache.log4j@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filesystem.win32.x86_64@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.resources.win32.x86_64@default:false,org.eclipse.core.resources@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.emf.codegen.ecore@default:default,org.eclipse.emf.codegen@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.emf.mwe.core@default:default,org.eclipse.emf.mwe.utils@default:default,org.eclipse.emf.mwe2.runtime@default:default,org.eclipse.emf@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.jdt.core@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.jdt.launching@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi@-1:true,org.eclipse.text@default:default,org.eclipse.xpand@default:default,org.eclipse.xtend.lib.macro@default:default,org.eclipse.xtend.lib@default:default,org.eclipse.xtend.typesystem.emf@default:default,org.eclipse.xtend@default:default,org.eclipse.xtext.common.types@default:default,org.eclipse.xtext.ecore@default:default,org.eclipse.xtext.generator@default:default,org.eclipse.xtext.logging@default:false,org.eclipse.xtext.smap@default:default,org.eclipse.xtext.util@default:default,org.eclipse.xtext.xbase.lib@default:default,org.eclipse.xtext.xtext.generator@default:default,org.eclipse.xtext@default:default,org.hamcrest.core@default:default,org.junit@default:default,org.objectweb.asm*5.2.0.v20170126-0011@default:default,org.objectweb.asm*6.0.0.v20180116-1719@default:default"/>
<stringAttribute key="selected_workspace_plugins" value="org.eclipse.etrice.core.common@default:default,org.eclipse.etrice.core.etmap@default:default,org.eclipse.etrice.core.etphys@default:default,org.eclipse.etrice.core.fsm@default:default,org.eclipse.etrice.core.genmodel.fsm@default:default,org.eclipse.etrice.core.genmodel@default:default,org.eclipse.etrice.core.room@default:default,org.eclipse.etrice.generator.fsm@default:default,org.eclipse.etrice.generator.tests@default:default,org.eclipse.etrice.generator@default:default,org.eclipse.etrice.logging@default:false"/>
<booleanAttribute key="show_selected_only" value="true"/>
<booleanAttribute key="tracing" value="false"/>
diff --git a/tests/org.eclipse.etrice.generator.tests/src/org/eclipse/etrice/generator/base/TestDetailCodeTranslator.java b/tests/org.eclipse.etrice.generator.tests/src/org/eclipse/etrice/generator/base/TestDetailCodeTranslator.java
index ccfc8fa17..4161aca07 100644
--- a/tests/org.eclipse.etrice.generator.tests/src/org/eclipse/etrice/generator/base/TestDetailCodeTranslator.java
+++ b/tests/org.eclipse.etrice.generator.tests/src/org/eclipse/etrice/generator/base/TestDetailCodeTranslator.java
@@ -19,7 +19,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
-import java.util.ArrayList;
+import java.util.List;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.emf.ecore.EObject;
@@ -88,12 +88,12 @@ public class TestDetailCodeTranslator {
}
@Override
- public String getOperationText(Operation op, ArrayList<String> args, String orig) {
+ public String getOperationText(Operation op, List<String> args, String orig) {
return ">"+op.getName()+"("+getArgList(args)+")<";
}
@Override
- public String getInterfaceItemMessageText(AbstractInterfaceItem item, EObject abstractMsg, ArrayList<String> args, String index, String orig) {
+ public String getInterfaceItemMessageText(AbstractInterfaceItem item, EObject abstractMsg, List<String> args, String index, String orig) {
if (!(abstractMsg instanceof Message))
return orig;
@@ -110,7 +110,7 @@ public class TestDetailCodeTranslator {
return ">"+item.getName()+"."+msg.getName()+"<";
}
- private String getArgList(ArrayList<String> args) {
+ private String getArgList(List<String> args) {
StringBuilder result = new StringBuilder();
for (String string : args) {
result.append(string+", ");
@@ -145,11 +145,11 @@ public class TestDetailCodeTranslator {
}
/* (non-Javadoc)
- * @see org.eclipse.etrice.generator.base.ITranslationProvider#getInterfaceItemOperationText(org.eclipse.etrice.core.fsm.fSM.AbstractInterfaceItem, org.eclipse.etrice.core.room.PortOperation, java.util.ArrayList, java.lang.String)
+ * @see org.eclipse.etrice.generator.base.ITranslationProvider#getInterfaceItemOperationText(org.eclipse.etrice.core.fsm.fSM.AbstractInterfaceItem, org.eclipse.etrice.core.room.PortOperation, java.util.List, java.lang.String)
*/
@Override
public String getInterfaceItemOperationText(AbstractInterfaceItem item,
- PortOperation op, ArrayList<String> args, String orig) {
+ PortOperation op, List<String> args, String orig) {
return null;
}
}
diff --git a/tests/org.eclipse.etrice.ui.behavior.tests/org.eclipse.etrice.ui.behavior.tests.launch b/tests/org.eclipse.etrice.ui.behavior.tests/org.eclipse.etrice.ui.behavior.tests.launch
index 637fadb1f..1d7afa5bd 100644
--- a/tests/org.eclipse.etrice.ui.behavior.tests/org.eclipse.etrice.ui.behavior.tests.launch
+++ b/tests/org.eclipse.etrice.ui.behavior.tests/org.eclipse.etrice.ui.behavior.tests.launch
@@ -33,7 +33,7 @@
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.ui.behavior.tests"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-XX:PermSize=32m&#13;&#10;-XX:MaxPermSize=256m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.platform.ide"/>
<booleanAttribute key="run_in_ui_thread" value="true"/>
diff --git a/tests/org.eclipse.etrice.ui.structure.tests/org.eclipse.etrice.ui.structure.tests.launch b/tests/org.eclipse.etrice.ui.structure.tests/org.eclipse.etrice.ui.structure.tests.launch
index 0550a9654..7a69f51e9 100644
--- a/tests/org.eclipse.etrice.ui.structure.tests/org.eclipse.etrice.ui.structure.tests.launch
+++ b/tests/org.eclipse.etrice.ui.structure.tests/org.eclipse.etrice.ui.structure.tests.launch
@@ -32,7 +32,7 @@
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.etrice.ui.structure.tests"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-XX:PermSize=32m&#13;&#10;-XX:MaxPermSize=256m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea&#13;&#10;-Xmx512m&#13;&#10;-Xms128m&#13;&#10;-Dfile.encoding=UTF-8&#13;&#10;-Dosgi.requiredJavaVersion=1.5"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.platform.ide"/>
<booleanAttribute key="run_in_ui_thread" value="true"/>

Back to the top