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]