added final for methodlocal vars
This commit is contained in:
parent
caf43cfb19
commit
e22d507c30
6 changed files with 74 additions and 66 deletions
|
|
@ -43,7 +43,7 @@ public class JsonReader {
|
|||
* array => List
|
||||
*/
|
||||
public static Object read(InputStream inputStream) {
|
||||
InputStream in = ensureBuffered(inputStream);
|
||||
final InputStream in = ensureBuffered(inputStream);
|
||||
try (Parser parser = getParser(in)) {
|
||||
return read(parser);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,37 +37,37 @@ public class Parser extends Lexer {
|
|||
}
|
||||
|
||||
public Integer parseInteger() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Double.valueOf(value).intValue();
|
||||
}
|
||||
|
||||
public Long parseLong() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Long.parseLong(value);
|
||||
}
|
||||
|
||||
public Float parseFloat() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Float.parseFloat(value);
|
||||
}
|
||||
|
||||
public Double parseDouble() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
public Short parseShort() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Short.parseShort(value);
|
||||
}
|
||||
|
||||
public Byte parseByte() {
|
||||
String value = parseNumber();
|
||||
final String value = parseNumber();
|
||||
return Byte.parseByte(value);
|
||||
}
|
||||
|
||||
public Character parseCharacter() {
|
||||
String string = parseString();
|
||||
final String string = parseString();
|
||||
return string.charAt(0);
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ public class Parser extends Lexer {
|
|||
advance();
|
||||
}
|
||||
|
||||
String maybeBoolean = characterBuffer.toString();
|
||||
final String maybeBoolean = characterBuffer.toString();
|
||||
boolean returnValue;
|
||||
if ((returnValue = maybeBoolean.equals("true")) || maybeBoolean.equals("false")) {
|
||||
return returnValue;
|
||||
|
|
@ -109,10 +109,10 @@ public class Parser extends Lexer {
|
|||
if (current != '[') {
|
||||
throw new JsonParseException("no list found");
|
||||
}
|
||||
List<Object> list = new ArrayList<>();
|
||||
final List<Object> list = new ArrayList<>();
|
||||
advance();
|
||||
while (current != -1 && current != ']') {
|
||||
Maybe<Object> maybeValue = parseValue();
|
||||
final Maybe<Object> maybeValue = parseValue();
|
||||
if (!maybeValue.isPresent()) {
|
||||
break;
|
||||
} else {
|
||||
|
|
@ -125,7 +125,7 @@ public class Parser extends Lexer {
|
|||
}
|
||||
|
||||
public Map<?, ?> parseObject() {
|
||||
HashMap<Object, Object> map = new HashMap<>();
|
||||
final HashMap<Object, Object> map = new HashMap<>();
|
||||
skipWhitespace();
|
||||
if (current != '{') {
|
||||
throw new JsonParseException("no map found");
|
||||
|
|
@ -134,7 +134,7 @@ public class Parser extends Lexer {
|
|||
while (current != -1 && current != '}') {
|
||||
skipWhitespace();
|
||||
if (current == '"') {
|
||||
String key = parseString();
|
||||
final String key = parseString();
|
||||
skipWhitespace();
|
||||
if (current == ':') {
|
||||
advance();
|
||||
|
|
@ -142,7 +142,7 @@ public class Parser extends Lexer {
|
|||
throw new JsonParseException("expected colon");
|
||||
}
|
||||
skipWhitespace();
|
||||
Maybe<Object> maybeValue = parseValue();
|
||||
final Maybe<Object> maybeValue = parseValue();
|
||||
maybeValue.ifPresent(value -> map.put(key, value));
|
||||
}
|
||||
advance();
|
||||
|
|
@ -152,7 +152,7 @@ public class Parser extends Lexer {
|
|||
}
|
||||
|
||||
public Object parseAny() {
|
||||
Maybe<Object> maybe = parseValue();
|
||||
final Maybe<Object> maybe = parseValue();
|
||||
if (maybe.isPresent()) {
|
||||
return maybe.get();
|
||||
} else {
|
||||
|
|
@ -161,7 +161,7 @@ public class Parser extends Lexer {
|
|||
}
|
||||
|
||||
private Maybe<Object> parseValue() {
|
||||
Object value;
|
||||
final Object value;
|
||||
skipWhitespace();
|
||||
switch (current) {
|
||||
case ']':
|
||||
|
|
@ -251,8 +251,8 @@ public class Parser extends Lexer {
|
|||
}
|
||||
|
||||
private void parseEncoded() {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
char codePoint = parseCodePoint();
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
final char codePoint = parseCodePoint();
|
||||
buf.append(codePoint);
|
||||
if (Character.isHighSurrogate(codePoint)) {
|
||||
expect(() -> new JsonParseException("Invalid unicode codepoint at line " + linecount), '\\', 'u');
|
||||
|
|
|
|||
|
|
@ -7,12 +7,20 @@ import java.util.Arrays;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Contains info from parsed bytecode
|
||||
*/
|
||||
public class ClassObject {
|
||||
|
||||
public class ClassObject<T> {
|
||||
private final ConstantPoolEntry[] constantPool;
|
||||
private final Info[] fieldInfos;
|
||||
private final Info[] methodInfos;
|
||||
|
||||
private ConstantPoolEntry[] constantPool;
|
||||
private Info[] fieldInfos;
|
||||
private Info[] methodInfos;
|
||||
private ClassObject(ConstantPoolEntry[] constantPool, Info[] fieldInfos, Info[] methodInfos) {
|
||||
this.constantPool = constantPool;
|
||||
this.fieldInfos = fieldInfos;
|
||||
this.methodInfos = methodInfos;
|
||||
}
|
||||
|
||||
private String getUtf8(int index) {
|
||||
return ((Utf8Entry) constantPool[index - 1]).getUtf8();
|
||||
|
|
@ -41,41 +49,44 @@ public class ClassObject<T> {
|
|||
|
||||
public static class Builder<T> {
|
||||
|
||||
private final ClassObject<T> classObject = new ClassObject<>();
|
||||
private int constantPoolIndex = 0;
|
||||
private int fieldInfoIndex = 0;
|
||||
private int methodInfoIndex = 0;
|
||||
|
||||
public ClassObject<T> build() {
|
||||
return classObject;
|
||||
private ConstantPoolEntry[] constantPool;
|
||||
private Info[] fieldInfos;
|
||||
private Info[] methodInfos;
|
||||
|
||||
public ClassObject build() {
|
||||
return new ClassObject(constantPool, fieldInfos, methodInfos);
|
||||
}
|
||||
|
||||
public Builder<T> constantPoolCount(int constantPoolCount) {
|
||||
classObject.constantPool = new ConstantPoolEntry[constantPoolCount - 1];
|
||||
constantPool = new ConstantPoolEntry[constantPoolCount - 1];
|
||||
return this;
|
||||
}
|
||||
|
||||
void constantPoolEntry(ConstantPoolEntry entry) {
|
||||
classObject.constantPool[constantPoolIndex++] = entry;
|
||||
constantPool[constantPoolIndex++] = entry;
|
||||
}
|
||||
|
||||
public Builder<T> fieldInfoCount(int fieldInfoCount) {
|
||||
classObject.fieldInfos = new Info[fieldInfoCount];
|
||||
fieldInfos = new Info[fieldInfoCount];
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> fieldInfo(Info fieldInfo) {
|
||||
classObject.fieldInfos[fieldInfoIndex++] = fieldInfo;
|
||||
fieldInfos[fieldInfoIndex++] = fieldInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> methodInfoCount(int methodInfoCount) {
|
||||
classObject.methodInfos = new Info[methodInfoCount];
|
||||
methodInfos = new Info[methodInfoCount];
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> methodInfo(Info methodInfo) {
|
||||
classObject.methodInfos[methodInfoIndex++] = methodInfo;
|
||||
methodInfos[methodInfoIndex++] = methodInfo;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import java.io.IOException;
|
|||
|
||||
public class ClassReader extends DataReader {
|
||||
|
||||
public <T> ClassObject<T> parse(Class<T> type) {
|
||||
DataInputStream in = new DataInputStream(new BufferedInputStream(type.getResourceAsStream(getResourceName(type))));
|
||||
public <T> ClassObject parse(Class<T> type) {
|
||||
final DataInputStream in = new DataInputStream(new BufferedInputStream(type.getResourceAsStream(getResourceName(type))));
|
||||
expect(in, 0xCAFEBABE);
|
||||
|
||||
ClassObject.Builder<T> builder = new ClassObject.Builder<>();
|
||||
|
|
@ -19,7 +19,7 @@ public class ClassReader extends DataReader {
|
|||
readConstantPool(in, builder);
|
||||
|
||||
skip(in, 6); // u2 access_flags, u2 this_class, u2 super_class
|
||||
int interfacesCount = readU16(in);
|
||||
final int interfacesCount = readUnsignedShort(in);
|
||||
skip(in, interfacesCount * 2); // interfaces[u2;]
|
||||
|
||||
readFields(in, builder);
|
||||
|
|
@ -29,7 +29,7 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private <T> void readConstantPool(DataInputStream in, ClassObject.Builder<T> builder) {
|
||||
int constantPoolCount = readU16(in);
|
||||
final int constantPoolCount = readUnsignedShort(in);
|
||||
builder.constantPoolCount(constantPoolCount);
|
||||
for (int i = 1; i < constantPoolCount; i++) {
|
||||
builder.constantPoolEntry(readConstantPoolEntry(in));
|
||||
|
|
@ -37,7 +37,7 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private <T> void readFields(DataInputStream in, ClassObject.Builder<T> builder) {
|
||||
int fieldInfoCount = readU16(in);
|
||||
final int fieldInfoCount = readUnsignedShort(in);
|
||||
builder.fieldInfoCount(fieldInfoCount);
|
||||
for (int i = 0; i < fieldInfoCount; i++) {
|
||||
builder.fieldInfo(readField(in));
|
||||
|
|
@ -45,7 +45,7 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private <T> void readMethods(DataInputStream in, ClassObject.Builder<T> builder) {
|
||||
int methodInfoCount = readU16(in);
|
||||
final int methodInfoCount = readUnsignedShort(in);
|
||||
builder.methodInfoCount(methodInfoCount);
|
||||
for (int i = 0; i < methodInfoCount; i++) {
|
||||
builder.methodInfo(readMethod(in));
|
||||
|
|
@ -53,7 +53,7 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private <T> Info readField(DataInputStream in) {
|
||||
Info fieldInfo = new Info(readU16(in), readU16(in), readU16(in), readU16(in));
|
||||
final Info fieldInfo = new Info(readUnsignedShort(in), readUnsignedShort(in), readUnsignedShort(in), readUnsignedShort(in));
|
||||
for (int i = 0; i < fieldInfo.getAttributesCount(); i++) {
|
||||
fieldInfo.add(readAttribute(in));
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private <T> Info readMethod(DataInputStream in) {
|
||||
Info methodInfo = new Info(readU16(in), readU16(in), readU16(in), readU16(in));
|
||||
final Info methodInfo = new Info(readUnsignedShort(in), readUnsignedShort(in), readUnsignedShort(in), readUnsignedShort(in));
|
||||
for (int i = 0; i < methodInfo.getAttributesCount(); i++) {
|
||||
methodInfo.add(readAttribute(in));
|
||||
}
|
||||
|
|
@ -71,9 +71,9 @@ public class ClassReader extends DataReader {
|
|||
}
|
||||
|
||||
private AttributeInfo readAttribute(DataInputStream in) {
|
||||
int attributeNameIndex = readU16(in);
|
||||
int attributeLength = readS32(in);
|
||||
byte[] info;
|
||||
final int attributeNameIndex = readUnsignedShort(in);
|
||||
final int attributeLength = readS32(in);
|
||||
final byte[] info;
|
||||
if (attributeLength > 0) {
|
||||
info = new byte[attributeLength];
|
||||
try {
|
||||
|
|
@ -87,32 +87,32 @@ public class ClassReader extends DataReader {
|
|||
return new AttributeInfo(attributeNameIndex, info);
|
||||
}
|
||||
|
||||
private <T> ConstantPoolEntry readConstantPoolEntry(DataInputStream in) {
|
||||
byte tag = readByte(in);
|
||||
private ConstantPoolEntry readConstantPoolEntry(DataInputStream in) {
|
||||
final byte tag = readByte(in);
|
||||
switch (tag) {
|
||||
case 1: return readUtf8Entry(in);
|
||||
case 1: return new Utf8Entry(readString(in, readUnsignedShort(in)));
|
||||
case 2: throw new IllegalStateException("2: invalid classpool tag");
|
||||
case 3: return new IntEntry(readS32(in));
|
||||
case 4: return new FloatEntry(readF32(in));
|
||||
case 5: return new LongEntry(readS64(in));
|
||||
case 6: return new DoubleEntry(readF64(in));
|
||||
case 7: return new ClassEntry(readU16(in));
|
||||
case 8: return new StringEntry(readU16(in));
|
||||
case 9: return new FieldRefEntry(readU16(in), readU16(in));
|
||||
case 10: return new MethodRefEntry(readU16(in), readU16(in));
|
||||
case 11: return new InterfaceMethodRefEntry(readU16(in), readU16(in));
|
||||
case 12: return new NameAndTypeEntry(readU16(in), readU16(in));
|
||||
case 15: return new MethodHandleEntry(readU16(in), readU16(in));
|
||||
case 16: return new MethodTypeEntry(readU16(in));
|
||||
case 18: return new InvokeDynamicEntry(readU16(in), readU16(in));
|
||||
case 19: return new ModuleEntry(readU16(in));
|
||||
case 20: return new PackageEntry(readU16(in));
|
||||
case 7: return new ClassEntry(readUnsignedShort(in));
|
||||
case 8: return new StringEntry(readUnsignedShort(in));
|
||||
case 9: return new FieldRefEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 10: return new MethodRefEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 11: return new InterfaceMethodRefEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 12: return new NameAndTypeEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 15: return new MethodHandleEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 16: return new MethodTypeEntry(readUnsignedShort(in));
|
||||
case 18: return new InvokeDynamicEntry(readUnsignedShort(in), readUnsignedShort(in));
|
||||
case 19: return new ModuleEntry(readUnsignedShort(in));
|
||||
case 20: return new PackageEntry(readUnsignedShort(in));
|
||||
default: throw new IllegalStateException("invalid classpool");
|
||||
}
|
||||
}
|
||||
|
||||
protected <T> String getResourceName(Class<T> type) {
|
||||
StringBuilder typeName = new StringBuilder("/" + type.getName());
|
||||
final StringBuilder typeName = new StringBuilder("/" + type.getName());
|
||||
|
||||
for (int i = 0; i < typeName.length(); i++) {
|
||||
if (typeName.charAt(i) == '.') {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
package nl.sander.jsontoy2.java;
|
||||
|
||||
import nl.sander.jsontoy2.java.constantpool.Utf8Entry;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* basic IO operations with runtime exceptions
|
||||
*/
|
||||
public class DataReader {
|
||||
|
||||
protected long readS64(DataInputStream in) {
|
||||
|
|
@ -33,7 +34,7 @@ public class DataReader {
|
|||
}
|
||||
}
|
||||
|
||||
protected int readU16(DataInputStream in) {
|
||||
protected int readUnsignedShort(DataInputStream in) {
|
||||
try {
|
||||
return in.readUnsignedShort();
|
||||
} catch (IOException e) {
|
||||
|
|
@ -49,11 +50,6 @@ public class DataReader {
|
|||
}
|
||||
}
|
||||
|
||||
protected Utf8Entry readUtf8Entry(DataInputStream in) {
|
||||
int length = readU16(in);
|
||||
return new Utf8Entry(readString(in, length));
|
||||
}
|
||||
|
||||
protected String readString(DataInputStream in, int length) {
|
||||
try {
|
||||
byte[] bytes = in.readNBytes(length);
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
|
||||
public class ClassReaderTest {
|
||||
|
||||
//part of the test
|
||||
public int field;
|
||||
|
||||
@Test
|
||||
public void testReadClass() {
|
||||
ClassObject<ClassReaderTest> object = new ClassReader().parse(ClassReaderTest.class);
|
||||
ClassObject object = new ClassReader().parse(ClassReaderTest.class);
|
||||
assertEquals(Set.of(new Field("field", "I")), object.getFields());
|
||||
assertEquals(Set.of(new Method("<init>", "()V"), new Method("testReadClass", "()V")), object.getMethods());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue