Annotation processor cleanup

This commit is contained in:
Anuken
2020-01-22 12:24:00 -05:00
parent 85e0103ff8
commit 5e977312a7
7 changed files with 202 additions and 231 deletions
@@ -14,43 +14,20 @@ import javax.tools.Diagnostic.*;
import javax.tools.*; import javax.tools.*;
import java.util.*; import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults") @SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults")
public class AssetsAnnotationProcessor extends AbstractProcessor{ public class AssetsAnnotationProcessor extends BaseProcessor{
/** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private String path; private String path;
private int round;
@Override @Override
public synchronized void init(ProcessingEnvironment processingEnv){ public void process(RoundEnvironment env) throws Exception{
super.init(processingEnv); path = Fi.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
//put all relevant utils into utils class .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
Utils.typeUtils = processingEnv.getTypeUtils(); .parent().parent().parent().parent().parent().parent().toString();
Utils.elementUtils = processingEnv.getElementUtils(); path = path.replace("%20", " ");
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound");
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){ processSounds("Musics", path + "/assets/music", "arc.audio.Music");
if(round++ != 0) return false; //only process 1 round processUI(env.getElementsAnnotatedWith(StyleDefaults.class));
try{
path = Fi.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
.parent().parent().parent().parent().parent().parent().toString();
path = path.replace("%20", " ");
processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound");
processSounds("Musics", path + "/assets/music", "arc.audio.Music");
processUI(roundEnv.getElementsAnnotatedWith(StyleDefaults.class));
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
} }
void processUI(Set<? extends Element> elements) throws Exception{ void processUI(Set<? extends Element> elements) throws Exception{
@@ -0,0 +1,38 @@
package mindustry.annotations;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public abstract class BaseProcessor extends AbstractProcessor{
/** Name of the base package to put all the generated classes. */
public static final String packageName = "mindustry.gen";
private int round;
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv);
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override
public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
process(roundEnv);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return true;
}
public abstract void process(RoundEnvironment env) throws Exception;
}
@@ -14,109 +14,86 @@ import java.lang.reflect.*;
import java.util.*; import java.util.*;
import java.util.zip.*; import java.util.zip.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Serialize") @SupportedAnnotationTypes("mindustry.annotations.Annotations.Serialize")
public class SerializeAnnotationProcessor extends AbstractProcessor{ public class SerializeAnnotationProcessor extends BaseProcessor{
/** Target class name. */ /** Target class name. */
private static final String className = "Serialization"; private static final String className = "Serialization";
/** Name of the base package to put all the generated classes. */ /** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private static final String data = "eJztV0tvGzcQvvfQ3zDRIeDCKhsbQVDUsgP5UViH2IHl9BIEBsUdSYxX3C3Jlawm+XH9Z53hUg/bkuOmOfRQwfDuDme++ebBWe6PfwU3/wTwUU2VLJQdSYfDAnWQvxkschjCAUyMzWtPetJikF2nzzG8deXU5OjkW6VvMPTRGVWYP0mgC+W9HGE4Qbp1mEcg0Zo5E9C1sn2AofQYulqj92ZQoAiuxqVc2Loo2iCU03JYWy2PS+v3OndJNF7bDW1rSnk0D3hUD4foDjNRtWGQwU+HQIGZoajAWB+U1VgOYROOZx+Wgm4eMzJ7ghpoyo14Cl5FsQ2I4PsPcE2/XXpssk7kOMw6mEJe9KXxXZu70uTM4Jjz2Hl9CJ79xCc5LN25mqBoqUZPVosy9DEEY0eebnTtMKZ5iaDddgRd2oA2MGO+XqIvi2mq0xJAqQ0ARHzA8dncywWar91QaZwanMkUS7eqCqNVMKW9x+qRuO6wug3R8GGLvsEwLnMYMZBS6z3XrIgWidYhLgYfyQ50IyKrkZbGTssbjHU4Lh1KVVWbvaUNEf8fUFXYX+rt7vnJ5UXv5Lp3Et30g6NagDK55RZpHrNoyUaxwx+PyA+XLtZCaYBabSpoOzlptttX0uM8oen7aJsqnhLkkixmyPlFjlLe1kL0a/ER6YVis4UXKO2YCbYyNkCBnBQv6ToKY5Gt9kauAveZxVkjYc2fYe8DT4bSCTY2tP5iny4dxuGbnQPY4+3Cxu9N1GdODJAJcTxWTmmaOzI3IxOEl5ok3SBM1obdVxl0OvAyA9iB7Zq0uNtoM9cvy9gpvLoIiXAjW+1mnwZi7Ht5pDy+enlc8k5Fq+kqmG8EpBnQIEn8o1aFp25a/C66B60sgzB25Sx6uaxtMBM8vdVYMbBoHakc3r3rnchYvjhdiBGDM1csPD4cMr3Sc8ZSGHVtuJ+X/e8Xk2TZcKLFOtR2rVYizM8EdDqpwlxkDJZKeCcnUfYLl4+f2MFEhbG8pE0uMhqXt4Gntk/hM3Ti8k0JTSgM8zCWqg7LKPiyWcurKYr1PDaYi0x+Wi08gVaOkdYT85paa+Enbubo4NTWE3QRvtO87eg1Qy/gWeluerQd47w9BCRSsHWdfd6XebGcGptMoKw58Dhe4IwrXJYFKkspEKnYfImdRB0R7+GAasezjRIXamdhSP2M+1/rjv7cB5xI5Zya67KaN2BteNFOFvE2CtPUYObJxbN/1Sxb9hw8f/7dgbsMnKoMcAbjlIezWAcecJRxkmHcGacFTmg48xrLuYBnyuUzerl185y8UPkW6YbPn+HZWFJhtmlmMSKUY+XfUC8m8NgBG52uDeXrVFnYhv3Py3u9sb7X9wu8eMUE9x1GArUoAW0rNyVw42r3WwfwanDQHx1+9FhcMYii4y6E/6fvf3T6UiaZLA3BtXO9Zvvf0Xn2MahNEfmv1unr42peYe9Cxk+chD6gU5qcNla8/GQbSwfhJyvXvslmpC2oxOXAUIe9TgegXfgVXizXOSxN4RSlW9nEnK4eGzsGolO9pw+6xXC6d/pa0yDBzs7db6ZHGEczPgSbO+88qBpVMYjSbH/Trgn0vUM8+oE+O67otMbt8uWHvwGqGwCj"; private static final String data = "eJztV0tvGzcQvvfQ3zDRIeDCKhsbQVDUsgP5UViH2IHl9BIEBsUdSYxX3C3Jlawm+XH9Z53hUg/bkuOmOfRQwfDuDme++ebBWe6PfwU3/wTwUU2VLJQdSYfDAnWQvxkschjCAUyMzWtPetJikF2nzzG8deXU5OjkW6VvMPTRGVWYP0mgC+W9HGE4Qbp1mEcg0Zo5E9C1sn2AofQYulqj92ZQoAiuxqVc2Loo2iCU03JYWy2PS+v3OndJNF7bDW1rSnk0D3hUD4foDjNRtWGQwU+HQIGZoajAWB+U1VgOYROOZx+Wgm4eMzJ7ghpoyo14Cl5FsQ2I4PsPcE2/XXpssk7kOMw6mEJe9KXxXZu70uTM4Jjz2Hl9CJ79xCc5LN25mqBoqUZPVosy9DEEY0eebnTtMKZ5iaDddgRd2oA2MGO+XqIvi2mq0xJAqQ0ARHzA8dncywWar91QaZwanMkUS7eqCqNVMKW9x+qRuO6wug3R8GGLvsEwLnMYMZBS6z3XrIgWidYhLgYfyQ50IyKrkZbGTssbjHU4Lh1KVVWbvaUNEf8fUFXYX+rt7vnJ5UXv5Lp3Et30g6NagDK55RZpHrNoyUaxwx+PyA+XLtZCaYBabSpoOzlptttX0uM8oen7aJsqnhLkkixmyPlFjlLe1kL0a/ER6YVis4UXKO2YCbYyNkCBnBQv6ToKY5Gt9kauAveZxVkjYc2fYe8DT4bSCTY2tP5iny4dxuGbnQPY4+3Cxu9N1GdODJAJcTxWTmmaOzI3IxOEl5ok3SBM1obdVxl0OvAyA9iB7Zq0uNtoM9cvy9gpvLoIiXAjW+1mnwZi7Ht5pDy+enlc8k5Fq+kqmG8EpBnQIEn8o1aFp25a/C66B60sgzB25Sx6uaxtMBM8vdVYMbBoHakc3r3rnchYvjhdiBGDM1csPD4cMr3Sc8ZSGHVtuJ+X/e8Xk2TZcKLFOtR2rVYizM8EdDqpwlxkDJZKeCcnUfYLl4+f2MFEhbG8pE0uMhqXt4Gntk/hM3Ti8k0JTSgM8zCWqg7LKPiyWcurKYr1PDaYi0x+Wi08gVaOkdYT85paa+Enbubo4NTWE3QRvtO87eg1Qy/gWeluerQd47w9BCRSsHWdfd6XebGcGptMoKw58Dhe4IwrXJYFKkspEKnYfImdRB0R7+GAasezjRIXamdhSP2M+1/rjv7cB5xI5Zya67KaN2BteNFOFvE2CtPUYObJxbN/1Sxb9hw8f/7dgbsMnKoMcAbjlIezWAcecJRxkmHcGacFTmg48xrLuYBnyuUzerl185y8UPkW6YbPn+HZWFJhtmlmMSKUY+XfUC8m8NgBG52uDeXrVFnYhv3Py3u9sb7X9wu8eMUE9x1GArUoAW0rNyVw42r3WwfwanDQHx1+9FhcMYii4y6E/6fvf3T6UiaZLA3BtXO9Zvvf0Xn2MahNEfmv1unr42peYe9Cxk+chD6gU5qcNla8/GQbSwfhJyvXvslmpC2oxOXAUIe9TgegXfgVXizXOSxN4RSlW9nEnK4eGzsGolO9pw+6xXC6d/pa0yDBzs7db6ZHGEczPgSbO+88qBpVMYjSbH/Trgn0vUM8+oE+O67otMbt8uWHvwGqGwCj";
private int round;
@Override @Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){ public void process(RoundEnvironment env) throws Exception{
if(round++ != 0) return false; //only process 1 round Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Serialize.class));
try{ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class)); classBuilder.addStaticBlock(CodeBlock.of(new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data)))).readUTF()));
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning);
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
classBuilder.addStaticBlock(CodeBlock.of(new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data)))).readUTF()));
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning);
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC); for(TypeElement elem : elements){
TypeName type = TypeName.get(elem.asType());
String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1);
for(TypeElement elem : elements){ TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
TypeName type = TypeName.get(elem.asType()); .addSuperinterface(ParameterizedTypeName.get(
String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1); ClassName.bestGuess("arc.Settings.TypeSerializer"), type));
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("") MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
.addSuperinterface(ParameterizedTypeName.get( .returns(void.class)
ClassName.bestGuess("arc.Settings.TypeSerializer"), type)); .addParameter(DataOutput.class, "stream")
.addParameter(type, "object")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write") MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
.returns(void.class) .returns(type)
.addParameter(DataOutput.class, "stream") .addParameter(DataInput.class, "stream")
.addParameter(type, "object") .addException(IOException.class)
.addException(IOException.class) .addModifiers(Modifier.PUBLIC);
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read") readMethod.addStatement("$L object = new $L()", type, type);
.returns(type)
.addParameter(DataInput.class, "stream")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
readMethod.addStatement("$L object = new $L()", type, type); List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem));
for(VariableElement field : fields){
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE))
continue;
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem)); String name = field.getSimpleName().toString();
for(VariableElement field : fields){ String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.');
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
continue;
String name = field.getSimpleName().toString(); if(field.asType().getKind().isPrimitive()){
String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.'); writeMethod.addStatement("stream.write" + capName + "(object." + name + ")");
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1); readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
}else{
if(field.asType().getKind().isPrimitive()){ writeMethod.addStatement("arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")");
writeMethod.addStatement("stream.write" + capName + "(object." + name + ")"); readMethod.addStatement("object." + name + " = (" + typeName + ")arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)");
readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
}else{
writeMethod.addStatement("arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")");
readMethod.addStatement("object." + name + " = (" + typeName + ")arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)");
}
} }
readMethod.addStatement("return object");
serializer.addMethod(writeMethod.build());
serializer.addMethod(readMethod.build());
method.addStatement("arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
name(writeMethod, "write" + simpleTypeName);
name(readMethod, "read" + simpleTypeName);
writeMethod.addModifiers(Modifier.STATIC);
readMethod.addModifiers(Modifier.STATIC);
classBuilder.addMethod(writeMethod.build());
classBuilder.addMethod(readMethod.build());
} }
classBuilder.addMethod(method.build()); readMethod.addStatement("return object");
//write result serializer.addMethod(writeMethod.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer); serializer.addMethod(readMethod.build());
return true; method.addStatement("arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
}catch(Exception e){
e.printStackTrace(); name(writeMethod, "write" + simpleTypeName);
throw new RuntimeException(e); name(readMethod, "read" + simpleTypeName);
writeMethod.addModifiers(Modifier.STATIC);
readMethod.addModifiers(Modifier.STATIC);
classBuilder.addMethod(writeMethod.build());
classBuilder.addMethod(readMethod.build());
} }
}
@Override classBuilder.addMethod(method.build());
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv); //write result
//put all relevant utils into utils class JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
} }
static void name(MethodSpec.Builder builder, String name){ static void name(MethodSpec.Builder builder, String name){
@@ -17,148 +17,126 @@ import java.util.Set;
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. * Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
* It would be nice if Java didn't make crazy hacks like this necessary. * It would be nice if Java didn't make crazy hacks like this necessary.
*/ */
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({ @SupportedAnnotationTypes({
"mindustry.annotations.Annotations.Struct" "mindustry.annotations.Annotations.Struct"
}) })
public class StructAnnotationProcessor extends AbstractProcessor{ public class StructAnnotationProcessor extends BaseProcessor{
/** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private int round;
@Override @Override
public synchronized void init(ProcessingEnvironment processingEnv){ public void process(RoundEnvironment env) throws Exception{
super.init(processingEnv); Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Struct.class));
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override for(TypeElement elem : elements){
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{ if(!elem.getSimpleName().toString().endsWith("Struct")){
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Struct.class)); Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
continue;
}
for(TypeElement elem : elements){ String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length());
String structParam = structName.toLowerCase();
if(!elem.getSimpleName().toString().endsWith("Struct")){ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem); .addModifiers(Modifier.FINAL, Modifier.PUBLIC);
try{
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements());
int structSize = variables.stream().mapToInt(StructAnnotationProcessor::varSize).sum();
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){
Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
continue; continue;
} }
String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length()); //obtain type which will be stored
String structParam = structName.toLowerCase(); Class<?> structType = typeForSize(structSize);
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName) //[constructor] get(fields...) : structType
.addModifiers(Modifier.FINAL, Modifier.PUBLIC); MethodSpec.Builder constructor = MethodSpec.methodBuilder("get")
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType);
try{ StringBuilder cons = new StringBuilder();
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements()); StringBuilder doc = new StringBuilder();
int structSize = variables.stream().mapToInt(StructAnnotationProcessor::varSize).sum(); doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){ int offset = 0;
Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem); for(VariableElement var : variables){
continue; int size = varSize(var);
} TypeName varType = TypeName.get(var.asType());
String varName = var.getSimpleName().toString();
//obtain type which will be stored //add val param to constructor
Class<?> structType = typeForSize(structSize); constructor.addParameter(varType, varName);
//[constructor] get(fields...) : structType //[get] field(structType) : fieldType
MethodSpec.Builder constructor = MethodSpec.methodBuilder("get") MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType); .returns(varType)
.addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value");
StringBuilder cons = new StringBuilder(); //[getter]
StringBuilder doc = new StringBuilder(); if(varType == TypeName.BOOLEAN){
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n"); //bools: single bit, is simplified
getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset);
int offset = 0; }else if(varType == TypeName.FLOAT){
for(VariableElement var : variables){ //floats: need conversion
int size = varSize(var); getter.addStatement("return Float.intBitsToFloat((int)(($L >>> $L) & $L))", structParam, offset, bitString(size, structTotalSize));
TypeName varType = TypeName.get(var.asType()); }else{
String varName = var.getSimpleName().toString(); //bytes, shorts, chars, ints
getter.addStatement("return ($T)(($L >>> $L) & $L)", varType, structParam, offset, bitString(size, structTotalSize));
//add val param to constructor
constructor.addParameter(varType, varName);
//[get] field(structType) : fieldType
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(varType)
.addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value");
//[getter]
if(varType == TypeName.BOOLEAN){
//bools: single bit, is simplified
getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset);
}else if(varType == TypeName.FLOAT){
//floats: need conversion
getter.addStatement("return Float.intBitsToFloat((int)(($L >>> $L) & $L))", structParam, offset, bitString(size, structTotalSize));
}else{
//bytes, shorts, chars, ints
getter.addStatement("return ($T)(($L >>> $L) & $L)", varType, structParam, offset, bitString(size, structTotalSize));
}
//[setter] + [constructor building]
if(varType == TypeName.BOOLEAN){
cons.append(" | (").append(varName).append(" ? ").append("1L << ").append(offset).append("L : 0)");
//bools: single bit, needs special case to clear things
setter.beginControlFlow("if(value)");
setter.addStatement("return ($T)(($L & ~(1L << $LL)))", structType, structParam, offset);
setter.nextControlFlow("else");
setter.addStatement("return ($T)(($L & ~(1L << $LL)) | (1L << $LL))", structType, structParam, offset, offset);
setter.endControlFlow();
}else if(varType == TypeName.FLOAT){
cons.append(" | (").append("(").append(structType).append(")").append("Float.floatToIntBits(").append(varName).append(") << ").append(offset).append("L)");
//floats: need conversion
setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}else{
cons.append(" | (((").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)").append(" & ").append(bitString(offset, size, structTotalSize)).append(")");
//bytes, shorts, chars, ints
setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}
doc.append("<br> ").append(varName).append(" [").append(offset).append("..").append(size + offset).append("]\n");
//add finished methods
classBuilder.addMethod(getter.build());
classBuilder.addMethod(setter.build());
offset += size;
} }
classBuilder.addJavadoc(doc.toString()); //[setter] + [constructor building]
if(varType == TypeName.BOOLEAN){
cons.append(" | (").append(varName).append(" ? ").append("1L << ").append(offset).append("L : 0)");
//add constructor final statement + add to class and build //bools: single bit, needs special case to clear things
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3)); setter.beginControlFlow("if(value)");
classBuilder.addMethod(constructor.build()); setter.addStatement("return ($T)(($L & ~(1L << $LL)))", structType, structParam, offset);
setter.nextControlFlow("else");
setter.addStatement("return ($T)(($L & ~(1L << $LL)) | (1L << $LL))", structType, structParam, offset, offset);
setter.endControlFlow();
}else if(varType == TypeName.FLOAT){
cons.append(" | (").append("(").append(structType).append(")").append("Float.floatToIntBits(").append(varName).append(") << ").append(offset).append("L)");
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer); //floats: need conversion
}catch(IllegalArgumentException e){ setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
e.printStackTrace(); }else{
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem); cons.append(" | (((").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)").append(" & ").append(bitString(offset, size, structTotalSize)).append(")");
//bytes, shorts, chars, ints
setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}
doc.append("<br> ").append(varName).append(" [").append(offset).append("..").append(size + offset).append("]\n");
//add finished methods
classBuilder.addMethod(getter.build());
classBuilder.addMethod(setter.build());
offset += size;
} }
}
return true; classBuilder.addJavadoc(doc.toString());
}catch(Exception e){
e.printStackTrace(); //add constructor final statement + add to class and build
throw new RuntimeException(e); constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
classBuilder.addMethod(constructor.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
}catch(IllegalArgumentException e){
e.printStackTrace();
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
}
} }
} }
static String bitString(int offset, int size, int totalSize){ static String bitString(int offset, int size, int totalSize){
+3 -1
View File
@@ -308,8 +308,10 @@ project(":annotations"){
apply plugin: "java" apply plugin: "java"
dependencies{ dependencies{
def arcVersion = "e287fdce0449a87fb15599c67b5167ac0273bcb6"
compile 'com.squareup:javapoet:1.11.0' compile 'com.squareup:javapoet:1.11.0'
compile "com.github.Anuken.Arc:arc-core:b77767039334b2658f44d69e72d1ef6bc84f95b0" compile "com.github.Anuken.Arc:arc-core:$arcVersion"
compile files("${System.getProperty('java.home')}/../lib/tools.jar") compile files("${System.getProperty('java.home')}/../lib/tools.jar")
} }
} }
+1 -2
View File
@@ -32,7 +32,6 @@ import java.util.*;
import static arc.Core.settings; import static arc.Core.settings;
@SuppressWarnings("unchecked")
public class Vars implements Loadable{ public class Vars implements Loadable{
/** Whether to load locales.*/ /** Whether to load locales.*/
public static boolean loadLocales = true; public static boolean loadLocales = true;
@@ -60,7 +59,7 @@ public class Vars implements Loadable{
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json"; public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json";
/** URL to the JSON file containing all the BE servers. Only queried in BE. */ /** URL to the JSON file containing all the BE servers. Only queried in BE. */
public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json"; public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
/** URL the links to the wiki's modding guide.*/ /** URL of the github issue report template.*/
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md"; public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md";
/** list of built-in servers.*/ /** list of built-in servers.*/
public static final Array<String> defaultServers = Array.with(); public static final Array<String> defaultServers = Array.with();
+1 -1
View File
@@ -1,3 +1,3 @@
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=bf5f253d458e0b8bddf9efcc3642a644f4b48fb6 archash=e287fdce0449a87fb15599c67b5167ac0273bcb6