Repository: bpmn-io/bpmnlint (js)

Issue:
Adjust no-bpmndi rule to also catch messageFlows without visual representation
__Is your feature request related to a problem? Please describe__

The current implementation of the no-bpmndi rule seems to not catch the case where visual representation of a messageFlow is missing. Example:

```
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:modeler="http://camunda.org/schema/modeler/1.0" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_0o87biy" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.0.0" camunda:diagramRelationId="c3dfa14f-62b5-469a-99c2-eea2474361c4">
  <bpmn:collaboration id="Collaboration_03svvle">
    <bpmn:participant id="Participant_19296tk" name="Camunda" processRef="optimizeRelease" />
    <bpmn:messageFlow id="Flow_02zjpio" />
    <bpmn:messageFlow id="Flow_02fgw1s" />
    <bpmn:messageFlow id="Flow_1tfrum1" />
    <bpmn:messageFlow id="Flow_0j117b6" />
    <bpmn:messageFlow id="Flow_1p82kq7" />
    <bpmn:messageFlow id="Flow_12ujv1h" />
    <bpmn:messageFlow id="Flow_1ud5vc7" />
    <bpmn:messageFlow id="Flow_1pgfh6h" />
    <bpmn:messageFlow id="Flow_1n7tpee" />
  </bpmn:collaboration>
  <bpmn:process id="optimizeRelease" name="Optimize Release Process" isExecutable="true">
    <bpmn:laneSet id="LaneSet_0vxjmiv">
      <bpmn:lane id="other-lane" name="Other">
        <bpmn:flowNodeRef>Event_14w2go1</bpmn:flowNodeRef>
      </bpmn:lane>
      <bpmn:lane id="product-manager-lane" name="Product Manager">
        <bpmn:flowNodeRef>Event_14w2go1</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>Start_1</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>Event_14a4ede</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>add-cat-pic</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:endEvent id="Event_14w2go1" />
    <bpmn:sequenceFlow id="Flow_1yoohwu" sourceRef="Start_1" targetRef="add-cat-pic" />
    <bpmn:startEvent id="Start_1" name="At beginning of release month">
      <bpmn:outgoing>Flow_1yoohwu</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:endEvent id="Event_14a4ede">
      <bpmn:incoming>Flow_1opo8o2</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="Flow_1opo8o2" sourceRef="add-cat-pic" targetRef="Event_14a4ede" />
    <bpmn:serviceTask id="add-cat-pic" name="Add cat pic of the month">
      <bpmn:incoming>Flow_1yoohwu</bpmn:incoming>
      <bpmn:outgoing>Flow_1opo8o2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:textAnnotation id="TextAnnotation_1m4hg8y">
      <bpmn:text>Configure timer cycle</bpmn:text>
    </bpmn:textAnnotation>
    <bpmn:association id="Association_1srpwa7" sourceRef="Start_1" targetRef="TextAnnotation_1m4hg8y" />
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_03svvle">
      <bpmndi:BPMNShape id="Participant_19296tk_di" bpmnElement="Participant_19296tk" isHorizontal="true">
        <dc:Bounds x="175" y="45" width="4310" height="1085" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Lane_1hg66tj_di" bpmnElement="product-manager-lane" isHorizontal="true">
        <dc:Bounds x="205" y="497.5" width="4280" height="632.5" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Lane_1i9ntug_di" bpmnElement="other-lane" isHorizontal="true">
        <dc:Bounds x="205" y="45" width="4280" height="452.5" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Flow_1opo8o2_di" bpmnElement="Flow_1opo8o2">
        <di:waypoint x="495" y="625" />
        <di:waypoint x="622" y="625" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="Flow_1yoohwu_di" bpmnElement="Flow_1yoohwu">
        <di:waypoint x="273" y="625" />
        <di:waypoint x="395" y="625" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Event_14w2go1_di" bpmnElement="Event_14w2go1">
        <dc:Bounds x="4412" y="477" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="4375" y="520" width="71" height="14" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_06qyu4n_di" bpmnElement="Start_1">
        <dc:Bounds x="237" y="607" width="36" height="36" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="219" y="650" width="74" height="27" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Event_14a4ede_di" bpmnElement="Event_14a4ede">
        <dc:Bounds x="622" y="607" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="Activity_1gbnx01_di" bpmnElement="add-cat-pic">
        <dc:Bounds x="395" y="585" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="TextAnnotation_1m4hg8y_di" bpmnElement="TextAnnotation_1m4hg8y">
        <dc:Bounds x="225" y="525" width="100" height="39" />
        <bpmndi:BPMNLabel />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="Association_1srpwa7_di" bpmnElement="Association_1srpwa7">
        <di:waypoint x="259" y="608" />
        <di:waypoint x="269" y="564" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>
```



__Describe the solution you'd like__

no-bpmndi rule should error also for messageFlows without visual representation


__Describe alternatives you've considered__

seperate new rule


__Additional context__

<!-- Add any other context or screenshots about the feature request here. -->


Pull request:
feat(no-bpmndi): detect messageflows without di
closes #84

<!--

Thanks for creating this pull request!

Please make sure to link the issue you are closing as "Closes #issueNr". 
This helps us to understand the context of this PR.

-->


Patch:
diff --git a/rules/no-bpmndi.js b/rules/no-bpmndi.js
index eef0aa2..4cb35ed 100644
--- a/rules/no-bpmndi.js
+++ b/rules/no-bpmndi.js
@@ -53,7 +53,6 @@ module.exports = function() {
  */
 function getAllBpmnElements(rootElements) {
   return flatten(rootElements.map((rootElement) => {
-
     const laneSet =
       rootElement.laneSets && rootElement.laneSets[0] || rootElement.childLaneSet;
 
@@ -66,13 +65,15 @@ function getAllBpmnElements(rootElements) {
     // * nested laneSets
     // * childLaneSets
     // * nested childLaneSets
+    // * messageFlows
     const elements = flatten([].concat(
       rootElement.flowElements || [],
       (rootElement.flowElements && getAllBpmnElements(rootElement.flowElements.filter(hasFlowElements))) || [],
       rootElement.participants || [],
       rootElement.artifacts || [],
       laneSet && laneSet.lanes || [],
-      laneSet && laneSet.lanes && getAllBpmnElements(laneSet.lanes.filter(hasChildLaneSet)) || []
+      laneSet && laneSet.lanes && getAllBpmnElements(laneSet.lanes.filter(hasChildLaneSet)) || [],
+      rootElement.messageFlows || []
     ));
 
     if (elements.length > 0) {


Test patch:
diff --git a/test/rules/no-bpmndi.js b/test/rules/no-bpmndi.js
index d19b8f0..c47c0f8 100644
--- a/test/rules/no-bpmndi.js
+++ b/test/rules/no-bpmndi.js
@@ -47,6 +47,9 @@ RuleTester.verify('no-bpmndi', rule, {
     },
     {
       moddleElement: readModdle(__dirname + '/no-bpmndi/valid-no-lanes.bpmn')
+    },
+    {
+      moddleElement: readModdle(__dirname + '/no-bpmndi/valid-message-flow.bpmn')
     }
   ],
   invalid: [
@@ -154,6 +157,13 @@ RuleTester.verify('no-bpmndi', rule, {
         id: 'lane7',
         message: 'Element is missing bpmndi'
       }
+    },
+    {
+      moddleElement: readModdle(__dirname + '/no-bpmndi/invalid-message-flow.bpmn'),
+      report: {
+        id: 'danglingMessageFlow',
+        message: 'Element is missing bpmndi'
+      }
     }
   ]
 });
diff --git a/test/rules/no-bpmndi/invalid-message-flow.bpmn b/test/rules/no-bpmndi/invalid-message-flow.bpmn
new file mode 100644
index 0000000..34dc55f
--- /dev/null
+++ b/test/rules/no-bpmndi/invalid-message-flow.bpmn
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0mq9vjp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.0.0">
+  <bpmn:collaboration id="Collaboration_13yw7y6">
+    <bpmn:participant id="Participant_0ld5ubm" processRef="Process_1iy30yp" />
+    <bpmn:participant id="Participant_0neg2l0" processRef="Process_0o2afw0" />
+    <bpmn:messageFlow id="danglingMessageFlow" />
+  </bpmn:collaboration>
+  <bpmn:process id="Process_1iy30yp" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1">
+      <bpmn:outgoing>Flow_12s72gv</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:task id="Activity_0z1ovrr">
+      <bpmn:incoming>Flow_12s72gv</bpmn:incoming>
+      <bpmn:outgoing>Flow_05ybtxp</bpmn:outgoing>
+    </bpmn:task>
+    <bpmn:sequenceFlow id="Flow_12s72gv" sourceRef="StartEvent_1" targetRef="Activity_0z1ovrr" />
+    <bpmn:endEvent id="Event_1inu5iv">
+      <bpmn:incoming>Flow_05ybtxp</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_05ybtxp" sourceRef="Activity_0z1ovrr" targetRef="Event_1inu5iv" />
+  </bpmn:process>
+  <bpmn:process id="Process_0o2afw0" isExecutable="false">
+    <bpmn:startEvent id="Event_1n4y968">
+      <bpmn:outgoing>Flow_0jcico3</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:task id="Activity_1wmpm6n">
+      <bpmn:incoming>Flow_0jcico3</bpmn:incoming>
+      <bpmn:outgoing>Flow_0wtukph</bpmn:outgoing>
+    </bpmn:task>
+    <bpmn:sequenceFlow id="Flow_0jcico3" sourceRef="Event_1n4y968" targetRef="Activity_1wmpm6n" />
+    <bpmn:endEvent id="Event_1mt0zfh">
+      <bpmn:incoming>Flow_0wtukph</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_0wtukph" sourceRef="Activity_1wmpm6n" targetRef="Event_1mt0zfh" />
+  </bpmn:process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_13yw7y6">
+      <bpmndi:BPMNShape id="Participant_0ld5ubm_di" bpmnElement="Participant_0ld5ubm" isHorizontal="true">
+        <dc:Bounds x="129" y="70" width="600" height="250" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_12s72gv_di" bpmnElement="Flow_12s72gv">
+        <di:waypoint x="215" y="177" />
+        <di:waypoint x="270" y="177" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_05ybtxp_di" bpmnElement="Flow_05ybtxp">
+        <di:waypoint x="370" y="177" />
+        <di:waypoint x="432" y="177" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="179" y="159" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0z1ovrr_di" bpmnElement="Activity_0z1ovrr">
+        <dc:Bounds x="270" y="137" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1inu5iv_di" bpmnElement="Event_1inu5iv">
+        <dc:Bounds x="432" y="159" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Participant_0neg2l0_di" bpmnElement="Participant_0neg2l0" isHorizontal="true">
+        <dc:Bounds x="129" y="350" width="600" height="250" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_0jcico3_di" bpmnElement="Flow_0jcico3">
+        <di:waypoint x="208" y="490" />
+        <di:waypoint x="260" y="490" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0wtukph_di" bpmnElement="Flow_0wtukph">
+        <di:waypoint x="360" y="490" />
+        <di:waypoint x="412" y="490" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_1n4y968_di" bpmnElement="Event_1n4y968">
+        <dc:Bounds x="172" y="472" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1wmpm6n_di" bpmnElement="Activity_1wmpm6n">
+        <dc:Bounds x="260" y="450" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1mt0zfh_di" bpmnElement="Event_1mt0zfh">
+        <dc:Bounds x="412" y="472" width="36" height="36" />
+      </bpmndi:BPMNShape>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>
diff --git a/test/rules/no-bpmndi/valid-message-flow.bpmn b/test/rules/no-bpmndi/valid-message-flow.bpmn
new file mode 100644
index 0000000..a4693ab
--- /dev/null
+++ b/test/rules/no-bpmndi/valid-message-flow.bpmn
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0mq9vjp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Cloud" modeler:executionPlatformVersion="8.0.0">
+  <bpmn:collaboration id="Collaboration_13yw7y6">
+    <bpmn:participant id="Participant_0ld5ubm" processRef="Process_1iy30yp" />
+    <bpmn:participant id="Participant_0neg2l0" processRef="Process_0o2afw0" />
+    <bpmn:messageFlow id="Flow_03us99l" sourceRef="Activity_1wmpm6n" targetRef="Activity_0z1ovrr" />
+  </bpmn:collaboration>
+  <bpmn:process id="Process_1iy30yp" isExecutable="true">
+    <bpmn:startEvent id="StartEvent_1">
+      <bpmn:outgoing>Flow_12s72gv</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:task id="Activity_0z1ovrr">
+      <bpmn:incoming>Flow_12s72gv</bpmn:incoming>
+      <bpmn:outgoing>Flow_05ybtxp</bpmn:outgoing>
+    </bpmn:task>
+    <bpmn:sequenceFlow id="Flow_12s72gv" sourceRef="StartEvent_1" targetRef="Activity_0z1ovrr" />
+    <bpmn:endEvent id="Event_1inu5iv">
+      <bpmn:incoming>Flow_05ybtxp</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_05ybtxp" sourceRef="Activity_0z1ovrr" targetRef="Event_1inu5iv" />
+  </bpmn:process>
+  <bpmn:process id="Process_0o2afw0" isExecutable="false">
+    <bpmn:startEvent id="Event_1n4y968">
+      <bpmn:outgoing>Flow_0jcico3</bpmn:outgoing>
+    </bpmn:startEvent>
+    <bpmn:task id="Activity_1wmpm6n">
+      <bpmn:incoming>Flow_0jcico3</bpmn:incoming>
+      <bpmn:outgoing>Flow_0wtukph</bpmn:outgoing>
+    </bpmn:task>
+    <bpmn:sequenceFlow id="Flow_0jcico3" sourceRef="Event_1n4y968" targetRef="Activity_1wmpm6n" />
+    <bpmn:endEvent id="Event_1mt0zfh">
+      <bpmn:incoming>Flow_0wtukph</bpmn:incoming>
+    </bpmn:endEvent>
+    <bpmn:sequenceFlow id="Flow_0wtukph" sourceRef="Activity_1wmpm6n" targetRef="Event_1mt0zfh" />
+  </bpmn:process>
+  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
+    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_13yw7y6">
+      <bpmndi:BPMNShape id="Participant_0ld5ubm_di" bpmnElement="Participant_0ld5ubm" isHorizontal="true">
+        <dc:Bounds x="129" y="70" width="600" height="250" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_12s72gv_di" bpmnElement="Flow_12s72gv">
+        <di:waypoint x="215" y="177" />
+        <di:waypoint x="270" y="177" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_05ybtxp_di" bpmnElement="Flow_05ybtxp">
+        <di:waypoint x="370" y="177" />
+        <di:waypoint x="432" y="177" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
+        <dc:Bounds x="179" y="159" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_0z1ovrr_di" bpmnElement="Activity_0z1ovrr">
+        <dc:Bounds x="270" y="137" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1inu5iv_di" bpmnElement="Event_1inu5iv">
+        <dc:Bounds x="432" y="159" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Participant_0neg2l0_di" bpmnElement="Participant_0neg2l0" isHorizontal="true">
+        <dc:Bounds x="129" y="350" width="600" height="250" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_0jcico3_di" bpmnElement="Flow_0jcico3">
+        <di:waypoint x="208" y="490" />
+        <di:waypoint x="260" y="490" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNEdge id="Flow_0wtukph_di" bpmnElement="Flow_0wtukph">
+        <di:waypoint x="360" y="490" />
+        <di:waypoint x="412" y="490" />
+      </bpmndi:BPMNEdge>
+      <bpmndi:BPMNShape id="Event_1n4y968_di" bpmnElement="Event_1n4y968">
+        <dc:Bounds x="172" y="472" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Activity_1wmpm6n_di" bpmnElement="Activity_1wmpm6n">
+        <dc:Bounds x="260" y="450" width="100" height="80" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNShape id="Event_1mt0zfh_di" bpmnElement="Event_1mt0zfh">
+        <dc:Bounds x="412" y="472" width="36" height="36" />
+      </bpmndi:BPMNShape>
+      <bpmndi:BPMNEdge id="Flow_03us99l_di" bpmnElement="Flow_03us99l">
+        <di:waypoint x="310" y="450" />
+        <di:waypoint x="310" y="217" />
+      </bpmndi:BPMNEdge>
+    </bpmndi:BPMNPlane>
+  </bpmndi:BPMNDiagram>
+</bpmn:definitions>