diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java
index f506e0068e1..0ca3e301d70 100644
--- a/src/java.base/share/classes/module-info.java
+++ b/src/java.base/share/classes/module-info.java
@@ -162,7 +162,8 @@
jdk.jfr, // participates in preview features
jdk.jlink, // participates in preview features
jdk.jshell, // participates in preview features
- jdk.incubator.code; // participates in preview features
+ jdk.incubator.code, // participates in preview features
+ jdk.incubator.code.proc; // participates in preview features
exports jdk.internal.access to
java.desktop,
java.logging,
diff --git a/src/jdk.compiler/share/classes/module-info.java b/src/jdk.compiler/share/classes/module-info.java
index c0893f560ef..d04b492523d 100644
--- a/src/jdk.compiler/share/classes/module-info.java
+++ b/src/jdk.compiler/share/classes/module-info.java
@@ -239,17 +239,19 @@
jdk.javadoc,
jdk.jshell,
jdk.internal.md,
- jdk.incubator.code;
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.resources to
jdk.jshell;
exports com.sun.tools.javac.code to
jdk.javadoc,
jdk.jshell,
- jdk.incubator.code;
+ jdk.incubator.code,
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.comp to
jdk.javadoc,
jdk.jshell,
- jdk.incubator.code;
+ jdk.incubator.code,
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.file to
jdk.jdeps,
jdk.javadoc;
@@ -262,7 +264,7 @@
jdk.incubator.code;
exports com.sun.tools.javac.model to
jdk.javadoc,
- jdk.incubator.code;
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.parser to
jdk.jshell,
jdk.internal.md;
@@ -273,15 +275,17 @@
jdk.javadoc,
jdk.jshell,
jdk.internal.md,
- jdk.incubator.code;
+ jdk.incubator.code,
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.util to
jdk.jdeps,
jdk.javadoc,
jdk.jshell,
jdk.internal.md,
- jdk.incubator.code;
+ jdk.incubator.code,
+ jdk.incubator.code.proc;
exports com.sun.tools.javac.processing to
- jdk.incubator.code;
+ jdk.incubator.code.proc;
uses javax.annotation.processing.Processor;
uses com.sun.source.util.Plugin;
diff --git a/src/jdk.incubator.code.proc/share/classes/jdk/incubator/code/proc/CodeModelElements.java b/src/jdk.incubator.code.proc/share/classes/jdk/incubator/code/proc/CodeModelElements.java
new file mode 100644
index 00000000000..8d63f5770f2
--- /dev/null
+++ b/src/jdk.incubator.code.proc/share/classes/jdk/incubator/code/proc/CodeModelElements.java
@@ -0,0 +1,78 @@
+package jdk.incubator.code.proc;
+
+import com.sun.tools.javac.api.JavacScope;
+import com.sun.tools.javac.api.JavacTrees;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.comp.Attr;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.util.Context;
+import jdk.incubator.code.dialect.core.CoreOp.FuncOp;
+import jdk.incubator.code.internal.ReflectMethods;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import java.util.Optional;
+
+/**
+ * Utility methods for extracting code models from program elements.
+ */
+public class CodeModelElements {
+
+ final ReflectMethods reflectMethods;
+ final Attr attr;
+ final JavacElements elements;
+ final JavacTrees trees;
+ final TreeMaker make;
+
+ CodeModelElements(ProcessingEnvironment processingEnvironment) {
+ Context context = ((JavacProcessingEnvironment)processingEnvironment).getContext();
+ reflectMethods = ReflectMethods.instance(context);
+ attr = Attr.instance(context);
+ elements = JavacElements.instance(context);
+ trees = JavacTrees.instance(context);
+ make = TreeMaker.instance(context);
+ }
+ /**
+ * Returns the code model of provided executable element (if any).
+ *
+ * If the executable element has a code model then it will be an instance of
+ * {@code java.lang.reflect.code.op.CoreOps.FuncOp}.
+ * Note: due to circular dependencies we cannot refer to the type explicitly.
+ *
+ * @implSpec The default implementation unconditionally returns an empty optional.
+ * @param e the executable element.
+ * @return the code model of the provided executable element (if any).
+ */
+ public Optional createCodeModel(ExecutableElement e) {
+ if (e.getModifiers().contains(Modifier.ABSTRACT) ||
+ e.getModifiers().contains(Modifier.NATIVE)) {
+ return Optional.empty();
+ }
+
+ try {
+ JCMethodDecl methodTree = (JCMethodDecl)elements.getTree(e);
+ JavacScope scope = trees.getScope(trees.getPath(e));
+ ClassSymbol enclosingClass = (ClassSymbol) scope.getEnclosingClass();
+ FuncOp op = attr.runWithAttributedMethod(scope.getEnv(), methodTree,
+ attribBlock -> reflectMethods.getMethodBody(enclosingClass, methodTree, attribBlock, make));
+ return Optional.of(op);
+ } catch (RuntimeException ex) { // ReflectMethods.UnsupportedASTException
+ // some other error occurred when attempting to attribute the method
+ // @@@ better report of error
+ ex.printStackTrace();
+ return Optional.empty();
+ }
+ }
+
+ /**
+ * {@return a new instance of {@code CodeModelElements} for the provided processing environment}
+ * @param processingEnvironment the annotation processing environment
+ */
+ public static CodeModelElements of(ProcessingEnvironment processingEnvironment) {
+ return new CodeModelElements(processingEnvironment);
+ }
+}
diff --git a/src/jdk.incubator.code.proc/share/classes/module-info.java b/src/jdk.incubator.code.proc/share/classes/module-info.java
new file mode 100644
index 00000000000..f1949b1e835
--- /dev/null
+++ b/src/jdk.incubator.code.proc/share/classes/module-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * A module which provides classes and interfaces for obtaining reflective information about
+ * classes and objects.
+ * {@incubating}
+ *
+ * @moduleGraph
+ */
+
+import jdk.internal.javac.ParticipatesInPreview;
+
+@ParticipatesInPreview
+module jdk.incubator.code.proc {
+ requires transitive jdk.compiler;
+ requires transitive jdk.incubator.code;
+
+ exports jdk.incubator.code.proc;
+}
diff --git a/src/jdk.incubator.code/share/classes/jdk/incubator/code/Op.java b/src/jdk.incubator.code/share/classes/jdk/incubator/code/Op.java
index 2496b804d58..3e8c2943d58 100644
--- a/src/jdk.incubator.code/share/classes/jdk/incubator/code/Op.java
+++ b/src/jdk.incubator.code/share/classes/jdk/incubator/code/Op.java
@@ -29,26 +29,13 @@
import java.io.OutputStreamWriter;
import java.io.Writer;
-import com.sun.tools.javac.api.JavacScope;
-import com.sun.tools.javac.api.JavacTrees;
-import com.sun.tools.javac.code.Symbol.ClassSymbol;
-import com.sun.tools.javac.comp.Attr;
-import com.sun.tools.javac.model.JavacElements;
-import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
-import com.sun.tools.javac.tree.TreeMaker;
-import com.sun.tools.javac.util.Context;
import jdk.incubator.code.dialect.core.CoreType;
-import jdk.incubator.code.internal.ReflectMethods;
import jdk.incubator.code.dialect.core.CoreOp.FuncOp;
import jdk.incubator.code.dialect.core.FunctionType;
import jdk.incubator.code.dialect.java.MethodRef;
import jdk.incubator.code.extern.OpWriter;
import jdk.internal.access.SharedSecrets;
-import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.Modifier;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
@@ -568,43 +555,4 @@ private static Optional createCodeModel(Method method) {
throw new RuntimeException(e);
}
}
-
- /**
- * Returns the code model of provided executable element (if any).
- *
- * If the executable element has a code model then it will be an instance of
- * {@code java.lang.reflect.code.op.CoreOps.FuncOp}.
- * Note: due to circular dependencies we cannot refer to the type explicitly.
- *
- * @implSpec The default implementation unconditionally returns an empty optional.
- * @param e the executable element.
- * @return the code model of the provided executable element (if any).
- * @since 99
- */
- public static Optional ofElement(ProcessingEnvironment processingEnvironment, ExecutableElement e) {
- if (e.getModifiers().contains(Modifier.ABSTRACT) ||
- e.getModifiers().contains(Modifier.NATIVE)) {
- return Optional.empty();
- }
-
- Context context = ((JavacProcessingEnvironment)processingEnvironment).getContext();
- ReflectMethods reflectMethods = ReflectMethods.instance(context);
- Attr attr = Attr.instance(context);
- JavacElements elements = JavacElements.instance(context);
- JavacTrees javacTrees = JavacTrees.instance(context);
- TreeMaker make = TreeMaker.instance(context);
- try {
- JCMethodDecl methodTree = (JCMethodDecl)elements.getTree(e);
- JavacScope scope = javacTrees.getScope(javacTrees.getPath(e));
- ClassSymbol enclosingClass = (ClassSymbol) scope.getEnclosingClass();
- FuncOp op = attr.runWithAttributedMethod(scope.getEnv(), methodTree,
- attribBlock -> reflectMethods.getMethodBody(enclosingClass, methodTree, attribBlock, make));
- return Optional.of(op);
- } catch (RuntimeException ex) { // ReflectMethods.UnsupportedASTException
- // some other error occurred when attempting to attribute the method
- // @@@ better report of error
- ex.printStackTrace();
- return Optional.empty();
- }
- }
}
diff --git a/src/jdk.incubator.code/share/classes/module-info.java b/src/jdk.incubator.code/share/classes/module-info.java
index 37e89ed1bec..1d9508b33e1 100644
--- a/src/jdk.incubator.code/share/classes/module-info.java
+++ b/src/jdk.incubator.code/share/classes/module-info.java
@@ -36,7 +36,7 @@
@ParticipatesInPreview
module jdk.incubator.code {
- requires transitive jdk.compiler;
+ requires jdk.compiler;
exports jdk.incubator.code;
exports jdk.incubator.code.extern;
@@ -46,6 +46,8 @@
exports jdk.incubator.code.bytecode;
exports jdk.incubator.code.interpreter;
+ exports jdk.incubator.code.internal to jdk.incubator.code.proc;
+
provides com.sun.tools.javac.comp.CodeReflectionTransformer with
ReflectMethods.Provider;
}
diff --git a/test/langtools/tools/javac/reflect/TestIRFromAnnotation.java b/test/langtools/tools/javac/reflect/TestIRFromAnnotation.java
index 9f2951db969..93c651b9ef1 100644
--- a/test/langtools/tools/javac/reflect/TestIRFromAnnotation.java
+++ b/test/langtools/tools/javac/reflect/TestIRFromAnnotation.java
@@ -23,7 +23,7 @@
/*
* @test
- * @modules jdk.incubator.code
+ * @modules jdk.incubator.code jdk.incubator.code.proc
* @enablePreview
* @library ../lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -41,6 +41,8 @@
import jdk.incubator.code.dialect.java.JavaOp;
import jdk.incubator.code.extern.OpParser;
import jdk.incubator.code.extern.OpWriter;
+import jdk.incubator.code.proc.CodeModelElements;
+
import java.nio.charset.Charset;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -150,7 +152,7 @@ public Void visitExecutable(ExecutableElement e, Void p) {
if (ir == null) {
return null; // skip
}
- Optional body = Op.ofElement(processingEnv, e);
+ Optional body = CodeModelElements.of(processingEnv).createCodeModel(e);
if (!body.isPresent()) {
throw new AssertionError(String.format("No body found in method %s annotated with @IR",
toMethodString(e)));