codeconsole commented on code in PR #16772:
URL: https://github.com/apache/grails-core/pull/16772#discussion_r4384027521


##########
grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy:
##########
@@ -380,15 +380,30 @@ class NavigableMap implements Map<String, Object>, 
Cloneable {
     }
 
     private void flattenKeys(Map<? extends Object, Object> flatConfig, Map 
currentMap, List<String> path, boolean forceStrings) {
+        flattenKeys(flatConfig, currentMap, path, forceStrings, this, 0)
+    }
+
+    /**
+     * Writes the entries of a map under their names. An entry of a map 
written by map subscripts, such as {@code /api/**}
+     * of {@code app.routes[/api/**]}, is written under the bracketed flat key 
that the nearest enclosing nested map holds
+     * for it, relative to that map, and so is skipped here, where it would be 
written again under the dotted name
+     * {@code app.routes./api/**}, which Spring Boot binds as {@code api}; so 
is a dotted flat key of the map itself that
+     * names the same entry, as a merge of a block holding the entry writes 
{@code app.routes./api/**} at the root.
+     */
+    private void flattenKeys(Map<? extends Object, Object> flatConfig, Map 
currentMap, List<String> path, boolean forceStrings,
+                             NavigableMap owner, int ownerDepth) {
+        NavigableMap childOwner = currentMap instanceof NavigableMap ? 
(NavigableMap) currentMap : owner
+        int childOwnerDepth = currentMap instanceof NavigableMap ? path.size() 
: ownerDepth
+        List<String> relativePath = path.subList(ownerDepth, path.size())
         currentMap.each { key, value ->
             String stringKey = String.valueOf(key)
-            if (value != null) {
+            if (value != null && !isNamedInBrackets(owner, relativePath, 
stringKey)) {

Review Comment:
   Fixed in bedc5780e3. The walk now skips an entry only when its bracketed key 
exports every name and value the entry would. Otherwise the entry is exported 
under its own name, as on 7.0.x:
   
   - With your `routes[api]` merge, `routes[api]` holds only `enabled`, so 
`routes.api.target` and `routes.api.enabled` are exported beside 
`routes[api].enabled`. Binder binds `routes` as `[api: [target: 
'http://localhost', enabled: 'true']]`.
   - After `app.routes[k]` = null and then `app.routes.k` = `'new'`, 
`app.routes.k=new` is exported.
   
   The shapes this PR is for still export only the bracketed key:
   
   - a map written in brackets, such as `app.routes[api]: [target: …, enabled: 
…]`
   - lists written below a bracket, such as 
`grails.cors.mappings[/api/**].allowedOrigins[0]`
   - the YAML rows from before
   
   At the root, a dotted key such as `app.routes./api/**` is still skipped 
whenever a bracketed key names it, because the walk of the nested maps exports 
that entry with its current value. Comparing its value instead would export a 
stale one. After `app.routes.k` = `'old'` and then `app.routes[k]` = `'new'`, 
the root keeps `app.routes.k` on `'old'`.
   
   One shape stays as on 7.0.x. After `app.routes[k]` = `'old'` and then 
`app.routes.k` = `'new'`, the bracketed key keeps `'old'`, so both 
`app.routes[k]=old` and `app.routes.k=new` are exported. 
`config['app.routes[k]']` reads `'old'` there too; that alias is left by the 
merge, not the export.
   
   Tests:
   - `ConfigMapSpec` covers your two cases and that one, checking that every 
field is exported with the value the nested maps hold. It also checks that the 
map and list shapes are exported once.
   - `PropertySourcesConfigSpec` binds your two cases with `Binder`.
   
   The rows for your cases fail at 0db23f17a4; the rows for the bracketed 
shapes pass there too and are there so that a stricter comparison can't bring 
the duplicate back. 67e841d524 merges 7.0.x in.
   



-- 
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