< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java

Print this page
@@ -24,10 +24,12 @@
   */
  
  package com.sun.tools.javac.main;
  
  import java.io.*;
+ import java.lang.module.Configuration;
+ import java.lang.reflect.Method;
  import java.nio.file.FileSystemNotFoundException;
  import java.nio.file.InvalidPathException;
  import java.nio.file.ReadOnlyFileSystemException;
  import java.util.Collection;
  import java.util.Comparator;

@@ -36,12 +38,14 @@
  import java.util.HashSet;
  import java.util.LinkedHashMap;
  import java.util.LinkedHashSet;
  import java.util.Map;
  import java.util.MissingResourceException;
+ import java.util.Optional;
  import java.util.Queue;
  import java.util.ResourceBundle;
+ import java.util.ServiceLoader;
  import java.util.Set;
  import java.util.function.Function;
  import java.util.function.ToIntFunction;
  
  import javax.annotation.processing.Processor;

@@ -85,10 +89,12 @@
  import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
  import com.sun.tools.javac.util.Log.WriterKind;
  
  import static com.sun.tools.javac.code.Kinds.Kind.*;
  
+ import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+ 
  import com.sun.tools.javac.resources.CompilerProperties.Errors;
  import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  import com.sun.tools.javac.resources.CompilerProperties.Notes;
  import com.sun.tools.javac.resources.CompilerProperties.Warnings;
  

@@ -765,10 +771,17 @@
       *                containing this class.
       *  @param cdef   The class definition from which code is generated.
       */
      JavaFileObject genCode(Env<AttrContext> env, JCClassDecl cdef) throws IOException {
          try {
+             if (Feature.REFLECT_METHODS.allowedInSource(source)) {
+                 Optional<CodeReflectionTransformer> reflectMethods = reflectMethods();
+                 if (reflectMethods.isPresent()) {
+                     reflectMethods.get().genCode(context, cdef);
+                 }
+             }
+ 
              if (gen.genClass(env, cdef) && (errorCount() == 0))
                  return writer.writeClass(cdef.sym);
          } catch (ClassWriter.PoolOverflow ex) {
              log.error(cdef.pos(), Errors.LimitPool);
          } catch (ClassWriter.StringOverflow ex) {

@@ -1047,10 +1060,11 @@
          return !shouldStop(CompileState.ATTR);
      }
  
      public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
          modules.initModules(roots);
+ 
          if (roots.isEmpty()) {
              enterDone();
          }
          return roots;
      }

@@ -1659,10 +1673,17 @@
              }
  
              if (shouldStop(CompileState.TRANSTYPES))
                  return;
  
+             if (Feature.REFLECT_METHODS.allowedInSource(source)) {
+                 Optional<CodeReflectionTransformer> reflectMethods = reflectMethods();
+                 if (reflectMethods.isPresent()) {
+                     env.tree = reflectMethods.get().translateTopLevelClass(context, env.tree, localMake);
+                 }
+             }
+ 
              env.tree = transTypes.translateTopLevelClass(env.tree, localMake);
              compileStates.put(env, CompileState.TRANSTYPES);
  
              if (shouldStop(CompileState.TRANSPATTERNS))
                  return;

@@ -1714,10 +1735,56 @@
              log.useSource(prev);
          }
  
      }
  
+     Optional<CodeReflectionTransformer> reflectMethods() {
+         return CodeReflectionSupport.CODE_LAYER != null ?
+                 ServiceLoader.load(CodeReflectionSupport.CODE_LAYER, CodeReflectionTransformer.class).findFirst() :
+                 Optional.empty();
+     }
+ 
+     public static class CodeReflectionSupport {
+         public static final ModuleLayer CODE_LAYER;
+ 
+         static {
+             if (ModuleLayer.boot().findModule("jdk.incubator.code").isPresent()) {
+                 // we are in an exploded build, so just use the boot layer
+                 CODE_LAYER = ModuleLayer.boot();
+             } else if (java.lang.module.ModuleFinder.ofSystem().find("jdk.incubator.code").isPresent()) {
+                 // The incubating jdk.incubator.code module is installed, but not in the boot layer
+                 // The module needs to be resolved so the jdk.compiler module can find and use the service provider
+                 // for CodeReflectionTransformer
+                 ModuleLayer parent = ModuleLayer.boot();
+                 // Create a new configuration from the boot layer configuration with the resolved jdk.incubator.code module
+                 Configuration cf = parent.configuration()
+                         .resolve(java.lang.module.ModuleFinder.of(), java.lang.module.ModuleFinder.ofSystem(), Set.of("jdk.incubator.code"));
+                 ClassLoader scl = ClassLoader.getSystemClassLoader();
+                 // Create the code module layer using the new configuration and the system class loader
+                 CODE_LAYER = parent.defineModulesWithOneLoader(cf, scl);
+                 Module codeReflectionModule = CODE_LAYER.findModule("jdk.incubator.code").get();
+                 Module jdkCompilerModule = JavaCompiler.class.getModule();
+                 // Add exports to all jdk.compiler packages so that the jdk.incubator.code module can use them
+                 for (String packageName : jdkCompilerModule.getPackages()) {
+                     jdkCompilerModule.addExports(packageName, codeReflectionModule);
+                 }
+                 // Add exports to all java.base packages so that the jdk.incubator.code module can use them
+                 // We need to do so by calling a method in java.base reflectively
+                 try {
+                     Class<?> codeModuleLayerInit = Class.forName("jdk.internal.access.code.CodeModuleLayerInit");
+                     Method initLayerMethod = codeModuleLayerInit.getDeclaredMethod("initCodeModuleLayer", ModuleLayer.class);
+                     initLayerMethod.invoke(null, CODE_LAYER);
+                 } catch (ReflectiveOperationException ex) {
+                     throw new AssertionError(ex);
+                 }
+             } else {
+                 // If we run in bootstrap mode, there might be no jdk.incubator.code
+                 CODE_LAYER = null;
+             }
+         }
+     }
+ 
      /** Generates the source or class file for a list of classes.
       * The decision to generate a source file or a class file is
       * based upon the compiler's options.
       * Generation stops if an error occurs while writing files.
       */
< prev index next >