added final for methodlocal vars

This commit is contained in:
Sander Hautvast 2020-07-28 15:39:53 +02:00
parent caf43cfb19
commit e22d507c30
6 changed files with 74 additions and 66 deletions

View file

@ -43,7 +43,7 @@ public class JsonReader {
* array => List * array => List
*/ */
public static Object read(InputStream inputStream) { public static Object read(InputStream inputStream) {
InputStream in = ensureBuffered(inputStream); final InputStream in = ensureBuffered(inputStream);
try (Parser parser = getParser(in)) { try (Parser parser = getParser(in)) {
return read(parser); return read(parser);
} }

View file

@ -37,37 +37,37 @@ public class Parser extends Lexer {
} }
public Integer parseInteger() { public Integer parseInteger() {
String value = parseNumber(); final String value = parseNumber();
return Double.valueOf(value).intValue(); return Double.valueOf(value).intValue();
} }
public Long parseLong() { public Long parseLong() {
String value = parseNumber(); final String value = parseNumber();
return Long.parseLong(value); return Long.parseLong(value);
} }
public Float parseFloat() { public Float parseFloat() {
String value = parseNumber(); final String value = parseNumber();
return Float.parseFloat(value); return Float.parseFloat(value);
} }
public Double parseDouble() { public Double parseDouble() {
String value = parseNumber(); final String value = parseNumber();
return Double.parseDouble(value); return Double.parseDouble(value);
} }
public Short parseShort() { public Short parseShort() {
String value = parseNumber(); final String value = parseNumber();
return Short.parseShort(value); return Short.parseShort(value);
} }
public Byte parseByte() { public Byte parseByte() {
String value = parseNumber(); final String value = parseNumber();
return Byte.parseByte(value); return Byte.parseByte(value);
} }
public Character parseCharacter() { public Character parseCharacter() {
String string = parseString(); final String string = parseString();
return string.charAt(0); return string.charAt(0);
} }
@ -78,7 +78,7 @@ public class Parser extends Lexer {
advance(); advance();
} }
String maybeBoolean = characterBuffer.toString(); final String maybeBoolean = characterBuffer.toString();
boolean returnValue; boolean returnValue;
if ((returnValue = maybeBoolean.equals("true")) || maybeBoolean.equals("false")) { if ((returnValue = maybeBoolean.equals("true")) || maybeBoolean.equals("false")) {
return returnValue; return returnValue;
@ -109,10 +109,10 @@ public class Parser extends Lexer {
if (current != '[') { if (current != '[') {
throw new JsonParseException("no list found"); throw new JsonParseException("no list found");
} }
List<Object> list = new ArrayList<>(); final List<Object> list = new ArrayList<>();
advance(); advance();
while (current != -1 && current != ']') { while (current != -1 && current != ']') {
Maybe<Object> maybeValue = parseValue(); final Maybe<Object> maybeValue = parseValue();
if (!maybeValue.isPresent()) { if (!maybeValue.isPresent()) {
break; break;
} else { } else {
@ -125,7 +125,7 @@ public class Parser extends Lexer {
} }
public Map<?, ?> parseObject() { public Map<?, ?> parseObject() {
HashMap<Object, Object> map = new HashMap<>(); final HashMap<Object, Object> map = new HashMap<>();
skipWhitespace(); skipWhitespace();
if (current != '{') { if (current != '{') {
throw new JsonParseException("no map found"); throw new JsonParseException("no map found");
@ -134,7 +134,7 @@ public class Parser extends Lexer {
while (current != -1 && current != '}') { while (current != -1 && current != '}') {
skipWhitespace(); skipWhitespace();
if (current == '"') { if (current == '"') {
String key = parseString(); final String key = parseString();
skipWhitespace(); skipWhitespace();
if (current == ':') { if (current == ':') {
advance(); advance();
@ -142,7 +142,7 @@ public class Parser extends Lexer {
throw new JsonParseException("expected colon"); throw new JsonParseException("expected colon");
} }
skipWhitespace(); skipWhitespace();
Maybe<Object> maybeValue = parseValue(); final Maybe<Object> maybeValue = parseValue();
maybeValue.ifPresent(value -> map.put(key, value)); maybeValue.ifPresent(value -> map.put(key, value));
} }
advance(); advance();
@ -152,7 +152,7 @@ public class Parser extends Lexer {
} }
public Object parseAny() { public Object parseAny() {
Maybe<Object> maybe = parseValue(); final Maybe<Object> maybe = parseValue();
if (maybe.isPresent()) { if (maybe.isPresent()) {
return maybe.get(); return maybe.get();
} else { } else {
@ -161,7 +161,7 @@ public class Parser extends Lexer {
} }
private Maybe<Object> parseValue() { private Maybe<Object> parseValue() {
Object value; final Object value;
skipWhitespace(); skipWhitespace();
switch (current) { switch (current) {
case ']': case ']':
@ -251,8 +251,8 @@ public class Parser extends Lexer {
} }
private void parseEncoded() { private void parseEncoded() {
StringBuilder buf = new StringBuilder(); final StringBuilder buf = new StringBuilder();
char codePoint = parseCodePoint(); final char codePoint = parseCodePoint();
buf.append(codePoint); buf.append(codePoint);
if (Character.isHighSurrogate(codePoint)) { if (Character.isHighSurrogate(codePoint)) {
expect(() -> new JsonParseException("Invalid unicode codepoint at line " + linecount), '\\', 'u'); expect(() -> new JsonParseException("Invalid unicode codepoint at line " + linecount), '\\', 'u');

View file

@ -7,12 +7,20 @@ import java.util.Arrays;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; 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 ClassObject(ConstantPoolEntry[] constantPool, Info[] fieldInfos, Info[] methodInfos) {
private Info[] fieldInfos; this.constantPool = constantPool;
private Info[] methodInfos; this.fieldInfos = fieldInfos;
this.methodInfos = methodInfos;
}
private String getUtf8(int index) { private String getUtf8(int index) {
return ((Utf8Entry) constantPool[index - 1]).getUtf8(); return ((Utf8Entry) constantPool[index - 1]).getUtf8();
@ -41,41 +49,44 @@ public class ClassObject<T> {
public static class Builder<T> { public static class Builder<T> {
private final ClassObject<T> classObject = new ClassObject<>();
private int constantPoolIndex = 0; private int constantPoolIndex = 0;
private int fieldInfoIndex = 0; private int fieldInfoIndex = 0;
private int methodInfoIndex = 0; private int methodInfoIndex = 0;
public ClassObject<T> build() { private ConstantPoolEntry[] constantPool;
return classObject; private Info[] fieldInfos;
private Info[] methodInfos;
public ClassObject build() {
return new ClassObject(constantPool, fieldInfos, methodInfos);
} }
public Builder<T> constantPoolCount(int constantPoolCount) { public Builder<T> constantPoolCount(int constantPoolCount) {
classObject.constantPool = new ConstantPoolEntry[constantPoolCount - 1]; constantPool = new ConstantPoolEntry[constantPoolCount - 1];
return this; return this;
} }
void constantPoolEntry(ConstantPoolEntry entry) { void constantPoolEntry(ConstantPoolEntry entry) {
classObject.constantPool[constantPoolIndex++] = entry; constantPool[constantPoolIndex++] = entry;
} }
public Builder<T> fieldInfoCount(int fieldInfoCount) { public Builder<T> fieldInfoCount(int fieldInfoCount) {
classObject.fieldInfos = new Info[fieldInfoCount]; fieldInfos = new Info[fieldInfoCount];
return this; return this;
} }
public Builder<T> fieldInfo(Info fieldInfo) { public Builder<T> fieldInfo(Info fieldInfo) {
classObject.fieldInfos[fieldInfoIndex++] = fieldInfo; fieldInfos[fieldInfoIndex++] = fieldInfo;
return this; return this;
} }
public Builder<T> methodInfoCount(int methodInfoCount) { public Builder<T> methodInfoCount(int methodInfoCount) {
classObject.methodInfos = new Info[methodInfoCount]; methodInfos = new Info[methodInfoCount];
return this; return this;
} }
public Builder<T> methodInfo(Info methodInfo) { public Builder<T> methodInfo(Info methodInfo) {
classObject.methodInfos[methodInfoIndex++] = methodInfo; methodInfos[methodInfoIndex++] = methodInfo;
return this; return this;
} }
} }

View file

@ -8,8 +8,8 @@ import java.io.IOException;
public class ClassReader extends DataReader { public class ClassReader extends DataReader {
public <T> ClassObject<T> parse(Class<T> type) { public <T> ClassObject parse(Class<T> type) {
DataInputStream in = new DataInputStream(new BufferedInputStream(type.getResourceAsStream(getResourceName(type)))); final DataInputStream in = new DataInputStream(new BufferedInputStream(type.getResourceAsStream(getResourceName(type))));
expect(in, 0xCAFEBABE); expect(in, 0xCAFEBABE);
ClassObject.Builder<T> builder = new ClassObject.Builder<>(); ClassObject.Builder<T> builder = new ClassObject.Builder<>();
@ -19,7 +19,7 @@ public class ClassReader extends DataReader {
readConstantPool(in, builder); readConstantPool(in, builder);
skip(in, 6); // u2 access_flags, u2 this_class, u2 super_class 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;] skip(in, interfacesCount * 2); // interfaces[u2;]
readFields(in, builder); readFields(in, builder);
@ -29,7 +29,7 @@ public class ClassReader extends DataReader {
} }
private <T> void readConstantPool(DataInputStream in, ClassObject.Builder<T> builder) { private <T> void readConstantPool(DataInputStream in, ClassObject.Builder<T> builder) {
int constantPoolCount = readU16(in); final int constantPoolCount = readUnsignedShort(in);
builder.constantPoolCount(constantPoolCount); builder.constantPoolCount(constantPoolCount);
for (int i = 1; i < constantPoolCount; i++) { for (int i = 1; i < constantPoolCount; i++) {
builder.constantPoolEntry(readConstantPoolEntry(in)); builder.constantPoolEntry(readConstantPoolEntry(in));
@ -37,7 +37,7 @@ public class ClassReader extends DataReader {
} }
private <T> void readFields(DataInputStream in, ClassObject.Builder<T> builder) { private <T> void readFields(DataInputStream in, ClassObject.Builder<T> builder) {
int fieldInfoCount = readU16(in); final int fieldInfoCount = readUnsignedShort(in);
builder.fieldInfoCount(fieldInfoCount); builder.fieldInfoCount(fieldInfoCount);
for (int i = 0; i < fieldInfoCount; i++) { for (int i = 0; i < fieldInfoCount; i++) {
builder.fieldInfo(readField(in)); builder.fieldInfo(readField(in));
@ -45,7 +45,7 @@ public class ClassReader extends DataReader {
} }
private <T> void readMethods(DataInputStream in, ClassObject.Builder<T> builder) { private <T> void readMethods(DataInputStream in, ClassObject.Builder<T> builder) {
int methodInfoCount = readU16(in); final int methodInfoCount = readUnsignedShort(in);
builder.methodInfoCount(methodInfoCount); builder.methodInfoCount(methodInfoCount);
for (int i = 0; i < methodInfoCount; i++) { for (int i = 0; i < methodInfoCount; i++) {
builder.methodInfo(readMethod(in)); builder.methodInfo(readMethod(in));
@ -53,7 +53,7 @@ public class ClassReader extends DataReader {
} }
private <T> Info readField(DataInputStream in) { 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++) { for (int i = 0; i < fieldInfo.getAttributesCount(); i++) {
fieldInfo.add(readAttribute(in)); fieldInfo.add(readAttribute(in));
} }
@ -62,7 +62,7 @@ public class ClassReader extends DataReader {
} }
private <T> Info readMethod(DataInputStream in) { 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++) { for (int i = 0; i < methodInfo.getAttributesCount(); i++) {
methodInfo.add(readAttribute(in)); methodInfo.add(readAttribute(in));
} }
@ -71,9 +71,9 @@ public class ClassReader extends DataReader {
} }
private AttributeInfo readAttribute(DataInputStream in) { private AttributeInfo readAttribute(DataInputStream in) {
int attributeNameIndex = readU16(in); final int attributeNameIndex = readUnsignedShort(in);
int attributeLength = readS32(in); final int attributeLength = readS32(in);
byte[] info; final byte[] info;
if (attributeLength > 0) { if (attributeLength > 0) {
info = new byte[attributeLength]; info = new byte[attributeLength];
try { try {
@ -87,32 +87,32 @@ public class ClassReader extends DataReader {
return new AttributeInfo(attributeNameIndex, info); return new AttributeInfo(attributeNameIndex, info);
} }
private <T> ConstantPoolEntry readConstantPoolEntry(DataInputStream in) { private ConstantPoolEntry readConstantPoolEntry(DataInputStream in) {
byte tag = readByte(in); final byte tag = readByte(in);
switch (tag) { 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 2: throw new IllegalStateException("2: invalid classpool tag");
case 3: return new IntEntry(readS32(in)); case 3: return new IntEntry(readS32(in));
case 4: return new FloatEntry(readF32(in)); case 4: return new FloatEntry(readF32(in));
case 5: return new LongEntry(readS64(in)); case 5: return new LongEntry(readS64(in));
case 6: return new DoubleEntry(readF64(in)); case 6: return new DoubleEntry(readF64(in));
case 7: return new ClassEntry(readU16(in)); case 7: return new ClassEntry(readUnsignedShort(in));
case 8: return new StringEntry(readU16(in)); case 8: return new StringEntry(readUnsignedShort(in));
case 9: return new FieldRefEntry(readU16(in), readU16(in)); case 9: return new FieldRefEntry(readUnsignedShort(in), readUnsignedShort(in));
case 10: return new MethodRefEntry(readU16(in), readU16(in)); case 10: return new MethodRefEntry(readUnsignedShort(in), readUnsignedShort(in));
case 11: return new InterfaceMethodRefEntry(readU16(in), readU16(in)); case 11: return new InterfaceMethodRefEntry(readUnsignedShort(in), readUnsignedShort(in));
case 12: return new NameAndTypeEntry(readU16(in), readU16(in)); case 12: return new NameAndTypeEntry(readUnsignedShort(in), readUnsignedShort(in));
case 15: return new MethodHandleEntry(readU16(in), readU16(in)); case 15: return new MethodHandleEntry(readUnsignedShort(in), readUnsignedShort(in));
case 16: return new MethodTypeEntry(readU16(in)); case 16: return new MethodTypeEntry(readUnsignedShort(in));
case 18: return new InvokeDynamicEntry(readU16(in), readU16(in)); case 18: return new InvokeDynamicEntry(readUnsignedShort(in), readUnsignedShort(in));
case 19: return new ModuleEntry(readU16(in)); case 19: return new ModuleEntry(readUnsignedShort(in));
case 20: return new PackageEntry(readU16(in)); case 20: return new PackageEntry(readUnsignedShort(in));
default: throw new IllegalStateException("invalid classpool"); default: throw new IllegalStateException("invalid classpool");
} }
} }
protected <T> String getResourceName(Class<T> type) { 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++) { for (int i = 0; i < typeName.length(); i++) {
if (typeName.charAt(i) == '.') { if (typeName.charAt(i) == '.') {

View file

@ -1,12 +1,13 @@
package nl.sander.jsontoy2.java; package nl.sander.jsontoy2.java;
import nl.sander.jsontoy2.java.constantpool.Utf8Entry;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
/**
* basic IO operations with runtime exceptions
*/
public class DataReader { public class DataReader {
protected long readS64(DataInputStream in) { protected long readS64(DataInputStream in) {
@ -33,7 +34,7 @@ public class DataReader {
} }
} }
protected int readU16(DataInputStream in) { protected int readUnsignedShort(DataInputStream in) {
try { try {
return in.readUnsignedShort(); return in.readUnsignedShort();
} catch (IOException e) { } 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) { protected String readString(DataInputStream in, int length) {
try { try {
byte[] bytes = in.readNBytes(length); byte[] bytes = in.readNBytes(length);

View file

@ -8,11 +8,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class ClassReaderTest { public class ClassReaderTest {
//part of the test
public int field; public int field;
@Test @Test
public void testReadClass() { 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 Field("field", "I")), object.getFields());
assertEquals(Set.of(new Method("<init>", "()V"), new Method("testReadClass", "()V")), object.getMethods()); assertEquals(Set.of(new Method("<init>", "()V"), new Method("testReadClass", "()V")), object.getMethods());
} }