< prev index next >

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

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

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

@@ -35,12 +36,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;

@@ -83,12 +86,10 @@
  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.Lint;
- import com.sun.tools.javac.code.Lint.LintCategory;
  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;

@@ -376,10 +377,12 @@
  
      private boolean enterDone;
  
      protected CompileStates compileStates;
  
+     private boolean hasCodeReflectionModule;
+ 
      /** Construct a new compiler using a shared context.
       */
      @SuppressWarnings("this-escape")
      public JavaCompiler(Context context) {
          this.context = context;

@@ -1052,10 +1055,19 @@
          return !shouldStop(CompileState.ATTR);
      }
  
      public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
          modules.initModules(roots);
+ 
+         if (modules.modulesInitialized()) {
+             // This has to happen precisely here. At this point, we have all we need to
+             // determine whether jdk.incubator.module is part of the module graph
+             // but we have yet to trigger an ENTER event. This gives the code reflection plugin
+             // a window to check whether code reflection should be enabled for this compilation unit.
+             hasCodeReflectionModule = modules.getObservableModule(names.jdk_incubator_code) != null;
+         }
+ 
          if (roots.isEmpty()) {
              enterDone();
          }
          return roots;
      }

@@ -1604,18 +1616,26 @@
              }
  
              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;
  
              if (scanner.hasPatterns) {
-                 env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake);
+                 env.tree = TransPatterns.instance(context)
+                         .translateTopLevelClass(env, env.tree, localMake);
              }
  
              compileStates.put(env, CompileState.TRANSPATTERNS);
  
              if (shouldStop(CompileState.LOWER))

@@ -1659,10 +1679,43 @@
              log.useSource(prev);
          }
  
      }
  
+     Optional<CodeReflectionTransformer> reflectMethods() {
+         if (CodeReflectionSupport.CODE_LAYER != null) {
+             return ServiceLoader.load(CodeReflectionSupport.CODE_LAYER, CodeReflectionTransformer.class)
+                             .findFirst();
+         } else {
+             return Optional.empty();
+         }
+     }
+ 
+     static class CodeReflectionSupport {
+         static final ModuleLayer CODE_LAYER;
+ 
+         static {
+             if (java.lang.module.ModuleFinder.ofSystem().find("jdk.incubator.code").isPresent() &&
+                     !ModuleLayer.boot().findModule("jdk.incubator.code").isPresent()) {
+                 ModuleLayer parent = ModuleLayer.boot();
+                 Configuration cf = parent.configuration()
+                         .resolve(java.lang.module.ModuleFinder.of(), java.lang.module.ModuleFinder.ofSystem(), Set.of("jdk.incubator.code"));
+                 ClassLoader scl = ClassLoader.getSystemClassLoader();
+                 CODE_LAYER = parent.defineModulesWithOneLoader(cf, scl);
+                 Module codeReflectionModule = CODE_LAYER.findModule("jdk.incubator.code").get();
+                 Module jdkCompilerModule = JavaCompiler.class.getModule();
+                 // We need to add exports all jdk.compiler packages so that the plugin can use them
+                 for (String packageName : jdkCompilerModule.getPackages()) {
+                     jdkCompilerModule.addExports(packageName, codeReflectionModule);
+                 }
+             } else {
+                 // if we run javac 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.
       */

@@ -1814,10 +1867,14 @@
  
      public boolean isEnterDone() {
          return enterDone;
      }
  
+     public boolean hasCodeReflectionModule() {
+         return hasCodeReflectionModule;
+     }
+ 
      private Name readModuleName(JavaFileObject fo) {
          return parseAndGetName(fo, t -> {
              JCModuleDecl md = t.getModuleDecl();
  
              return md != null ? TreeInfo.fullName(md.getName()) : null;
< prev index next >