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)));