From c3f5b702085fce59a466d88176a4e74f450551d4 Mon Sep 17 00:00:00 2001
From: rschoene <rene.schoene@tu-dresden.de>
Date: Fri, 10 Feb 2023 15:30:37 +0100
Subject: [PATCH] Change token component directly in supertype if connected in
 any subtype.

---
 .../src/main/jastadd/Analysis.jrag            | 16 ++++++++++----
 .../src/main/jastadd/Intermediate.jadd        | 20 +++++++++++++++---
 .../src/main/jastadd/NameResolution.jrag      |  6 ++++--
 .../src/main/jastadd/Navigation.jrag          | 21 +++++++++++++++++++
 .../src/main/jastadd/RagConnect.relast        |  2 ++
 .../jastadd/ragconnect/tests/JavaTest.java    |  3 +++
 6 files changed, 59 insertions(+), 9 deletions(-)

diff --git a/ragconnect.base/src/main/jastadd/Analysis.jrag b/ragconnect.base/src/main/jastadd/Analysis.jrag
index 79f37b3..3b99df8 100644
--- a/ragconnect.base/src/main/jastadd/Analysis.jrag
+++ b/ragconnect.base/src/main/jastadd/Analysis.jrag
@@ -98,10 +98,18 @@ aspect Analysis {
   eq ContextFreeTypePortTarget.hasAttributeResetMethod() = false;
 
   // --- needProxyToken ---
-  syn boolean TokenComponent.needProxyToken() = !getDependencySourceDefinitionList().isEmpty() ||
-          getTokenPortTargetList().stream()
-                  .map(PortTarget::containingPortDefinition)
-                  .anyMatch(PortDefinition::shouldNotResetValue);
+  syn boolean TokenComponent.needProxyToken() {
+    for (Component comp : meOwnedByOthers()) {
+      TokenComponent tokenComp = comp.asTokenComponent();
+      if (!tokenComp.getDependencySourceDefinitionList().isEmpty() ||
+              tokenComp.getTokenPortTargetList().stream()
+                      .map(PortTarget::containingPortDefinition)
+                      .anyMatch(PortDefinition::shouldNotResetValue)) {
+        return true;
+      }
+    }
+    return false;
+  }
 
   // --- effectiveUsedAt ---
   coll Set<PortDefinition> MappingDefinition.effectiveUsedAt()
diff --git a/ragconnect.base/src/main/jastadd/Intermediate.jadd b/ragconnect.base/src/main/jastadd/Intermediate.jadd
index b847dc7..5cd7019 100644
--- a/ragconnect.base/src/main/jastadd/Intermediate.jadd
+++ b/ragconnect.base/src/main/jastadd/Intermediate.jadd
@@ -358,7 +358,14 @@ aspect MustacheRagConnect {
   eq ContextFreeTypePortTarget.impliedPortDefinitions() {
     JastAddList<PortDefinition> result = super.impliedPortDefinitions();
     PortDefinition containingDef = containingPortDefinition();
+    Set<TypeComponent> seenTypeComponents = new HashSet<>();
     for (TypeComponent typeComponent : getTypeDecl().occurencesInProductionRules()) {
+      // only process each once
+      if (seenTypeComponents.contains(typeComponent)) {
+        continue;
+      }
+      seenTypeComponents.add(typeComponent);
+
       List<PortDefinition> defsForTypeComponent = lookupGivenTypePortDefinitions(typeComponent);
       if (!defsForTypeComponent.stream().anyMatch(containingDef::matchesType)) {
         // there is no user-defined port definition for this typeComponent yet
@@ -630,9 +637,12 @@ aspect MustacheTokenComponent {
   syn String TokenComponent.javaType() = effectiveJavaTypeUse().prettyPrint();
 
   syn PortDefinition TokenComponent.normalTokenSendDef() {
-    for (PortTarget target : getTokenPortTargetList()) {
-      if (target.isTokenPortTarget() && target.containingPortDefinition().shouldNotResetValue()) {
-        return target.containingPortDefinition();
+    for (Component comp : meOwnedByOthers()) {
+      TokenComponent tokenComp = comp.asTokenComponent();
+      for (PortTarget target : tokenComp.getTokenPortTargetList()) {
+        if (target.isTokenPortTarget() && target.containingPortDefinition().shouldNotResetValue()) {
+          return target.containingPortDefinition();
+        }
       }
     }
     return null;
@@ -670,6 +680,10 @@ aspect MustacheTypeDecl {
   syn String TypeComponent.parentTypeName() = containingTypeDecl().getName();
   syn String TypeComponent.disconnectMethodName() {
     List<TypePortTarget> typePortTargets = getTypePortTargets();
+    while (typePortTargets.isEmpty() && getRealComponent() != null) {
+      // get for "real" typeComponent (of super-type) and use its getTypePortTargets
+      typePortTargets = getRealComponent().asTypeComponent().getTypePortTargets();
+    }
     if (typePortTargets.isEmpty()) {
       return "MISSING_PORT";
     } else {
diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag
index eb589e1..18a35f7 100644
--- a/ragconnect.base/src/main/jastadd/NameResolution.jrag
+++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag
@@ -197,7 +197,9 @@ aspect RelastNameResolution {
   syn nta JastAddList<Component> TypeDecl.allComponentsAsOwnedByMe() {
     JastAddList<Component> result = new JastAddList<>();
     for (Component comp : allComponents()) {
-      result.add(comp.treeCopy());
+      Component newComp = comp.treeCopy();
+      newComp.setRealComponent(comp);
+      result.add(newComp);
     }
     return result;
   }
@@ -214,7 +216,7 @@ aspect RelastNameResolution {
   syn boolean Component.matches(Component other) = false;
   eq TokenComponent.matches(Component other) {
     if (!other.isTokenComponent()) { return false; }
-    return getName().equals(other.getName()) && getJavaTypeUse().prettyPrint().equals(other.asTokenComponent().getJavaTypeUse().prettyPrint());
+    return getName().equals(other.getName()) && (getJavaTypeUse() == null && other.asTokenComponent().getJavaTypeUse() == null || getJavaTypeUse().prettyPrint().equals(other.asTokenComponent().getJavaTypeUse().prettyPrint()));
   }
   eq TypeComponent.matches(Component other) = matchesNameAndType(other);
   eq NormalComponent.matches(Component other) {
diff --git a/ragconnect.base/src/main/jastadd/Navigation.jrag b/ragconnect.base/src/main/jastadd/Navigation.jrag
index 8b23c00..ffa4596 100644
--- a/ragconnect.base/src/main/jastadd/Navigation.jrag
+++ b/ragconnect.base/src/main/jastadd/Navigation.jrag
@@ -175,4 +175,25 @@ aspect RagConnectNavigation {
 
   // --- isListComponent --- (defined in PP, but only on TypeComponent)
   syn boolean Component.isListComponent() = false;
+
+  syn Set<Component> Component.meOwnedByOthers() {
+    Set<Component> result = new HashSet<>();
+    Deque<TypeDecl> todo = new ArrayDeque<>();
+    todo.add(containingTypeDecl());
+    while (!todo.isEmpty()) {
+      TypeDecl current = todo.pop();
+      todo.addAll(current.getSubTypeList());
+
+      for (Component comp : current.allComponentsAsOwnedByMe()) {
+        if (comp.matches(this)) {
+          result.add(comp);
+        }
+      }
+    }
+    return result;
+  }
+}
+aspect RelastNavigation {
+  // TODO only token-components from the nta "owned-by-me" must be added to Program.allTokenComponents
+  //TypeDecl contributes nta allComponentsAsOwnedByMe() to Program.allTokenComponents();
 }
diff --git a/ragconnect.base/src/main/jastadd/RagConnect.relast b/ragconnect.base/src/main/jastadd/RagConnect.relast
index 7282bb3..60f0849 100644
--- a/ragconnect.base/src/main/jastadd/RagConnect.relast
+++ b/ragconnect.base/src/main/jastadd/RagConnect.relast
@@ -47,3 +47,5 @@ Configuration ::=
 <EvaluationCounter:boolean>
 <ExperimentalJastAdd329:boolean>;
 rel Configuration.RootNode -> TypeDecl ;
+
+rel Component.RealComponent? -> Component ;
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/JavaTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/JavaTest.java
index 81d2817..dfac385 100644
--- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/JavaTest.java
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/JavaTest.java
@@ -150,7 +150,10 @@ public class JavaTest extends RagConnectTest {
 
     model.ragconnectJavaPush(TOPIC_RECEIVE_NTA, ExposingASTNode.INSTANCE.aToBytes(createA("12")));
     checker.put(TOPIC_RECEIVE_NTA, "12").check();
+  }
 
+  @AfterEach
+  public void printEvaluationSummary() {
     System.out.println(model.ragconnectEvaluationCounterSummary());
   }
 
-- 
GitLab