mbeckerle commented on code in PR #1366:
URL: https://github.com/apache/daffodil/pull/1366#discussion_r1852504166


##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it
+          // we don't need the check for what it carries since all properties 
on the type are shared
+          // by the element using it
+          std.propCache.foreach(kv => ele.propCache.put(kv._1, kv._2))
+          // copy the used properties from the element to the type
+          ele.propCache.foreach(kv =>
+            if (std.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+              // only add the used properties that the simple type carries, 
not any local element properties that aren't shared
+              std.propCache.put(kv._1, kv._2)
+            }
+          )
+          // propagate through the element's simple type base chain
+          std.propagateUsedProperties
+        }
+      case t: SimpleTypeDefBase => {
+        val ost = t.optReferredToComponent
+        ost.collect { case st: SimpleTypeDefBase =>
+          // propagate from type to base type
+          t.propCache.foreach { kv =>
+            {
+              if (st.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+                st.propCache.put(kv._1, kv._2)
+              }
+            }
+          }
+          // propagate through all bases
+          st.bases.collect { case stdb: SimpleTypeDefBase =>
+            stdb.propagateUsedProperties
+          }
+        }
+      }
+      case _ => // do nothing
+    }
+  }
+
+  /**
+   * Used to look for DFDL properties on Annotated Schema Components that
+   * have not been accessed and record it as a warning. This function uses the
+   * property cache state to determine which properties have been accessed, so
+   * this function must only be called after all property accesses are complete
+   * (e.g. schema compilation has finished) to ensure there are no false
+   * positives.
+   */
+  final lazy val checkUnusedProperties: Unit = {
+    // Get the properties defined on this component and what it refers to
+    val localProps = formatAnnotation.justThisOneProperties
+    val refProps = optReferredToComponent
+      .map { _.formatAnnotation.justThisOneProperties }
+      .getOrElse(Map.empty)
+
+    val usedProperties = propCache

Review Comment:
   Not in this file, but in the files where the PropCache type is defined you 
need to add comments there that the PropCache plays two roles in different 
phases of the compilation. First for property lookups, second for determining 
which properties are present, but unused. 
   
   You need to explain, there, that these two uses are incompatible. The first 
use must be over. Then the caches are repurposed for the second algorithm. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it
+          // we don't need the check for what it carries since all properties 
on the type are shared
+          // by the element using it
+          std.propCache.foreach(kv => ele.propCache.put(kv._1, kv._2))
+          // copy the used properties from the element to the type
+          ele.propCache.foreach(kv =>
+            if (std.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+              // only add the used properties that the simple type carries, 
not any local element properties that aren't shared
+              std.propCache.put(kv._1, kv._2)
+            }
+          )
+          // propagate through the element's simple type base chain
+          std.propagateUsedProperties

Review Comment:
   An additional thought: If you can walk in this "referencers before 
referenced" order by way of the Root.refMap, starting from the leaf simple 
types, the global group defs, and the global element defs (having complex 
type), then, for each ASC you can compute a separate value which is the set of 
all properties used. 
   
   That is, you don't need to be doing put() calls on the propCache. You can 
read the propCache, but fill in a separate structure of just the properties 
that are used so as to isolate from those that are unused. This could be a 
separate structure which holds only properties in the referencer's propCache 
that are NOT found in the referenced object's propCache, so that this new 
structure is not redundant with the contents of the propCache. 
   
   This would be cleaner and much more space efficient than reusing the 
propCache data structure in this way that reads it but also modifies it. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types

Review Comment:
   This comment says what we do, but not why. 
   
   Start this comment by saying this is a central part of the algorithm by 
which we identify properties that are present, but not used. 
   
   The overall algorithm is expressed in multiple places. This part handles the 
propagation of properties from referencer to referenced object when property 
combining occurs. The rest of the algorithm is then just traversing every 
AnnocatedSchemaComponent to see what properties are present on them that do not 
appear in the propCache. This overall explaining of the algoirthm maybe doesn't 
go on this lazy val but elsewhere at the top level where this gets called 
perhaps. 
   
   It is also important to point out that this is clobbering the property 
caches, making them subsequently unusable for their initial property lookup 
uses. Hence, this must be done in a pass that happens only after all other 
schema compilation involving properties is complete. 
   



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it
+          // we don't need the check for what it carries since all properties 
on the type are shared
+          // by the element using it
+          std.propCache.foreach(kv => ele.propCache.put(kv._1, kv._2))
+          // copy the used properties from the element to the type
+          ele.propCache.foreach(kv =>
+            if (std.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+              // only add the used properties that the simple type carries, 
not any local element properties that aren't shared
+              std.propCache.put(kv._1, kv._2)
+            }
+          )
+          // propagate through the element's simple type base chain
+          std.propagateUsedProperties

Review Comment:
   This propagation down the chain is the problematic part of this algorithm. 
One is potentially going to walk the length of this chain many more times than 
is necessary, and not by some small amount. 
   
   Consider trying this:
   
   Take the list of all annotated schema comopnents ASCs, and divide it up into 
lists of 
   
   - all global group defs
   - all global element defs
   
   For all global group defs, process them by using Root.refMap to find all 
referencing global group refs and pull the propCache entries from there over 
onto the global group def. 
   
   For all global element decls, process them by using Root.refMap to find all 
element refs and pull the propCache entries from there over onto the global 
element decl. 
   
   For all global simple type defs, process them by using Root.refMap to find 
all _elements_ that reference them and pull the propCache entries from there 
onto the globalSimpleType def. 
   
   For all _local_ simple type defs, process them by pulling the propCache 
entries from their enclosing element onto them. 
   
   This leaves only global simple type defs with references to them from other 
simple type defs (which can be global or local). 
   
   These need to be processed in a specific order to avoid redundant 
processing. Create a table of "done" global simple type defs, initially empty. 
   
   Then start from all global simple type defs whose base is a primitive type 
(call these leaf simple type defs). 
   Process each of these as follows.
   
   Use Root.refMap to find the other simple type defs which reference this one. 
   
   If they are found in the "done" table, pull their properties onto this 
simple type. 
   
   If they are not found in the "done" table, recursively process them, (they 
will become "done") then pull their properties onto this simple type. 
   
   When all the simple type defs which reference this one are "done" and their 
properties have been pulled onto this one, add this simple type def to the 
"done" table, and go on to the next in the list. 
   
   That is a walk which visits all referencers first before any referenced, so 
will propagate the propCache entries visiting each simple type def exactly 
once. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala:
##########
@@ -540,8 +540,25 @@ final class SchemaSet private (
     .flatMap(_.defineVariables)
     .union(predefinedVars)
 
+  /**
+   * propagate used properties through AnnotatedSchemaComponent

Review Comment:
   Add that this is part of the algorithm for identifying properties that are 
present, but unused. 
   
   Add that not only must this be done after compilation is complete, but that 
it repurposes the propCaches which are no longer usable for property lookups 
after this is done. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaSet.scala:
##########
@@ -540,8 +540,25 @@ final class SchemaSet private (
     .flatMap(_.defineVariables)
     .union(predefinedVars)
 
+  /**
+   * propagate used properties through AnnotatedSchemaComponent
+   * must be done after compilation is complete to ensure all properties
+   * that are used are accounted for
+   */
+  private lazy val propagateUsedProperties = {
+    root.allComponents.collect { case asc: AnnotatedSchemaComponent =>
+      asc.propagateUsedProperties

Review Comment:
   Unless you do something to walk this in a sensible order, this is a 
computationally expensive O(n^2) or worse algorithm.  
   
   See other comment above about how to do this in a "pull" style that visits 
each ASC exactly once. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With

Review Comment:
   Grammar "its" => "it has".  Some rephrasing and splitting into paragraphs 
will make this clearer. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it
+          // we don't need the check for what it carries since all properties 
on the type are shared
+          // by the element using it
+          std.propCache.foreach(kv => ele.propCache.put(kv._1, kv._2))
+          // copy the used properties from the element to the type
+          ele.propCache.foreach(kv =>
+            if (std.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+              // only add the used properties that the simple type carries, 
not any local element properties that aren't shared

Review Comment:
   The only properties I know on simple elements that can only be on the 
element, not the type, are dfdl:inputValueCalc and dfdl:outputValueCalc. Those 
can't be unused. 
   
   So when this comment says to only add the used properties that the simple 
type carries, not any local element properties that aren't "shared". What does 
"shared" mean? I also don't see any logic about removing any "uncarried" 
properties. 



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it

Review Comment:
   I don't understand why you have to copy from the simple type back to the 
element. Please add comment explaining why this is needed. 
   
   I would think this would go only from element to type (to base type, etc.)



##########
daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/AnnotatedSchemaComponent.scala:
##########
@@ -377,6 +378,118 @@ trait AnnotatedSchemaComponent
     val res = schemaDocument.formatAnnotation.formatChain
     res
   }
+
+  /**
+   * Used to propagate used properties through all element/group references, 
element declarations
+   * and simple types. This is necessary because we have elements being 
referenced
+   * by multiple element ref, where the first element gets its propCache 
populated with
+   * the properties its used, and the second element doesn't because of 
sharing. With
+   * this val, we copy used properties from element refs to elements, group 
refs to groups,
+   * from elements to their simple types, if the simple type is annotated with 
the property,
+   * and from simple types to their base types
+   */
+  final lazy val propagateUsedProperties: Unit = {
+    this match {
+      case ref: GroupRef =>
+        val groupBeingReferenced = ref.groupDef
+        // if the groupBeingReferenced carries the property then add the 
property to its propCache
+        ref.propCache.foreach { kv =>
+          if 
(groupBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+            groupBeingReferenced.propCache.put(kv._1, kv._2)
+          }
+        }
+      case ref: AbstractElementRef =>
+        val elementBeingReferenced = ref.optReferredToComponent.get
+        ref.propCache.foreach(kv =>
+          // if the elementBeingReferenced or its simpleType carries the 
property
+          // then add the property to its propCache
+          if (
+            
elementBeingReferenced.formatAnnotation.justThisOneProperties.contains(kv._1)
+            || elementBeingReferenced.optSimpleType.exists {
+              case std: SimpleTypeDefBase =>
+                std.formatAnnotation.justThisOneProperties.contains(kv._1)
+              case _ => false
+            }
+          ) {
+            // only add the used properties that the elementBeingReferenced or 
its simple type carries,
+            // not any local properties that aren't shared
+            elementBeingReferenced.propCache.put(kv._1, kv._2)
+            // propagate used properties from element to its simpletype and 
vice versa
+            elementBeingReferenced.propagateUsedProperties
+          }
+        )
+      case ele: ElementDeclMixin =>
+        val ost = ele.optSimpleType
+        ost.collect { case std: SimpleTypeDefBase =>
+          // if the type has used properties transfer it to the element that's 
using it
+          // we don't need the check for what it carries since all properties 
on the type are shared
+          // by the element using it
+          std.propCache.foreach(kv => ele.propCache.put(kv._1, kv._2))
+          // copy the used properties from the element to the type
+          ele.propCache.foreach(kv =>
+            if (std.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+              // only add the used properties that the simple type carries, 
not any local element properties that aren't shared
+              std.propCache.put(kv._1, kv._2)
+            }
+          )
+          // propagate through the element's simple type base chain
+          std.propagateUsedProperties
+        }
+      case t: SimpleTypeDefBase => {
+        val ost = t.optReferredToComponent
+        ost.collect { case st: SimpleTypeDefBase =>
+          // propagate from type to base type
+          t.propCache.foreach { kv =>
+            {
+              if (st.formatAnnotation.justThisOneProperties.contains(kv._1)) {
+                st.propCache.put(kv._1, kv._2)
+              }
+            }
+          }
+          // propagate through all bases
+          st.bases.collect { case stdb: SimpleTypeDefBase =>
+            stdb.propagateUsedProperties
+          }
+        }
+      }
+      case _ => // do nothing
+    }
+  }
+
+  /**
+   * Used to look for DFDL properties on Annotated Schema Components that
+   * have not been accessed and record it as a warning. This function uses the
+   * property cache state to determine which properties have been accessed, so
+   * this function must only be called after all property accesses are complete
+   * (e.g. schema compilation has finished) to ensure there are no false
+   * positives.
+   */
+  final lazy val checkUnusedProperties: Unit = {

Review Comment:
   Add to comment that the propagateUsedProperties must be called on all 
AnnotatedSchemaComponents before this will work properly. 
   
   Add that this is not a recursive walk. It identifies and issues warnings 
about unaccessed properties on just one AnnotatedSchemaComponent. 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to