You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/07/11 23:27:09 UTC

[groovy] branch GROOVY-9631 updated (4653c40 -> 007101d)

This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a change to branch GROOVY-9631
in repository https://gitbox.apache.org/repos/asf/groovy.git.


 discard 4653c40  Replace `Index` and `MethodIndex` with `IndexMap`
     new 007101d  Replace `Index` and `MethodIndex` with `IndexMap`

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (4653c40)
            \
             N -- N -- N   refs/heads/GROOVY-9631 (007101d)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/main/java/groovy/lang/MetaClassImpl.java               | 2 +-
 subprojects/groovy-json/src/spec/test/json/JsonTest.groovy | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)


[groovy] 01/01: Replace `Index` and `MethodIndex` with `IndexMap`

Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch GROOVY-9631
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 007101d76e4eec7794d5349628690930e0dc599e
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Jul 12 07:26:41 2020 +0800

    Replace `Index` and `MethodIndex` with `IndexMap`
---
 src/main/java/groovy/lang/MetaClassImpl.java       | 121 ++++++++++++---------
 .../groovy-json/src/spec/test/json/JsonTest.groovy |   4 +-
 .../test/groovy/groovy/json/JsonOutputTest.groovy  |  28 ++---
 3 files changed, 84 insertions(+), 69 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java
index f26af35..db6cc3e 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -102,6 +102,7 @@ import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -147,13 +148,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
     protected final boolean isMap;
     protected final MetaMethodIndex metaMethodIndex;
 
-    private final Index classPropertyIndex = new MethodIndex();
-    private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
+    private final IndexMap<CachedClass, IndexMap<String, MetaProperty>> classPropertyIndex = new IndexMap<>();
+    private final IndexMap<String, MetaProperty> staticPropertyIndex = new IndexMap<>();
     private final Map<String, MetaMethod> listeners = new HashMap<>();
     private final List<MetaMethod> allMethods = new ArrayList<>();
     // we only need one of these that can be reused over and over.
     private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
-    private final Index classPropertyIndexForSuper = new MethodIndex();
+    private final IndexMap<CachedClass, IndexMap<String, MetaProperty>> classPropertyIndexForSuper = new IndexMap<>();
     private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<>();
     private final MetaMethod[] myNewMetaMethods;
     private final MetaMethod[] additionalMetaMethods;
@@ -280,15 +281,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
      * @see MetaObjectProtocol#getMetaProperty(String)
      */
     public MetaProperty getMetaProperty(String name) {
-        MetaProperty metaProperty = null;
+        MetaProperty metaProperty;
 
-        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
-        metaProperty = (MetaProperty) propertyMap.get(name);
+        IndexMap<String, MetaProperty> propertyMap = classPropertyIndex.getOrPut(theCachedClass, new IndexMap<>());
+        metaProperty = propertyMap.get(name);
         if (metaProperty == null) {
-            metaProperty = (MetaProperty) staticPropertyIndex.get(name);
+            metaProperty = staticPropertyIndex.get(name);
             if (metaProperty == null) {
-                propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
-                metaProperty = (MetaProperty) propertyMap.get(name);
+                propertyMap = classPropertyIndexForSuper.getOrPut(theCachedClass, new IndexMap<>());
+                metaProperty = propertyMap.get(name);
                 if (metaProperty == null) {
                     MetaBeanProperty property = findPropertyInClassHierarchy(name, theCachedClass);
                     if (property != null) {
@@ -1623,7 +1624,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         };
         l.sort(comp);
         int found = -1;
-        for (int i = 0; i < l.size(); i++) {
+        for (int i = 0, n = l.size(); i < n; i++) {
             if (l.get(i) != constructor) continue;
             found = i;
             break;
@@ -2174,16 +2175,16 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
      */
     public List<MetaProperty> getProperties() {
         checkInitalised();
-        SingleKeyHashMap propertyMap = classPropertyIndex.getNullable(theCachedClass);
+        IndexMap<String, MetaProperty> propertyMap = classPropertyIndex.get(theCachedClass);
         if (propertyMap == null) {
             // GROOVY-6903: May happen in some special environment, like under Android, due
             // to classloading issues
-            propertyMap = new SingleKeyHashMap();
+            propertyMap = new IndexMap<>();
         }
         // simply return the values of the metaproperty map as a List
-        List ret = new ArrayList(propertyMap.size());
-        for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
-            MetaProperty element = (MetaProperty) ((SingleKeyHashMap.Entry) iter.next()).value;
+        List<MetaProperty> ret = new ArrayList<>(propertyMap.size());
+        for (Iterator<Map.Entry<String, MetaProperty>> iter = propertyMap.entrySet().iterator(); iter.hasNext(); ) {
+            MetaProperty element = iter.next().getValue();
             if (element instanceof CachedField) continue;
             // filter out DGM beans
             if (element instanceof MetaBeanProperty) {
@@ -2345,9 +2346,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
                 superInterfaces.sort(CACHED_CLASS_NAME_COMPARATOR);
             }
 
-            SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(theCachedClass);
+            IndexMap<String, MetaProperty> iPropertyIndex = classPropertyIndex.getOrPut(theCachedClass, new IndexMap<>());
             for (CachedClass iclass : superInterfaces) {
-                SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(iclass);
+                IndexMap<String, MetaProperty> sPropertyIndex = classPropertyIndex.getOrPut(iclass, new IndexMap<>());
                 copyNonPrivateFields(sPropertyIndex, iPropertyIndex, null);
                 addFields(iclass, iPropertyIndex);
             }
@@ -2368,7 +2369,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
 
             // if this an Array, then add the special read-only "length" property
             if (theCachedClass.isArray) {
-                SingleKeyHashMap map = new SingleKeyHashMap();
+                IndexMap<String, MetaProperty> map = new IndexMap<>();
                 map.put("length", arrayLengthProperty);
                 classPropertyIndex.put(theCachedClass, map);
             }
@@ -2387,11 +2388,11 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
     }
 
     private void makeStaticPropertyIndex() {
-        SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
-        for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
-            SingleKeyHashMap.Entry entry = ((SingleKeyHashMap.Entry) iter.next());
+        IndexMap<String, MetaProperty> propertyMap = classPropertyIndex.getOrPut(theCachedClass, new IndexMap<>());
+        for (Iterator<Map.Entry<String, MetaProperty>> iter = propertyMap.entrySet().iterator(); iter.hasNext(); ) {
+            Map.Entry<String, MetaProperty> entry = iter.next();
 
-            MetaProperty mp = (MetaProperty) entry.getValue();
+            MetaProperty mp = entry.getValue();
             if (mp instanceof CachedField) {
                 CachedField mfp = (CachedField) mp;
                 if (!mfp.isStatic()) continue;
@@ -2458,32 +2459,30 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         return result;
     }
 
-    private void copyClassPropertyIndexForSuper(Index dest) {
-        for (ComplexKeyHashMap.EntryIterator iter = classPropertyIndex.getEntrySetIterator(); iter.hasNext(); ) {
-            SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) iter.next();
-            SingleKeyHashMap newVal = new SingleKeyHashMap();
-            dest.put((CachedClass) entry.getKey(), newVal);
+    private void copyClassPropertyIndexForSuper(IndexMap<CachedClass, IndexMap<String, MetaProperty>> dest) {
+        for (Iterator<Map.Entry<CachedClass, IndexMap<String, MetaProperty>>> iter = classPropertyIndex.entrySet().iterator(); iter.hasNext(); ) {
+            Map.Entry<CachedClass, IndexMap<String, MetaProperty>> entry = iter.next();
+            IndexMap<String, MetaProperty> newVal = new IndexMap<>();
+            dest.put(entry.getKey(), newVal);
         }
     }
 
-    private void inheritStaticInterfaceFields(LinkedList superClasses, Set interfaces) {
-        for (Object anInterface : interfaces) {
-            CachedClass iclass = (CachedClass) anInterface;
-            SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(iclass);
+    private void inheritStaticInterfaceFields(List<CachedClass> superClasses, Set<CachedClass> interfaces) {
+        for (CachedClass iclass : interfaces) {
+            IndexMap<String, MetaProperty> iPropertyIndex = classPropertyIndex.getOrPut(iclass, new IndexMap<>());
             addFields(iclass, iPropertyIndex);
-            for (Object superClass : superClasses) {
-                CachedClass sclass = (CachedClass) superClass;
-                if (!iclass.getTheClass().isAssignableFrom(sclass.getTheClass())) continue;
-                SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(sclass);
+            for (CachedClass superClass : superClasses) {
+                if (!iclass.getTheClass().isAssignableFrom(superClass.getTheClass())) continue;
+                IndexMap<String, MetaProperty> sPropertyIndex = classPropertyIndex.getOrPut(superClass, new IndexMap<>());
                 copyNonPrivateFields(iPropertyIndex, sPropertyIndex, null);
             }
         }
     }
 
     private void inheritFields(LinkedList<CachedClass> superClasses) {
-        SingleKeyHashMap last = null;
+        IndexMap<String, MetaProperty> last = null;
         for (CachedClass klass : superClasses) {
-            SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
+            IndexMap<String, MetaProperty> propertyIndex = classPropertyIndex.getOrPut(klass, new IndexMap<>());
             if (last != null) {
                 copyNonPrivateFields(last, propertyIndex, klass);
             }
@@ -2492,15 +2491,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
-    private static void addFields(CachedClass klass, SingleKeyHashMap propertyIndex) {
+    private static void addFields(CachedClass klass, IndexMap<String, MetaProperty> propertyIndex) {
         for (CachedField field : klass.getFields()) {
             propertyIndex.put(field.getName(), field);
         }
     }
 
-    private static void copyNonPrivateFields(SingleKeyHashMap from, SingleKeyHashMap to, @Nullable CachedClass klass) {
-        for (ComplexKeyHashMap.EntryIterator it = from.getEntrySetIterator(); it.hasNext(); ) {
-            SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) it.next();
+    private static void copyNonPrivateFields(IndexMap<String, MetaProperty> from, IndexMap<String, MetaProperty> to, @Nullable CachedClass klass) {
+        for (Iterator<Map.Entry<String, MetaProperty>> it = from.entrySet().iterator(); it.hasNext(); ) {
+            Map.Entry<String, MetaProperty> entry = it.next();
             CachedField field = (CachedField) entry.getValue();
             int modifiers = field.getModifiers();
             if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || (!Modifier.isPrivate(modifiers)
@@ -2510,11 +2509,11 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
-    private void applyStrayPropertyMethods(LinkedList<CachedClass> superClasses, Index classPropertyIndex, boolean isThis) {
+    private void applyStrayPropertyMethods(LinkedList<CachedClass> superClasses, IndexMap<CachedClass, IndexMap<String, MetaProperty>> classPropertyIndex, boolean isThis) {
         // now look for any stray getters that may be used to define a property
         for (CachedClass klass : superClasses) {
             MetaMethodIndex.Header header = metaMethodIndex.getHeader(klass.getTheClass());
-            SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
+            IndexMap<String, MetaProperty> propertyIndex = classPropertyIndex.getOrPut(klass, new IndexMap<>());
             for (MetaMethodIndex.Entry e = header.head; e != null; e = e.nextClassEntry) {
                 String methodName = e.name;
                 // name too short?
@@ -2598,7 +2597,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
-    private static void createMetaBeanProperty(SingleKeyHashMap propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod) {
+    private static void createMetaBeanProperty(IndexMap<String, MetaProperty> propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod) {
         // is this property already accounted for?
         MetaProperty mp = (MetaProperty) propertyIndex.get(propName);
         MetaProperty newMp = makeReplacementMetaProperty(mp, propName, isGetter, propertyMethod);
@@ -2654,10 +2653,10 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         if (staticProperty != null) {
             staticPropertyIndex.put(mp.getName(), mp);
         } else {
-            SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
+            IndexMap<String, MetaProperty> propertyMap = classPropertyIndex.getOrPut(theCachedClass, new IndexMap<>());
             //keep field
             CachedField field;
-            MetaProperty old = (MetaProperty) propertyMap.get(mp.getName());
+            MetaProperty old = propertyMap.get(mp.getName());
             if (old != null) {
                 if (old instanceof MetaBeanProperty) {
                     field = ((MetaBeanProperty) old).getField();
@@ -2851,13 +2850,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
 
         CachedClass clazz = ReflectionCache.getCachedClass(_clazz);
         while (true) {
-            SingleKeyHashMap propertyMap;
+            IndexMap<String, MetaProperty> propertyMap;
             if (useStatic) {
                 propertyMap = staticPropertyIndex;
             } else if (useSuper) {
-                propertyMap = classPropertyIndexForSuper.getNullable(clazz);
+                propertyMap = classPropertyIndexForSuper.get(clazz);
             } else {
-                propertyMap = classPropertyIndex.getNullable(clazz);
+                propertyMap = classPropertyIndex.get(clazz);
             }
             if (propertyMap == null) {
                 if (clazz != theCachedClass) {
@@ -2867,22 +2866,22 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
                     return null;
                 }
             }
-            return (MetaProperty) propertyMap.get(name);
+            return propertyMap.get(name);
         }
     }
 
     private MetaProperty getMetaProperty(String name, boolean useStatic) {
         CachedClass clazz = theCachedClass;
-        SingleKeyHashMap propertyMap;
+        IndexMap<String, MetaProperty> propertyMap;
         if (useStatic) {
             propertyMap = staticPropertyIndex;
         } else {
-            propertyMap = classPropertyIndex.getNullable(clazz);
+            propertyMap = classPropertyIndex.get(clazz);
         }
         if (propertyMap == null) {
             return null;
         }
-        return (MetaProperty) propertyMap.get(name);
+        return propertyMap.get(name);
     }
 
     /**
@@ -3902,6 +3901,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         metaMethodIndex.clearCaches();
     }
 
+    @Deprecated
     private static final SingleKeyHashMap.Copier NAME_INDEX_COPIER = value -> {
         if (value instanceof FastArray) {
             return ((FastArray) value).copy();
@@ -3910,8 +3910,19 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     };
 
+    @Deprecated
     private static final SingleKeyHashMap.Copier METHOD_INDEX_COPIER = value -> SingleKeyHashMap.copy(new SingleKeyHashMap(false), (SingleKeyHashMap) value, NAME_INDEX_COPIER);
 
+    private static class IndexMap<K, V> extends LinkedHashMap<K, V> {
+        public V getOrPut(K key, V value) {
+            return this.computeIfAbsent(key, k -> value);
+        }
+    }
+
+    /**
+     * @deprecated use {@link IndexMap} instead
+     */
+    @Deprecated
     static class MethodIndex extends Index {
         public MethodIndex(boolean b) {
             super(false);
@@ -3934,6 +3945,10 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
+    /**
+     * @deprecated use {@link IndexMap} instead
+     */
+    @Deprecated
     public static class Index extends SingleKeyHashMap {
 
         public Index(int size) {
diff --git a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
index 1069af1..02b6863 100644
--- a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
+++ b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
@@ -120,7 +120,7 @@ class JsonTest extends GroovyTestCase {
             .excludeFieldsByType(URL)
             .build()
 
-        assert generator.toJson(person) == '{"dob":"1984@12","name":"John"}'
+        assert generator.toJson(person) == '{"name":"John","dob":"1984@12"}'
         // end::json_output_generator[]
         '''
     }
@@ -148,7 +148,7 @@ class JsonTest extends GroovyTestCase {
             }
             .build()
 
-        assert generator.toJson(person) == '{"favoriteUrl":"groovy-lang.org","name":"John"}'
+        assert generator.toJson(person) == '{"name":"John","favoriteUrl":"groovy-lang.org"}'
 
         // No key available when generating a JSON Array
         def list = [new URL('http://groovy-lang.org/json.html#_jsonoutput')]
diff --git a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
index 3ed54bf..20c061d 100644
--- a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
+++ b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
@@ -306,30 +306,30 @@ class JsonOutputTest extends GroovyTestCase {
                 "name": "Paris",
                 "districts": [
                     {
+                        "number": 1,
                         "streets": [
                             {
-                                "kind": "street",
-                                "streetName": "Saint-Honore"
+                                "streetName": "Saint-Honore",
+                                "kind": "street"
                             },
                             {
-                                "kind": "avenue",
-                                "streetName": "de l'Opera"
+                                "streetName": "de l'Opera",
+                                "kind": "avenue"
                             }
-                        ],
-                        "number": 1
+                        ]
                     },
                     {
+                        "number": 2,
                         "streets": [
                             {
-                                "kind": "boulevard",
-                                "streetName": "des Italiens"
+                                "streetName": "des Italiens",
+                                "kind": "boulevard"
                             },
                             {
-                                "kind": "boulevard",
-                                "streetName": "Bonne Nouvelle"
+                                "streetName": "Bonne Nouvelle",
+                                "kind": "boulevard"
                             }
-                        ],
-                        "number": 2
+                        ]
                     }
                 ]
             }'''.stripIndent()
@@ -350,12 +350,12 @@ class JsonOutputTest extends GroovyTestCase {
     void testObjectWithDeclaredPropertiesField() {
         def person = new JsonObject(name: "pillow", properties: [state: "fluffy", color: "white"])
         def json = toJson(person)
-        assert json == '{"properties":{"state":"fluffy","color":"white"},"name":"pillow"}'
+        assert json == '{"name":"pillow","properties":{"state":"fluffy","color":"white"}}'
     }
 
     void testGROOVY5494() {
         def json = toJson(new JsonFoo(name: "foo"))
-        assert json == '{"properties":0,"name":"foo"}'
+        assert json == '{"name":"foo","properties":0}'
     }
 
     void testCharacter() {