Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep reference to type of SimpleNode value #9

Merged
merged 2 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/ru/mingun/kaitai/struct/tree/ChunkNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ public abstract class ChunkNode extends ValueNode {
* @throws ReflectiveOperationException If {@code value} is {@link KaitaiStruct}
* and it was compiled without debug info (which includes position information)
*/
protected ChunkNode create(String name, Object value, long offset, long start, long end) throws ReflectiveOperationException {
protected ChunkNode create(String name, Object value, Class<?> classOfValue, long offset, long start, long end) throws ReflectiveOperationException {
return value instanceof KaitaiStruct
? new StructNode(name, (KaitaiStruct)value, this, offset, start, end)
: new SimpleNode(name, value, this, offset, start, end);
: new SimpleNode(name, value, classOfValue, this, offset, start, end);
}
}
23 changes: 20 additions & 3 deletions src/main/java/ru/mingun/kaitai/struct/tree/ListNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
*/
package ru.mingun.kaitai.struct.tree;

import javax.swing.tree.TreeNode;
import java.util.ArrayList;
import static java.util.Collections.enumeration;
import java.util.Enumeration;
import java.util.List;
import javax.swing.tree.TreeNode;
import java.util.Objects;
import java.util.Optional;

import static java.util.Collections.enumeration;

/**
* Node, that represents a repeated data in struct definition. An each repeated value
Expand Down Expand Up @@ -91,7 +94,21 @@ private List<ChunkNode> init() {
try {
final int s = arrStart.get(index);
final int e = arrEnd.get(index);
children.add(create("[" + index + ']', obj, 0, s, e));

/*
We cannot access the generic type of the List at runtime due to
type erasure. Instead, look for a non-null element in the List,
which will tell us the type of the whole list.
*/
final Class<?> valueClass;
final Optional<?> nonNullElement = value.stream().filter(Objects::nonNull).findAny();
if (nonNullElement.isPresent()) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like the idea of looking at the content, because the type will depend on the specific object. Probably it is possible to extract some type from generic boundaries? I remember, that this should be possible.

valueClass = nonNullElement.get().getClass();
} else {
valueClass = null;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to avoid null in that field:

Suggested change
valueClass = null;
valueClass = Object.class;

}

children.add(create("[" + index + ']', obj, valueClass, 0, s, e));
++index;
} catch (ReflectiveOperationException ex) {
throw new UnsupportedOperationException("Can't get list value at index " + index, ex);
Expand Down
8 changes: 7 additions & 1 deletion src/main/java/ru/mingun/kaitai/struct/tree/SimpleNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,20 @@ public class SimpleNode extends ChunkNode {
/** Parsed value of non-constructed type. */
private final Object value;

SimpleNode(String name, Object value, ChunkNode parent, long offset, long start, long end) {
/** Replace value.getClass() when value==null. */
private final Class<?> classOfValue;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Replace value.getClass() when value==null. */
private final Class<?> classOfValue;
/** Class of property, represented by the getter return value. */
private final Class<?> valueClass;

value.getClass() is slightly incorrect, because it is dynamic type, but in fact the static type is stored here. For example ArrayList vs List


SimpleNode(String name, Object value, Class<?> valueClass, ChunkNode parent, long offset, long start, long end) {
super(name, parent, offset, start, end);
this.value = value;
this.classOfValue = valueClass;
}

@Override
public Object getValue() { return value; }

public Class<?> getClassOfValue() { return classOfValue; }
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public Class<?> getClassOfValue() { return classOfValue; }
public Class<?> getValueClass() { return valueClass; }

I bet, that this name is better.


//<editor-fold defaultstate="collapsed" desc="TreeNode">
@Override
public ChunkNode getChildAt(int childIndex) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ru/mingun/kaitai/struct/tree/StructNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ private ChunkNode create(Method getter) throws ReflectiveOperationException {
final List<Integer> se = arrEnd.get(name);
return new ListNode(name, (List<?>)field, this, offset, s, e, sa, se);
}
return create(name, field, start, s, e);
return create(name, field, getter.getReturnType(), start, s, e);
}

private ArrayList<ChunkNode> init() {
Expand Down