(sorry, been ooo.)

On Sun, Jun 28, 2020 at 11:21 PM Rob Landley <r...@landley.net> wrote:

> On 6/26/20 2:35 PM, enh via Toybox wrote:
> > toybox patch fails to apply the patch
> >
> https://android.googlesource.com/platform/external/snakeyaml/+/refs/heads/master/src/patches/android/Representer.patch
>
> That's html, I clicked the ".txt" link at the bottom and it downloaded a
> block
> of
> "Zy95YW1sL3NuYWtleWFtbC9yZXByZXNlbnRlci9SZXByZXNlbnRlci5qYXZhCkBAIC0xNSw3"
> which I don't recognize the encoding of?
>
>   $ file Representer.txt
>   Representer.txt: ASCII text, with very long lines, with no line
> terminators
>
> The debian file command is editorializing, but not helpful.
>
> > to the file
> https://android.googlesource.com/platform/external/snakeyaml/+/refs/heads/master/src/main/java/org/yaml/snakeyaml/representer/Representer.java
> .
>
> Could you send me the two files?
>

attached.

note that when you're finding gittiles unhelpful (which, let's face it, it
usually is), you can just chop the first part off the URL and `git clone`.
so here, for example, `git clone
https://android.googlesource.com/platform/external/snakeyaml/` will check
out this single git project, which isn't very large.


> > the worst part is that it _thinks_ it succeeds :-(
> >
> > the interesting bit happens when we come to apply this hunk:
> >
> > @@ -15,7 +15,6 @@
> > */
> >  package org.yaml.snakeyaml.representer;
> >
> > -import java.beans.IntrospectionException;
> >  import java.util.ArrayList;
> >  import java.util.Arrays;
> >  import java.util.Iterator;
> >
> > here:
> >
> > package org.yaml.snakeyaml.representer;
> >
> > import java.beans.IntrospectionException;
> > import java.util.ArrayList;
> > import java.util.Arrays;
> > import java.util.Collections;
> > import java.util.Iterator;
> > import java.util.List;
> >
> > the eagle-eyed human will notice that there's an extra "Collections"
> > in the actual file that isn't in the patch, because the patch was
> > actually against an older version of the source.
>
> Didn't commit 333a10f9ef59 fix this back in February? (It was supposed
> to...)
>
> > the bug is that toybox drops that new line in its output.
> >
> > it reads it:
> >
> > MAYBE:
> > IN: import java.beans.IntrospectionException;
> > MAYBE: -import java.beans.IntrospectionException;
> > IN: import java.util.ArrayList;
> > MAYBE:  import java.util.ArrayList;
> > IN: import java.util.Arrays;
> > MAYBE:  import java.util.Arrays;
> > IN: import java.util.Collections;
> > FUZZED: 21  import java.util.Iterator;
> >
> > but then it does a `goto fuzzed` and explicitly drops that line it
> > just read. which is clearly wrong here, but the code comment
> > explicitly calls out this behavior:
> >
> >     // If match failed, flush first line of buffered data and
> >     // recheck buffered data for a new match until we find one or run
> >     // out of buffer.
>
> That's leading data. The idea was if you're matching
>
> @@
>   abc
> - def
>   ghi
>
> And the data says:
>
>  abc
>  abc
>  def
>  ghi
>
> It shouldn't see the first abc, read in the second abc and go "nope,
> that's not
> def" and then discard _both_ before checking again. (It has to advance
> _one_
> line and try again, thus checking at every possible offset, including
> rechecking
> the data it's already buffered  because it thought it might be a later
> part of
> the hunk under consideration. The actual _start_ of the hunk might be in
> that
> mismatched later part it's already read in.)
>
> > so i'm not quite sure i understand the intended logic here. when would
> > you ever want to drop an input line that doesn't have a '-' or '+'
> > line in the hunk?
>
> Can you send me the test files? (I can try to put together a test from what
> you've sent me, but I'd rather have the real one.)
>
> Thanks,
>
> Rob
>
/**
 * Copyright (c) 2008, http://www.snakeyaml.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.yaml.snakeyaml.representer;

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.yaml.snakeyaml.DumperOptions.FlowStyle;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.SequenceNode;
import org.yaml.snakeyaml.nodes.Tag;

/**
 * Represent JavaBeans
 */
public class Representer extends SafeRepresenter {

    public Representer() {
        this.representers.put(null, new RepresentJavaBean());
    }

    protected class RepresentJavaBean implements Represent {
        public Node representData(Object data) {
            try {
                return representJavaBean(getProperties(data.getClass()), data);
            } catch (IntrospectionException e) {
                throw new YAMLException(e);
            }
        }
    }

    /**
     * Tag logic:<br/>
     * - explicit root tag is set in serializer <br/>
     * - if there is a predefined class tag it is used<br/>
     * - a global tag with class name is always used as tag. The JavaBean parent
     * of the specified JavaBean may set another tag (tag:yaml.org,2002:map)
     * when the property class is the same as runtime class
     * 
     * @param properties
     *            JavaBean getters
     * @param javaBean
     *            instance for Node
     * @return Node to get serialized
     */
    protected MappingNode representJavaBean(Set<Property> properties, Object javaBean) {
        List<NodeTuple> value = new ArrayList<NodeTuple>(properties.size());
        Tag tag;
        Tag customTag = classTags.get(javaBean.getClass());
        tag = customTag != null ? customTag : new Tag(javaBean.getClass());
        // flow style will be chosen by BaseRepresenter
        MappingNode node = new MappingNode(tag, value, null);
        representedObjects.put(javaBean, node);
        boolean bestStyle = true;
        for (Property property : properties) {
            Object memberValue = property.get(javaBean);
            Tag customPropertyTag = memberValue == null ? null : classTags.get(memberValue
                    .getClass());
            NodeTuple tuple = representJavaBeanProperty(javaBean, property, memberValue,
                    customPropertyTag);
            if (tuple == null) {
                continue;
            }
            if (((ScalarNode) tuple.getKeyNode()).getStyle() != null) {
                bestStyle = false;
            }
            Node nodeValue = tuple.getValueNode();
            if (!(nodeValue instanceof ScalarNode && ((ScalarNode) nodeValue).getStyle() == null)) {
                bestStyle = false;
            }
            value.add(tuple);
        }
        if (defaultFlowStyle != FlowStyle.AUTO) {
            node.setFlowStyle(defaultFlowStyle.getStyleBoolean());
        } else {
            node.setFlowStyle(bestStyle);
        }
        return node;
    }

    /**
     * Represent one JavaBean property.
     * 
     * @param javaBean
     *            - the instance to be represented
     * @param property
     *            - the property of the instance
     * @param propertyValue
     *            - value to be represented
     * @param customTag
     *            - user defined Tag
     * @return NodeTuple to be used in a MappingNode. Return null to skip the
     *         property
     */
    protected NodeTuple representJavaBeanProperty(Object javaBean, Property property,
            Object propertyValue, Tag customTag) {
        ScalarNode nodeKey = (ScalarNode) representData(property.getName());
        // the first occurrence of the node must keep the tag
        boolean hasAlias = this.representedObjects.containsKey(propertyValue);

        Node nodeValue = representData(propertyValue);

        if (propertyValue != null && !hasAlias) {
            NodeId nodeId = nodeValue.getNodeId();
            if (customTag == null) {
                if (nodeId == NodeId.scalar) {
                    if (propertyValue instanceof Enum<?>) {
                        nodeValue.setTag(Tag.STR);
                    }
                } else {
                    if (nodeId == NodeId.mapping) {
                        if (property.getType() == propertyValue.getClass()) {
                            if (!(propertyValue instanceof Map<?, ?>)) {
                                if (!nodeValue.getTag().equals(Tag.SET)) {
                                    nodeValue.setTag(Tag.MAP);
                                }
                            }
                        }
                    }
                    checkGlobalTag(property, nodeValue, propertyValue);
                }
            }
        }

        return new NodeTuple(nodeKey, nodeValue);
    }

    /**
     * Remove redundant global tag for a type safe (generic) collection if it is
     * the same as defined by the JavaBean property
     * 
     * @param property
     *            - JavaBean property
     * @param node
     *            - representation of the property
     * @param object
     *            - instance represented by the node
     */
    @SuppressWarnings("unchecked")
    protected void checkGlobalTag(Property property, Node node, Object object) {
        // Skip primitive arrays.
        if (object.getClass().isArray() && object.getClass().getComponentType().isPrimitive()) {
            return;
        }

        Class<?>[] arguments = property.getActualTypeArguments();
        if (arguments != null) {
            if (node.getNodeId() == NodeId.sequence) {
                // apply map tag where class is the same
                Class<? extends Object> t = arguments[0];
                SequenceNode snode = (SequenceNode) node;
                Iterable<Object> memberList = Collections.EMPTY_LIST;
                if (object.getClass().isArray()) {
                    memberList = Arrays.asList((Object[]) object);
                } else if (object instanceof Iterable<?>) {
                    // list
                    memberList = (Iterable<Object>) object;
                }
                Iterator<Object> iter = memberList.iterator();
                if (iter.hasNext()) {
                    for (Node childNode : snode.getValue()) {
                        Object member = iter.next();
                        if (member != null) {
                            if (t.equals(member.getClass()))
                                if (childNode.getNodeId() == NodeId.mapping) {
                                    childNode.setTag(Tag.MAP);
                                }
                        }
                    }
                }
            } else if (object instanceof Set) {
                Class<?> t = arguments[0];
                MappingNode mnode = (MappingNode) node;
                Iterator<NodeTuple> iter = mnode.getValue().iterator();
                Set<?> set = (Set<?>) object;
                for (Object member : set) {
                    NodeTuple tuple = iter.next();
                    Node keyNode = tuple.getKeyNode();
                    if (t.equals(member.getClass())) {
                        if (keyNode.getNodeId() == NodeId.mapping) {
                            keyNode.setTag(Tag.MAP);
                        }
                    }
                }
            } else if (object instanceof Map) {
                Class<?> keyType = arguments[0];
                Class<?> valueType = arguments[1];
                MappingNode mnode = (MappingNode) node;
                for (NodeTuple tuple : mnode.getValue()) {
                    resetTag(keyType, tuple.getKeyNode());
                    resetTag(valueType, tuple.getValueNode());
                }
            } else {
                // the type for collection entries cannot be
                // detected
            }
        }
    }

    private void resetTag(Class<? extends Object> type, Node node) {
        Tag tag = node.getTag();
        if (tag.matches(type)) {
            if (Enum.class.isAssignableFrom(type)) {
                node.setTag(Tag.STR);
            } else {
                node.setTag(Tag.MAP);
            }
        }
    }

    /**
     * Get JavaBean properties to be serialised. The order is respected. This
     * method may be overridden to provide custom property selection or order.
     * 
     * @param type
     *            - JavaBean to inspect the properties
     * @return properties to serialise
     */
    protected Set<Property> getProperties(Class<? extends Object> type)
            throws IntrospectionException {
        return getPropertyUtils().getProperties(type);
    }
}
# HG changeset patch
# Parent 44449b0d7ff73bbda13c28f2ebd4e8257c67a181
diff --git a/src/main/java/org/yaml/snakeyaml/representer/Representer.java b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
--- a/src/main/java/org/yaml/snakeyaml/representer/Representer.java
+++ b/src/main/java/org/yaml/snakeyaml/representer/Representer.java
@@ -15,7 +15,6 @@
  */
 package org.yaml.snakeyaml.representer;
 
-import java.beans.IntrospectionException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Iterator;
@@ -24,7 +23,6 @@
 import java.util.Set;
 
 import org.yaml.snakeyaml.DumperOptions.FlowStyle;
-import org.yaml.snakeyaml.error.YAMLException;
 import org.yaml.snakeyaml.introspector.Property;
 import org.yaml.snakeyaml.nodes.MappingNode;
 import org.yaml.snakeyaml.nodes.Node;
@@ -45,11 +43,7 @@
 
     protected class RepresentJavaBean implements Represent {
         public Node representData(Object data) {
-            try {
-                return representJavaBean(getProperties(data.getClass()), data);
-            } catch (IntrospectionException e) {
-                throw new YAMLException(e);
-            }
+            return representJavaBean(getProperties(data.getClass()), data);
         }
     }
 
@@ -233,8 +227,7 @@
      *            - JavaBean to inspect the properties
      * @return properties to serialise
      */
-    protected Set<Property> getProperties(Class<? extends Object> type)
-            throws IntrospectionException {
+    protected Set<Property> getProperties(Class<? extends Object> type) {
         return getPropertyUtils().getProperties(type);
     }
 }
_______________________________________________
Toybox mailing list
Toybox@lists.landley.net
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to