/* * Copyright (c) 2002-2008 LWJGL Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'LWJGL' nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.lwjgl.util.generator.opengl; import org.lwjgl.util.generator.Alternate; import org.lwjgl.util.generator.CachedReference; import org.lwjgl.util.generator.Utils; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.nio.file.Path; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.util.ElementFilter; import static org.lwjgl.util.generator.GeneratorVisitor.saveGeneratedJavaSource; import static org.lwjgl.util.generator.Utils.getRequiredOption; import static org.lwjgl.util.generator.Utils.await; import static org.lwjgl.util.generator.Utils.spawn; /** * Generator tool for creating the References class * * @author elias_naur * @version $Revision: 3237 $ $Id: ReferencesGeneratorProcessorFactory.java 3237 * 2009-09-08 15:07:15Z spasi $ */ @SupportedAnnotationTypes({ "*" }) @SupportedSourceVersion(SourceVersion.RELEASE_10) @SupportedOptions({ "genJavaPath", "generatechecks", "contextspecific" }) public final class GLReferencesGeneratorProcessor extends AbstractProcessor { private static final String REFERENCES_CLASS_NAME = "References"; private static final String REFERENCES_PARAMETER_NAME = "references"; private static boolean first_round = true; @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { if ( roundEnv.processingOver() || !first_round ) { System.exit(0); return true; } Map options = processingEnv.getOptions(); Path genJavaPath = Path.of(getRequiredOption(options, "genJavaPath", "a path.")); try { generateReferencesSource(processingEnv, genJavaPath, ElementFilter.typesIn(roundEnv.getRootElements())); first_round = false; return true; } catch (IOException e) { throw new RuntimeException(e); } } private static void generateClearsFromParameters(PrintWriter writer, TypeElement interface_decl, ExecutableElement method) { for ( VariableElement param : method.getParameters() ) { CachedReference cached_reference_annotation = param.getAnnotation(CachedReference.class); if ( cached_reference_annotation != null && cached_reference_annotation.name().length() == 0 ) { Class nio_type = Utils.getNIOBufferType(param.asType()); String reference_name = Utils.getReferenceName(interface_decl, method, param); writer.append("\t\tthis.").append(reference_name).append(" = null;\n"); } } } private static void generateCopiesFromParameters(PrintWriter writer, TypeElement interface_decl, ExecutableElement method) { for ( VariableElement param : method.getParameters() ) { CachedReference cached_reference_annotation = param.getAnnotation(CachedReference.class); if ( cached_reference_annotation != null && cached_reference_annotation.name().length() == 0 ) { Class nio_type = Utils.getNIOBufferType(param.asType()); String reference_name = Utils.getReferenceName(interface_decl, method, param); writer.append("\t\t\tthis.").append(reference_name).append(" = " + REFERENCES_PARAMETER_NAME + ".").append(reference_name).append(";\n"); } } } private static void generateClearsFromMethods(ProcessingEnvironment env, PrintWriter writer, TypeElement interface_decl) { for ( ExecutableElement method : Utils.getMethods(interface_decl) ) { if ( method.getAnnotation(Alternate.class) != null ) { continue; } generateClearsFromParameters(writer, interface_decl, method); } } private static void generateCopiesFromMethods(ProcessingEnvironment env, PrintWriter writer, TypeElement interface_decl) { for ( ExecutableElement method : Utils.getMethods(interface_decl) ) { if ( method.getAnnotation(Alternate.class) != null ) { continue; } generateCopiesFromParameters(writer, interface_decl, method); } } private static void generateReferencesFromParameters(PrintWriter writer, TypeElement interface_decl, ExecutableElement method) { for ( VariableElement param : method.getParameters() ) { CachedReference cached_reference_annotation = param.getAnnotation(CachedReference.class); if ( cached_reference_annotation != null && cached_reference_annotation.name().length() == 0 ) { Class nio_type = Utils.getNIOBufferType(param.asType()); if ( nio_type == null ) { throw new RuntimeException(param + " in method " + method + " in " + interface_decl + " is annotated with " + cached_reference_annotation.annotationType().getSimpleName() + " but the parameter is not a NIO buffer"); } writer.append('\t').append(nio_type.getName()).append(' ').append(Utils.getReferenceName(interface_decl, method, param)).append(";\n"); } } } private static void generateReferencesFromMethods(ProcessingEnvironment env, PrintWriter writer, TypeElement interface_decl) { for ( ExecutableElement method : Utils.getMethods(interface_decl) ) { if ( method.getAnnotation(Alternate.class) != null ) { continue; } generateReferencesFromParameters(writer, interface_decl, method); } } private void generateReferencesSource(ProcessingEnvironment env, Path genJavaPath, Set templates) throws IOException { long startTime = System.currentTimeMillis(); ByteArrayOutputStream writer1 = new ByteArrayOutputStream(); // interesting note: autoFlush does absolutely nothing PrintWriter writer = new PrintWriter(writer1); writer.append("/* MACHINE GENERATED FILE, DO NOT EDIT */\n\n" + "package org.lwjgl.opengl;\n\n" + "class " + REFERENCES_CLASS_NAME + " extends BaseReferences {\n" + "\t" + REFERENCES_CLASS_NAME + "(ContextCapabilities caps) {\n" + "\t\tsuper(caps);\n" + "\t}\n\n"); writer.flush(); templates.parallelStream().parallel().filter(tmpl -> tmpl.getKind().isInterface()).map(interface_decl -> { ByteArrayOutputStream writer2 = new ByteArrayOutputStream(); PrintWriter writer3 = new PrintWriter(writer2); generateReferencesFromMethods(env, writer3, interface_decl); writer3.flush(); return writer2.toByteArray(); }).sequential().forEach(writer1::writeBytes); writer.append("\tvoid copy(" + REFERENCES_CLASS_NAME + " " + REFERENCES_PARAMETER_NAME + ", int mask) {\n" + "\t\tsuper.copy(" + REFERENCES_PARAMETER_NAME + ", mask);\n" + "\t\tif ( (mask & GL11.GL_CLIENT_VERTEX_ARRAY_BIT) != 0 ) {\n"); writer.flush(); templates.parallelStream().parallel().filter(tmpl -> tmpl.getKind().isInterface()).map(interface_decl -> { ByteArrayOutputStream writer2 = new ByteArrayOutputStream(); PrintWriter writer3 = new PrintWriter(writer2); generateCopiesFromMethods(processingEnv, writer3, interface_decl); writer3.flush(); return writer2.toByteArray(); }).sequential().forEach(writer1::writeBytes); writer.append("\t\t}\n" + "\t}\n" + "\tvoid clear() {\n" + "\t\tsuper.clear();\n"); writer.flush(); templates.parallelStream().parallel().filter(tmpl -> tmpl.getKind().isInterface()).map(interface_decl -> { ByteArrayOutputStream writer2 = new ByteArrayOutputStream(); PrintWriter writer3 = new PrintWriter(writer2); generateClearsFromMethods(processingEnv, writer3, interface_decl); writer3.flush(); return writer2.toByteArray(); }).sequential().forEach(writer1::writeBytes); writer.append("\t}\n" + "}\n"); saveGeneratedJavaSource(env.getMessager(), genJavaPath, "org.lwjgl.opengl." + REFERENCES_CLASS_NAME, spawn((Callable) () -> { writer.flush(); return writer1.toByteArray(); }), startTime); } }