diff --git a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java index da79c17b387..df719d6fce6 100644 --- a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java @@ -40,6 +40,7 @@ import java.util.stream.Collectors; import static java.lang.System.lineSeparator; import static java.nio.file.StandardOpenOption.*; +import static java.util.stream.Collectors.joining; import static jdk.javadoc.doclet.Taglet.Location.TYPE; /** @@ -98,7 +99,7 @@ public final class SealedGraph implements Taglet { .map(Objects::toString) .collect(Collectors.toUnmodifiableSet()); - String dotContent = Renderer.graph(typeElement, exports); + String dotContent = new Renderer().graph(typeElement, exports); try { Files.writeString(dotFile, dotContent, WRITE, CREATE, TRUNCATE_EXISTING); @@ -133,13 +134,10 @@ public final class SealedGraph implements Taglet { (height <= 0 ? "" : " height=\"" + height + "\"")); } - private static final class Renderer { - - private Renderer() { - } + private final class Renderer { // Generates a graph in DOT format - static String graph(TypeElement rootClass, Set exports) { + String graph(TypeElement rootClass, Set exports) { final State state = new State(rootClass); traverse(state, rootClass, exports); return state.render(); @@ -155,17 +153,21 @@ public final class SealedGraph implements Taglet { } } - private static final class State { + private final class State { private static final String LABEL = "label"; private static final String TOOLTIP = "tooltip"; + private static final String LINK = "href"; private static final String STYLE = "style"; + private final TypeElement rootNode; + private final StringBuilder builder; private final Map> nodeStyleMap; public State(TypeElement rootNode) { + this.rootNode = rootNode; nodeStyleMap = new LinkedHashMap<>(); builder = new StringBuilder() .append("digraph G {") @@ -188,12 +190,30 @@ public final class SealedGraph implements Taglet { var styles = nodeStyleMap.computeIfAbsent(id(node), n -> new LinkedHashMap<>()); styles.put(LABEL, node.getSimpleName().toString()); styles.put(TOOLTIP, node.getQualifiedName().toString()); + styles.put(LINK, relativeLink(node)); if (!(node.getModifiers().contains(Modifier.SEALED) || node.getModifiers().contains(Modifier.FINAL))) { // This indicates that the hierarchy is not closed styles.put(STYLE, "dashed"); } } + // A permitted class must be in the same package or in the same module. + // This implies the module is always the same. + private String relativeLink(TypeElement node) { + var util = SealedGraph.this.docletEnvironment.getElementUtils(); + var rootPackage = util.getPackageOf(rootNode); + var nodePackage = util.getPackageOf(node); + var backNavigator = rootPackage.getQualifiedName().toString().chars() + .filter(c -> c == '.') + .mapToObj(c -> "../") + .collect(joining()) + + "../"; + var forwardNavigator = nodePackage.getQualifiedName().toString() + .replace(".", "/"); + + return backNavigator + forwardNavigator + "/" + node.getSimpleName() + ".html"; + } + public void addEdge(TypeElement node, TypeElement subNode) { builder.append(" ") .append(quotedId(subNode)) @@ -209,8 +229,8 @@ public final class SealedGraph implements Taglet { .append('"').append(nodeName).append("\" ") .append(styles.entrySet().stream() .map(e -> e.getKey() + "=\"" + e.getValue() + "\"") - .collect(Collectors.joining(" ", "[", "]"))) - .append(System.lineSeparator()); + .collect(joining(" ", "[", "]"))) + .append(lineSeparator()); }); builder.append("}"); return builder.toString(); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 0d333626ea0..5abc6ccf580 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -224,6 +224,10 @@ bool ZCollectedHeap::uses_stack_watermark_barrier() const { return true; } +MemoryUsage ZCollectedHeap::memory_usage() { + return _heap.serviceability_memory_pool()->get_memory_usage(); +} + GrowableArray ZCollectedHeap::memory_managers() { GrowableArray memory_managers(2); memory_managers.append(_heap.serviceability_cycle_memory_manager()); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index d1d14576e0b..37f41282c94 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -31,6 +31,7 @@ #include "gc/z/zInitialize.hpp" #include "gc/z/zRuntimeWorkers.hpp" #include "memory/metaspace.hpp" +#include "services/memoryUsage.hpp" class ZDirector; class ZDriver; @@ -90,6 +91,7 @@ public: virtual bool uses_stack_watermark_barrier() const; + virtual MemoryUsage memory_usage(); virtual GrowableArray memory_managers(); virtual GrowableArray memory_pools(); diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 19bbe25798c..ff4d255fc98 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -208,6 +208,9 @@ void JfrThreadLocal::on_exit(Thread* t) { assert(t != NULL, "invariant"); JfrThreadLocal * const tl = t->jfr_thread_local(); assert(!tl->is_dead(), "invariant"); + if (JfrRecorder::is_recording()) { + JfrCheckpointManager::write_checkpoint(t); + } if (t->is_Java_thread()) { JavaThread* const jt = JavaThread::cast(t); send_java_thread_end_event(jt, JfrThreadLocal::jvm_thread_id(jt)); diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 4789292de03..6e83806a038 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -180,9 +180,7 @@ public sealed interface Linker permits AbstractLinker { * * @return a linker for the ABI associated with the OS and processor where the Java runtime is currently executing. * @throws UnsupportedOperationException if the underlying native platform is not supported. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static Linker nativeLinker() { diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 76c2de64242..a1da55b8c0e 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -1065,9 +1065,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @param byteSize the size (in bytes) of the returned native segment. * @return a zero-length native segment with the given address and size. * @throws IllegalArgumentException if {@code byteSize < 0}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static MemorySegment ofAddress(long address, long byteSize) { @@ -1088,7 +1086,10 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * {@snippet lang = java: * ofAddress(address, byteSize, scope, null); *} - * + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. * @param address the returned segment's address. * @param byteSize the desired size. * @param scope the scope associated with the returned native segment. @@ -1097,9 +1098,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive @ForceInline @@ -1140,9 +1139,7 @@ public sealed interface MemorySegment permits AbstractMemorySegmentImpl { * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope, Runnable cleanupAction) { diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 50575f6b106..b2c5711922a 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -189,9 +189,7 @@ public interface SymbolLookup { * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given name. * @throws IllegalArgumentException if {@code name} does not identify a valid library. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static SymbolLookup libraryLookup(String name, SegmentScope scope) { @@ -215,9 +213,7 @@ public interface SymbolLookup { * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given path. * @throws IllegalArgumentException if {@code path} does not point to a valid library. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static SymbolLookup libraryLookup(Path path, SegmentScope scope) { diff --git a/src/java.base/share/classes/java/lang/foreign/VaList.java b/src/java.base/share/classes/java/lang/foreign/VaList.java index 0f6dd9fef47..4d8fab97575 100644 --- a/src/java.base/share/classes/java/lang/foreign/VaList.java +++ b/src/java.base/share/classes/java/lang/foreign/VaList.java @@ -247,9 +247,7 @@ public sealed interface VaList permits WinVaList, SysVVaList, LinuxAArch64VaList * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if the underlying native platform is not supported. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static VaList ofAddress(long address, SegmentScope scope) { diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java index f9a62419598..9ff1f08d7b9 100644 --- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java @@ -424,6 +424,7 @@ public sealed interface ValueLayout extends MemoryLayout { * restricted methods, and use safe and supported functionalities, where possible. * * @return an unbounded address layout with same characteristics as this layout. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. * @see #isUnbounded() */ @CallerSensitive diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index 7c134aa891e..01245b24af7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -356,10 +356,12 @@ public class Enter extends JCTree.Visitor { tree.packge.complete(); // Find all classes in package. Env topEnv = topLevelEnv(tree); - Env packageEnv = isPkgInfo ? topEnv.dup(pd) : null; + Env packageEnv = null; // Save environment of package-info.java file. if (isPkgInfo) { + packageEnv = topEnv.dup(pd != null ? pd : tree); + Env env0 = typeEnvs.get(tree.packge); if (env0 != null) { JCCompilationUnit tree0 = env0.toplevel; diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 0d8414feba8..fa259ef5137 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -47,39 +47,5 @@ serviceability/sa/ClhsdbPstack.java#core 8248912 generic- vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64 -vmTestbase/nsk/monitoring/stress/lowmem/lowmem001/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem002/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem003/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem004/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem005/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem006/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem007/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem008/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem009/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem010/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem011/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem012/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem013/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem014/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem015/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem016/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem017/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem018/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem019/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem020/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem021/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem022/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem023/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem024/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem025/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem026/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem027/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem028/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem029/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem030/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem031/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem032/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem033/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem034/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem035/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all +vmTestbase/nsk/sysdict/vm/stress/chain/chain008/chain008.java 8298596 linux-x64 diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 43e6ef2aa8d..d6a482d5267 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -79,6 +79,7 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/stress/TestStressG1Humongous.java 8286554 windows-x64 +gc/g1/TestVerifyGCType.java 8298215 linux-all,macosx-all ############################################################################# @@ -96,6 +97,7 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 runtime/vthread/RedefineClass.java 8297286 generic-all runtime/vthread/TestObjectAllocationSampleEvent.java 8297286 generic-all +runtime/StackGuardPages/TestStackGuardPages.java 8293452 linux-all applications/jcstress/copy.java 8229852 linux-all diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 5abeef70b3a..ab264783f71 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -752,7 +752,6 @@ jdk/jfr/startupargs/TestStartName.java 8214685 windows- jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 -jdk/jfr/api/consumer/TestRecordingFileWrite.java 8287699 generic-all ############################################################################ diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java index 6bd7121c651..62014baf8af 100644 --- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java +++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java @@ -50,9 +50,15 @@ public class MethodHandleLookup { return new Object[][]{ { MethodHandles.lookup().findStatic(Linker.class, "nativeLinker", MethodType.methodType(Linker.class)), "Linker::nativeLinker" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class)), + "MemorySegment::ofAddress/2" }, { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)), - "MemorySegment::ofAddressNative" }, + "MemorySegment::ofAddress/3" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class, Runnable.class)), + "MemorySegment::ofAddress/4" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", MethodType.methodType(SymbolLookup.class, String.class, SegmentScope.class)), "SymbolLookup::libraryLookup(String)" }, diff --git a/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java new file mode 100644 index 00000000000..4acf1e3abac --- /dev/null +++ b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022, 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. + * + * 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. + */ + +/** + * @test + * @bug 8298727 + * @summary Verify empty package-info.java is handled properly + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.TestRunner toolbox.ToolBox EmptyPackageInfo + * @run main EmptyPackageInfo + */ + +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import com.sun.source.util.Trees; +import java.util.ArrayList; +import java.util.List; +import javax.tools.ToolProvider; +import toolbox.TestRunner; +import toolbox.TestRunner.Test; +import toolbox.ToolBox; + +public class EmptyPackageInfo extends TestRunner { + + public static void main(String... args) throws Exception { + new EmptyPackageInfo().runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + private final ToolBox tb = new ToolBox(); + + public EmptyPackageInfo() { + super(System.err); + } + + @Test + public void testEmptyPackageInfo(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo = src.resolve("package-info.java"); + + tb.writeFile(packInfo, "/**javadoc*/\n"); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var task = + (JavacTask) compiler.getTask(null, + fm, + null, + null, + null, + fm.getJavaFileObjects(packInfo)); + task.analyze(); + var pack = task.getElements().getPackageElement(""); + var trees = Trees.instance(task); + var packPath = trees.getPath(pack); + var packTree = packPath.getLeaf(); + if (packTree.getKind() != Tree.Kind.COMPILATION_UNIT) { + throw new AssertionError("Unexpected tree kind: " + packTree.getKind()); + } + var actualJavadoc = trees.getDocComment(packPath); + var expectedJavadoc = "javadoc"; + if (!expectedJavadoc.equals(actualJavadoc)) { + throw new AssertionError("Unexpected javadoc, " + + "expected: " + expectedJavadoc + + ", got: " + actualJavadoc); + } + } + } + + @Test + public void testMultipleFiles(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo1 = src.resolve("test1").resolve("package-info.java"); + Path packInfo2 = src.resolve("test2").resolve("package-info.java"); + + tb.writeFile(packInfo1, ""); + tb.writeFile(packInfo2, ""); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var diags = new ArrayList(); + var task = + (JavacTask) compiler.getTask(null, + fm, + d -> diags.add(d.getCode()), + null, + null, + fm.getJavaFileObjects(packInfo1, + packInfo2)); + task.analyze(); + var expectedDiags = + List.of("compiler.warn.pkg-info.already.seen"); + if (!expectedDiags.equals(diags)) { + throw new AssertionError("Unexpected diags, " + + "expected: " + expectedDiags + + ", got: " + diags); + } + } + } +}