added testassertions and fixed more stuff

This commit is contained in:
Sander Hautvast 2020-11-20 17:53:19 +01:00
parent 33400c7268
commit 958a5b3fd7
5 changed files with 84 additions and 45 deletions

View file

@ -12,7 +12,7 @@ public final class BeeMethod extends CodeContainer {
private final Class<?> returnType; private final Class<?> returnType;
BeeMethod(String name, Set<MethodAccessFlag> accessFlags, public BeeMethod(String name, Set<MethodAccessFlag> accessFlags,
Set<BeeParameter> formalParameters, Set<BeeParameter> formalParameters,
Class<?> returnType, List<CodeLine> code) { Class<?> returnType, List<CodeLine> code) {
this.name = name; this.name = name;
@ -43,4 +43,19 @@ public final class BeeMethod extends CodeContainer {
* -If the name of the method is <clinit>, then the descriptor must denote avoid method, and, in a class file whose version number is 51.0 or above,a method that takes no arguments * -If the name of the method is <clinit>, then the descriptor must denote avoid method, and, in a class file whose version number is 51.0 or above,a method that takes no arguments
*/ */
} }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
BeeMethod beeMethod = (BeeMethod) o;
return name.equals(beeMethod.name) &&
returnType.equals(beeMethod.returnType);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), name, returnType);
}
} }

View file

@ -3,10 +3,7 @@ package nl.sander.beejava.apiv2;
import nl.sander.beejava.TypeMapper; import nl.sander.beejava.TypeMapper;
import nl.sander.beejava.flags.MethodAccessFlag; import nl.sander.beejava.flags.MethodAccessFlag;
import java.util.HashSet; import java.util.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -54,4 +51,17 @@ public abstract class CodeContainer {
} }
public abstract boolean isConstructor(); public abstract boolean isConstructor();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CodeContainer that = (CodeContainer) o;
return formalParameters.equals(that.formalParameters);
}
@Override
public int hashCode() {
return Objects.hash(formalParameters);
}
} }

View file

@ -16,7 +16,7 @@ import java.util.regex.Pattern;
public class SourceCompiler { public class SourceCompiler {
private final static Pattern firstBlanksplitter = Pattern.compile("(.+?) (.+)"); private final static Pattern firstBlanksplitter = Pattern.compile("(.+?) (.+)");
private final static Pattern parensplitter = Pattern.compile("(.+?)\\((.*?)\\)"); private final static Pattern parensplitter = Pattern.compile("(.+?)\\((.*?)\\)");
private final static Pattern returntypesplitter = Pattern.compile("(.+?)->(.*?)"); private final static Pattern returntypesplitter = Pattern.compile("->");
private final String sourcecode; private final String sourcecode;
private final List<Instruction> instructions = new ArrayList<>(); private final List<Instruction> instructions = new ArrayList<>();
private int currentLine = 0; private int currentLine = 0;
@ -34,14 +34,13 @@ public class SourceCompiler {
BeeSource beeSource = new nl.sander.beejava.apiv2.BeeSource(); BeeSource beeSource = new nl.sander.beejava.apiv2.BeeSource();
for (currentLine = 0; currentLine < instructions.size(); currentLine++) { for (currentLine = 0; currentLine < instructions.size(); ) {
Instruction ins = instructions.get(currentLine); Instruction ins = instructions.get(currentLine);
if (currentLine == 0) { if (currentLine == 0) {
parseClassDeclaration(ins, beeSource); parseClassDeclaration(ins, beeSource);
} else { } else {
parseInstruction(ins, beeSource); parseInstruction(ins, beeSource);
} }
currentLine += 1;
} }
return beeSource; return beeSource;
@ -61,15 +60,11 @@ public class SourceCompiler {
} }
private BeeMethod parseMethod(String text) { private BeeMethod parseMethod(String text) {
String[] tokens = split(text, returntypesplitter); String[] tokens = returntypesplitter.split(text);
final String first; final String first;
final Class<?> returnType; final Class<?> returnType;
if (tokens.length > 0) { if (tokens.length > 1) {
try { returnType = getType(tokens[1].trim());
returnType = Class.forName(tokens[1].trim());
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Not a valid type: " + tokens[1].trim());
}
first = tokens[0].trim(); first = tokens[0].trim();
} else { } else {
first = text; first = text;
@ -89,29 +84,31 @@ public class SourceCompiler {
String[] nameParams = split(flagsNameParameters[i], parensplitter); String[] nameParams = split(flagsNameParameters[i], parensplitter);
Set<BeeParameter> parameters = new HashSet<>(); Set<BeeParameter> parameters = new HashSet<>();
String methodName = ""; String methodName=null;
if (nameParams.length > 0) { if (nameParams.length > 0) {
methodName = nameParams[0]; methodName = nameParams[0];
if (nameParams[1].length() > 0) {
String params = nameParams[1]; String params = nameParams[1];
String[] paramTokens = params.split(","); String[] paramTokens = params.split(",");
for (String paramToken : paramTokens) { for (String paramToken : paramTokens) {
String[] declaration = paramToken.trim().split(" "); String[] declaration = paramToken.trim().split(" ");
String type = declaration[0]; String type = declaration[0];
String name = declaration[1]; String name = declaration[1];
try {
parameters.add(new BeeParameter(getType(type), name)); parameters.add(new BeeParameter(getType(type), name));
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("field type " + type + " not found");
} }
} }
} }
if (methodName==null){
throw new IllegalArgumentException("method name not found");
}
currentLine += 1; currentLine += 1;
List<CodeLine> lines = new ArrayList<>(); List<CodeLine> lines = new ArrayList<>();
Instruction nextInstruction = instructions.get(currentLine); Instruction nextInstruction = instructions.get(currentLine);
while (nextInstruction instanceof CodeLine) { while (nextInstruction instanceof CodeLine) {
lines.add((CodeLine) nextInstruction); lines.add((CodeLine) nextInstruction);
currentLine += 1; currentLine += 1;
if (currentLine >= instructions.size()){ if (currentLine >= instructions.size()) {
break; // too tired to think break; // too tired to think
} }
nextInstruction = instructions.get(currentLine); nextInstruction = instructions.get(currentLine);
@ -121,14 +118,6 @@ public class SourceCompiler {
return new BeeMethod(methodName, flags, parameters, returnType, lines); return new BeeMethod(methodName, flags, parameters, returnType, lines);
} }
private Class<?> getType(String type) throws ClassNotFoundException {
return switch (type) {
case "int" -> int.class;
case "double" -> double.class;
default -> Class.forName(type);
};
}
private BeeConstructor parseConstructor(String text) { private BeeConstructor parseConstructor(String text) {
String[] tokens = split(text, parensplitter); String[] tokens = split(text, parensplitter);
String flag = tokens[0]; String flag = tokens[0];
@ -167,7 +156,7 @@ public class SourceCompiler {
String type = null; String type = null;
String name = null; String name = null;
for (String token : tokens) { for (String token : tokens) {
Optional<FieldAccessFlag> maybeFlag = FieldAccessFlag.get(token); Optional<FieldAccessFlag> maybeFlag = FieldAccessFlag.get(token.toUpperCase());
if (maybeFlag.isPresent()) { if (maybeFlag.isPresent()) {
flags.add(maybeFlag.get()); flags.add(maybeFlag.get());
} else { } else {
@ -178,11 +167,8 @@ public class SourceCompiler {
} }
} }
} }
try { currentLine += 1;
return new BeeField(flags, Class.forName(type), name); return new BeeField(flags, getType(type), name);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("field type " + type + " not found");
}
} }
private void parseClassDeclaration(Instruction firstLine, BeeSource beeSource) { private void parseClassDeclaration(Instruction firstLine, BeeSource beeSource) {
@ -205,6 +191,7 @@ public class SourceCompiler {
} else { } else {
throw new IllegalArgumentException("class must start with 'class name(target.jdk.version)'"); throw new IllegalArgumentException("class must start with 'class name(target.jdk.version)'");
} }
currentLine += 1;
} }
private Instruction compileLine(String line) { private Instruction compileLine(String line) {
@ -245,4 +232,15 @@ public class SourceCompiler {
} }
} }
private Class<?> getType(String type) {
try {
return switch (type) {
case "int" -> int.class;
case "double" -> double.class;
default -> Class.forName(type);
};
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Not a valid type: " + type);
}
}
} }

View file

@ -1,14 +1,30 @@
package nl.sander.beejava; package nl.sander.beejava;
import nl.sander.beejava.apiv2.BeeSource; import nl.sander.beejava.apiv2.*;
import nl.sander.beejava.apiv2.SourceCompiler; import nl.sander.beejava.flags.AccessFlags;
import nl.sander.beejava.flags.ClassAccessFlags;
import nl.sander.beejava.flags.FieldAccessFlag;
import nl.sander.beejava.flags.MethodAccessFlag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class SourceCompilerTest { public class SourceCompilerTest {
@Test @Test
public void test(){ public void test() {
BeeSource beeSource = new SourceCompiler(TestData2.simpleBean).doCompile(); BeeSource beeSource = new SourceCompiler(TestData2.simpleBean).doCompile();
System.out.println(beeSource); assertEquals("com.acme.SimpleBean", beeSource.getName());
assertEquals(ClassAccessFlags.SUPER.getBytecode() | ClassAccessFlags.PUBLIC.getBytecode(), AccessFlags.combine(beeSource.getAccessFlags()));
assertTrue(beeSource.getFields().contains(new BeeField(Set.of(FieldAccessFlag.PRIVATE), int.class, "value")));
assertEquals(1, beeSource.getConstructors().size());
Set<BeeMethod> methods = beeSource.getMethods();
assertEquals(2, methods.size());
assertTrue(methods.contains(new BeeMethod("getValue", Set.of(MethodAccessFlag.PUBLIC), Set.of(), int.class, List.of())));
assertTrue(methods.contains(new BeeMethod("setValue", Set.of(MethodAccessFlag.PUBLIC), Set.of(new BeeParameter(int.class, "newValue")), Void.TYPE, List.of())));
} }
} }

View file

@ -4,7 +4,7 @@ public class TestData2 {
public final static String simpleBean= """ public final static String simpleBean= """
class com.acme.SimpleBean(V15) class com.acme.SimpleBean(V15)
field public final int value field private int value
constructor public() constructor public()
INVOKE super() INVOKE super()
RETURN RETURN