diff --git a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp index 89e06146589..6ef517ef4d1 100644 --- a/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/z/zBarrierSetAssembler_x86.cpp @@ -374,7 +374,7 @@ OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::N } // We use the vec_spill_helper from the x86.ad file to avoid reinventing this wheel -extern int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, +extern void vec_spill_helper(CodeBuffer *cbuf, bool is_load, int stack_offset, int reg, uint ireg, outputStream* st); #undef __ @@ -435,13 +435,13 @@ private: const OptoReg::Name opto_reg = OptoReg::as_OptoReg(reg_data._reg->as_VMReg()); const uint ideal_reg = xmm_ideal_reg_for_size(reg_data._size); _spill_offset -= reg_data._size; - vec_spill_helper(__ code(), false /* do_size */, false /* is_load */, _spill_offset, opto_reg, ideal_reg, tty); + vec_spill_helper(__ code(), false /* is_load */, _spill_offset, opto_reg, ideal_reg, tty); } void xmm_register_restore(const XMMRegisterData& reg_data) { const OptoReg::Name opto_reg = OptoReg::as_OptoReg(reg_data._reg->as_VMReg()); const uint ideal_reg = xmm_ideal_reg_for_size(reg_data._size); - vec_spill_helper(__ code(), false /* do_size */, true /* is_load */, _spill_offset, opto_reg, ideal_reg, tty); + vec_spill_helper(__ code(), true /* is_load */, _spill_offset, opto_reg, ideal_reg, tty); _spill_offset += reg_data._size; } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index bffa966751a..619a5538192 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -2130,18 +2130,14 @@ static inline Assembler::ComparisonPredicateFP booltest_pred_to_comparison_pred_ } // Helper methods for MachSpillCopyNode::implementation(). -static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, +static void vec_mov_helper(CodeBuffer *cbuf, int src_lo, int dst_lo, int src_hi, int dst_hi, uint ireg, outputStream* st) { - // In 64-bit VM size calculation is very complex. Emitting instructions - // into scratch buffer is used to get size in 64-bit VM. - LP64_ONLY( assert(!do_size, "this method calculates size only for 32-bit VM"); ) assert(ireg == Op_VecS || // 32bit vector (src_lo & 1) == 0 && (src_lo + 1) == src_hi && (dst_lo & 1) == 0 && (dst_lo + 1) == dst_hi, "no non-adjacent vector moves" ); if (cbuf) { C2_MacroAssembler _masm(cbuf); - int offset = __ offset(); switch (ireg) { case Op_VecS: // copy whole register case Op_VecD: @@ -2173,14 +2169,8 @@ static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo default: ShouldNotReachHere(); } - int size = __ offset() - offset; -#ifdef ASSERT - // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix. - assert(!do_size || size == 4, "incorrect size calculattion"); -#endif - return size; #ifndef PRODUCT - } else if (!do_size) { + } else { switch (ireg) { case Op_VecS: case Op_VecD: @@ -2196,18 +2186,12 @@ static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo } #endif } - // VEX_2bytes prefix is used if UseAVX > 0, and it takes the same 2 bytes as SIMD prefix. - return (UseAVX > 2) ? 6 : 4; } -int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, +void vec_spill_helper(CodeBuffer *cbuf, bool is_load, int stack_offset, int reg, uint ireg, outputStream* st) { - // In 64-bit VM size calculation is very complex. Emitting instructions - // into scratch buffer is used to get size in 64-bit VM. - LP64_ONLY( assert(!do_size, "this method calculates size only for 32-bit VM"); ) if (cbuf) { C2_MacroAssembler _masm(cbuf); - int offset = __ offset(); if (is_load) { switch (ireg) { case Op_VecS: @@ -2285,15 +2269,8 @@ int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, ShouldNotReachHere(); } } - int size = __ offset() - offset; -#ifdef ASSERT - int offset_size = (stack_offset == 0) ? 0 : ((stack_offset < 0x80) ? 1 : (UseAVX > 2) ? 6 : 4); - // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix. - assert(!do_size || size == (5+offset_size), "incorrect size calculattion"); -#endif - return size; #ifndef PRODUCT - } else if (!do_size) { + } else { if (is_load) { switch (ireg) { case Op_VecS: @@ -2333,47 +2310,6 @@ int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, } #endif } - bool is_single_byte = false; - int vec_len = 0; - if ((UseAVX > 2) && (stack_offset != 0)) { - int tuple_type = Assembler::EVEX_FVM; - int input_size = Assembler::EVEX_32bit; - switch (ireg) { - case Op_VecS: - tuple_type = Assembler::EVEX_T1S; - break; - case Op_VecD: - tuple_type = Assembler::EVEX_T1S; - input_size = Assembler::EVEX_64bit; - break; - case Op_VecX: - break; - case Op_VecY: - vec_len = 1; - break; - case Op_VecZ: - vec_len = 2; - break; - } - is_single_byte = Assembler::query_compressed_disp_byte(stack_offset, true, vec_len, tuple_type, input_size, 0); - } - int offset_size = 0; - int size = 5; - if (UseAVX > 2 ) { - if (VM_Version::supports_avx512novl() && (vec_len == 2)) { - offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4); - size += 2; // Need an additional two bytes for EVEX encoding - } else if (VM_Version::supports_avx512novl() && (vec_len < 2)) { - offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4); - } else { - offset_size = (stack_offset == 0) ? 0 : ((is_single_byte) ? 1 : 4); - size += 2; // Need an additional two bytes for EVEX encodding - } - } else { - offset_size = (stack_offset == 0) ? 0 : ((stack_offset <= 127) ? 1 : 4); - } - // VEX_2bytes prefix is used if UseAVX > 0, so it takes the same 2 bytes as SIMD prefix. - return size+offset_size; } static inline jlong replicate8_imm(int con, int width) { diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 92817041e36..fc0609b49b6 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -945,41 +945,16 @@ static int impl_fp_store_helper( CodeBuffer *cbuf, bool do_size, int src_lo, int } // Next two methods are shared by 32- and 64-bit VM. They are defined in x86.ad. -static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, +static void vec_mov_helper(CodeBuffer *cbuf, int src_lo, int dst_lo, int src_hi, int dst_hi, uint ireg, outputStream* st); -static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, +void vec_spill_helper(CodeBuffer *cbuf, bool is_load, int stack_offset, int reg, uint ireg, outputStream* st); -static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_offset, +static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset, int dst_offset, uint ireg, outputStream* st) { - int calc_size = 0; - int src_offset_size = (src_offset == 0) ? 0 : ((src_offset < 0x80) ? 1 : 4); - int dst_offset_size = (dst_offset == 0) ? 0 : ((dst_offset < 0x80) ? 1 : 4); - switch (ireg) { - case Op_VecS: - calc_size = 3+src_offset_size + 3+dst_offset_size; - break; - case Op_VecD: { - calc_size = 3+src_offset_size + 3+dst_offset_size; - int tmp_src_offset = src_offset + 4; - int tmp_dst_offset = dst_offset + 4; - src_offset_size = (tmp_src_offset == 0) ? 0 : ((tmp_src_offset < 0x80) ? 1 : 4); - dst_offset_size = (tmp_dst_offset == 0) ? 0 : ((tmp_dst_offset < 0x80) ? 1 : 4); - calc_size += 3+src_offset_size + 3+dst_offset_size; - break; - } - case Op_VecX: - case Op_VecY: - case Op_VecZ: - calc_size = 6 + 6 + 5+src_offset_size + 5+dst_offset_size; - break; - default: - ShouldNotReachHere(); - } if (cbuf) { MacroAssembler _masm(cbuf); - int offset = __ offset(); switch (ireg) { case Op_VecS: __ pushl(Address(rsp, src_offset)); @@ -1012,11 +987,8 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off default: ShouldNotReachHere(); } - int size = __ offset() - offset; - assert(size == calc_size, "incorrect size calculation"); - return size; #ifndef PRODUCT - } else if (!do_size) { + } else { switch (ireg) { case Op_VecS: st->print("pushl [rsp + #%d]\t# 32-bit mem-mem spill\n\t" @@ -1056,7 +1028,6 @@ static int vec_stack_to_stack_helper(CodeBuffer *cbuf, bool do_size, int src_off } #endif } - return calc_size; } uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { @@ -1088,18 +1059,19 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bo // mem -> mem int src_offset = ra_->reg2offset(src_first); int dst_offset = ra_->reg2offset(dst_first); - return vec_stack_to_stack_helper(cbuf, do_size, src_offset, dst_offset, ireg, st); + vec_stack_to_stack_helper(cbuf, src_offset, dst_offset, ireg, st); } else if (src_first_rc == rc_xmm && dst_first_rc == rc_xmm ) { - return vec_mov_helper(cbuf, do_size, src_first, dst_first, src_second, dst_second, ireg, st); + vec_mov_helper(cbuf, src_first, dst_first, src_second, dst_second, ireg, st); } else if (src_first_rc == rc_xmm && dst_first_rc == rc_stack ) { int stack_offset = ra_->reg2offset(dst_first); - return vec_spill_helper(cbuf, do_size, false, stack_offset, src_first, ireg, st); + vec_spill_helper(cbuf, false, stack_offset, src_first, ireg, st); } else if (src_first_rc == rc_stack && dst_first_rc == rc_xmm ) { int stack_offset = ra_->reg2offset(src_first); - return vec_spill_helper(cbuf, do_size, true, stack_offset, dst_first, ireg, st); + vec_spill_helper(cbuf, true, stack_offset, dst_first, ireg, st); } else { ShouldNotReachHere(); } + return 0; } // -------------------------------------- diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index dbe4be518f8..73fe1537528 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1033,10 +1033,10 @@ static enum RC rc_class(OptoReg::Name reg) } // Next two methods are shared by 32- and 64-bit VM. They are defined in x86.ad. -static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, +static void vec_mov_helper(CodeBuffer *cbuf, int src_lo, int dst_lo, int src_hi, int dst_hi, uint ireg, outputStream* st); -int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, +void vec_spill_helper(CodeBuffer *cbuf, bool is_load, int stack_offset, int reg, uint ireg, outputStream* st); static void vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset, @@ -1151,13 +1151,13 @@ uint MachSpillCopyNode::implementation(CodeBuffer* cbuf, int dst_offset = ra_->reg2offset(dst_first); vec_stack_to_stack_helper(cbuf, src_offset, dst_offset, ireg, st); } else if (src_first_rc == rc_float && dst_first_rc == rc_float ) { - vec_mov_helper(cbuf, false, src_first, dst_first, src_second, dst_second, ireg, st); + vec_mov_helper(cbuf, src_first, dst_first, src_second, dst_second, ireg, st); } else if (src_first_rc == rc_float && dst_first_rc == rc_stack ) { int stack_offset = ra_->reg2offset(dst_first); - vec_spill_helper(cbuf, false, false, stack_offset, src_first, ireg, st); + vec_spill_helper(cbuf, false, stack_offset, src_first, ireg, st); } else if (src_first_rc == rc_stack && dst_first_rc == rc_float ) { int stack_offset = ra_->reg2offset(src_first); - vec_spill_helper(cbuf, false, true, stack_offset, dst_first, ireg, st); + vec_spill_helper(cbuf, true, stack_offset, dst_first, ireg, st); } else { ShouldNotReachHere(); } diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index f08392fa4a2..3541657f472 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -65,16 +65,7 @@ # include address os::current_stack_pointer() { - address csp; - -#if !defined(USE_XLC_BUILTINS) - // inline assembly for `mr regno(csp), R1_SP': - __asm__ __volatile__ ("mr %0, 1":"=r"(csp):); -#else - csp = (address) __builtin_frame_address(0); -#endif - - return csp; + return (address)__builtin_frame_address(0); } char* os::non_memory_address_word() { @@ -159,13 +150,9 @@ frame os::get_sender_for_C_frame(frame* fr) { frame os::current_frame() { - intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer()); - // hack. - frame topframe(csp, (address)0x8); - // Return sender of sender of current topframe which hopefully - // both have pc != NULL. - frame tmp = os::get_sender_for_C_frame(&topframe); - return os::get_sender_for_C_frame(&tmp); + intptr_t* csp = *(intptr_t**) __builtin_frame_address(0); + frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame)); + return os::get_sender_for_C_frame(&topframe); } bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index fce1c84b72d..65147ff898c 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -78,12 +78,7 @@ address os::current_stack_pointer() { - intptr_t* csp; - - // inline assembly `mr regno(csp), R1_SP': - __asm__ __volatile__ ("mr %0, 1":"=r"(csp):); - - return (address) csp; + return (address)__builtin_frame_address(0); } char* os::non_memory_address_word() { @@ -179,13 +174,9 @@ frame os::get_sender_for_C_frame(frame* fr) { frame os::current_frame() { - intptr_t* csp = (intptr_t*) *((intptr_t*) os::current_stack_pointer()); - // hack. - frame topframe(csp, (address)0x8); - // Return sender of sender of current topframe which hopefully - // both have pc != NULL. - frame tmp = os::get_sender_for_C_frame(&topframe); - return os::get_sender_for_C_frame(&tmp); + intptr_t* csp = *(intptr_t**) __builtin_frame_address(0); + frame topframe(csp, CAST_FROM_FN_PTR(address, os::current_frame)); + return os::get_sender_for_C_frame(&topframe); } bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp index 664045b16c3..c0013cfcaa8 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.cpp @@ -59,9 +59,9 @@ void G1UncommitRegionTask::enqueue() { G1UncommitRegionTask* uncommit_task = instance(); if (!uncommit_task->is_active()) { - // Change state to active and schedule with no delay. + // Change state to active and schedule using UncommitInitialDelayMs. uncommit_task->set_active(true); - G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, 0); + G1CollectedHeap::heap()->service_thread()->schedule_task(uncommit_task, UncommitInitialDelayMs); } } @@ -124,9 +124,8 @@ void G1UncommitRegionTask::execute() { // Reschedule if there are more regions to uncommit, otherwise // change state to inactive. if (g1h->has_uncommittable_regions()) { - // No delay, reason to reschedule rather then to loop is to allow - // other tasks to run without waiting for a full uncommit cycle. - schedule(0); + // Delay to avoid starving application. + schedule(UncommitTaskDelayMs); } else { // Nothing more to do, change state and report a summary. set_active(false); diff --git a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp index 8ee13177549..058e7e4ba80 100644 --- a/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp +++ b/src/hotspot/share/gc/g1/g1UncommitRegionTask.hpp @@ -30,10 +30,14 @@ #include "utilities/ticks.hpp" class G1UncommitRegionTask : public G1ServiceTask { - // Each execution of the uncommit task is limited to uncommit at most 256M. + // Each execution of the uncommit task is limited to uncommit at most 128M. // This limit is small enough to ensure that the duration of each invocation // is short, while still making reasonable progress. - static const uint UncommitSizeLimit = 256 * M; + static const uint UncommitSizeLimit = 128 * M; + // Initial delay in milliseconds after GC before the regions are uncommitted. + static const uint UncommitInitialDelayMs = 100; + // The delay between two uncommit task executions. + static const uint UncommitTaskDelayMs = 10; static G1UncommitRegionTask* _instance; static void initialize(); diff --git a/src/hotspot/share/utilities/nativeCallStack.cpp b/src/hotspot/share/utilities/nativeCallStack.cpp index 1093a13eaec..45a29424fd7 100644 --- a/src/hotspot/share/utilities/nativeCallStack.cpp +++ b/src/hotspot/share/utilities/nativeCallStack.cpp @@ -36,7 +36,7 @@ NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : // to call os::get_native_stack. A tail call is used if _NMT_NOINLINE_ is not defined // (which means this is not a slowdebug build), and we are on 64-bit (except Windows). // This is not necessarily a rule, but what has been obvserved to date. -#if (defined(_NMT_NOINLINE_) || defined(_WINDOWS) || !defined(_LP64)) +#if (defined(_NMT_NOINLINE_) || defined(_WINDOWS) || !defined(_LP64) || defined(PPC64)) // Not a tail call. toSkip++; #if (defined(_NMT_NOINLINE_) && defined(BSD) && defined(_LP64)) diff --git a/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java b/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java index 9ecf35f828f..1c62d3d131c 100644 --- a/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java +++ b/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java @@ -38,6 +38,10 @@ public interface AnnotatedParameterizedType extends AnnotatedType { /** * Returns the potentially annotated actual type arguments of this parameterized type. * + *

Note that in some cases, the returned array can be empty. This can occur + * if this annotated type represents a non-parameterized type nested within + * a parameterized type. + * * @return the potentially annotated actual type arguments of this parameterized type * @see ParameterizedType#getActualTypeArguments() */ diff --git a/src/java.base/share/classes/java/lang/reflect/Constructor.java b/src/java.base/share/classes/java/lang/reflect/Constructor.java index 7a2309c25f1..8249c0158fd 100644 --- a/src/java.base/share/classes/java/lang/reflect/Constructor.java +++ b/src/java.base/share/classes/java/lang/reflect/Constructor.java @@ -662,7 +662,7 @@ public final class Constructor extends Executable { getConstantPool(thisDeclClass), this, thisDeclClass, - resolveToOwnerType(enclosingClass), + parameterize(enclosingClass), TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } } diff --git a/src/java.base/share/classes/java/lang/reflect/Executable.java b/src/java.base/share/classes/java/lang/reflect/Executable.java index 2d51111d8a5..3c4be628983 100644 --- a/src/java.base/share/classes/java/lang/reflect/Executable.java +++ b/src/java.base/share/classes/java/lang/reflect/Executable.java @@ -699,10 +699,29 @@ public abstract class Executable extends AccessibleObject getConstantPool(getDeclaringClass()), this, getDeclaringClass(), - resolveToOwnerType(getDeclaringClass()), + parameterize(getDeclaringClass()), TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } + Type parameterize(Class c) { + Class ownerClass = c.getDeclaringClass(); + TypeVariable[] typeVars = c.getTypeParameters(); + + if (ownerClass == null) { // base case + if (typeVars.length == 0) + return c; + else + return ParameterizedTypeImpl.make(c, typeVars, null); + } + + // Resolve owner + Type ownerType = parameterize(ownerClass); + if (ownerType instanceof Class && typeVars.length == 0) // We have yet to encounter type parameters + return c; + else + return ParameterizedTypeImpl.make(c, typeVars, ownerType); + } + /** * Returns an array of {@code AnnotatedType} objects that represent the use * of types to specify formal parameter types of the method/constructor @@ -753,24 +772,4 @@ public abstract class Executable extends AccessibleObject getGenericExceptionTypes(), TypeAnnotation.TypeAnnotationTarget.THROWS); } - - static Type resolveToOwnerType(Class c) { - TypeVariable[] v = c.getTypeParameters(); - Type o = resolveOwner(c); - Type t; - if (o != null || v.length > 0) { - t = ParameterizedTypeImpl.make(c, v, o); - } else { - t = c; - } - return t; - } - - private static Type resolveOwner(Class t) { - if (Modifier.isStatic(t.getModifiers()) || !(t.isLocalClass() || t.isMemberClass() || t.isAnonymousClass())) { - return null; - } - Class d = t.getDeclaringClass(); - return ParameterizedTypeImpl.make(d, d.getTypeParameters(), resolveOwner(d)); - } } diff --git a/src/java.base/share/classes/java/util/regex/Pattern.java b/src/java.base/share/classes/java/util/regex/Pattern.java index 002db861033..7469d5de4d8 100644 --- a/src/java.base/share/classes/java/util/regex/Pattern.java +++ b/src/java.base/share/classes/java/util/regex/Pattern.java @@ -2063,7 +2063,7 @@ loop: for(int x=0, offset=0; x x == 0x0A || x == 0x0B || - x == 0x0C || x == 0x0D || x == 0x85 || x == 0x2028 || - x == 0x2029); - chClass.next = branchConn; - grHead.next = new Branch(slice, chClass, branchConn); - return groupWithClosure(closure(grHead), grHead, grTail, false); - } - /** * Processes repetition. If the next character peeked is a quantifier * then new nodes must be appended to handle the repetition. @@ -4777,8 +4722,8 @@ loop: for(int x=0, offset=0; x= atoms.length) { - int len = ArraysSupport.newLength(size, - 1, /* minimum growth */ - size /* preferred growth */); - atoms = Arrays.copyOf(atoms, len); + Node[] tmp = new Node[atoms.length*2]; + System.arraycopy(atoms, 0, tmp, 0, atoms.length); + atoms = tmp; } atoms[size++] = node; } diff --git a/src/java.desktop/share/classes/javax/swing/JPasswordField.java b/src/java.desktop/share/classes/javax/swing/JPasswordField.java index ae90708b72b..8c40ba08973 100644 --- a/src/java.desktop/share/classes/javax/swing/JPasswordField.java +++ b/src/java.desktop/share/classes/javax/swing/JPasswordField.java @@ -280,6 +280,30 @@ public class JPasswordField extends JTextField { return super.getText(offs, len); } + @Override + @BeanProperty(bound = false, description = "the text of this component") + public void setText(String t) { + // overwrite the old data first + Document doc = getDocument(); + int nleft = doc.getLength(); + Segment text = new Segment(); + // we would like to get direct data array access, not a copy of it + text.setPartialReturn(true); + int offs = 0; + try { + while (nleft > 0) { + doc.getText(offs, nleft, text); + Arrays.fill(text.array, text.offset, + text.count + text.offset, '\u0000'); + nleft -= text.count; + offs += text.count; + } + } catch (BadLocationException ignored) { + // we tried + } + super.setText(t); + } + /** * Returns the text contained in this TextComponent. * If the underlying document is null, will give a diff --git a/src/java.desktop/share/classes/javax/swing/text/GapContent.java b/src/java.desktop/share/classes/javax/swing/text/GapContent.java index a5673b52540..a1ecff4895d 100644 --- a/src/java.desktop/share/classes/javax/swing/text/GapContent.java +++ b/src/java.desktop/share/classes/javax/swing/text/GapContent.java @@ -24,6 +24,7 @@ */ package javax.swing.text; +import java.util.Arrays; import java.util.Vector; import java.io.IOException; import java.io.ObjectInputStream; @@ -103,6 +104,12 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S return carray.length; } + @Override + void resize(int nsize) { + char[] carray = (char[]) getArray(); + super.resize(nsize); + Arrays.fill(carray, '\u0000'); + } // --- AbstractDocument.Content methods ------------------------- /** @@ -195,10 +202,12 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S if ((where + len) <= g0) { // below gap chars.array = array; + chars.copy = false; chars.offset = where; } else if (where >= g0) { // above gap chars.array = array; + chars.copy = false; chars.offset = g1 + where - g0; } else { // spans the gap @@ -206,12 +215,14 @@ public class GapContent extends GapVector implements AbstractDocument.Content, S if (chars.isPartialReturn()) { // partial return allowed, return amount before the gap chars.array = array; + chars.copy = false; chars.offset = where; chars.count = before; return; } // partial return not allowed, must copy chars.array = new char[len]; + chars.copy = true; chars.offset = 0; System.arraycopy(array, where, chars.array, 0, before); System.arraycopy(array, g1, chars.array, before, len - before); diff --git a/src/java.desktop/share/classes/javax/swing/text/Segment.java b/src/java.desktop/share/classes/javax/swing/text/Segment.java index 3e3c4025892..7f18daf644b 100644 --- a/src/java.desktop/share/classes/javax/swing/text/Segment.java +++ b/src/java.desktop/share/classes/javax/swing/text/Segment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, 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 @@ -61,6 +61,11 @@ public class Segment implements Cloneable, CharacterIterator, CharSequence { */ public int count; + /** + * Whether the array is a copy of data or not. + */ + boolean copy; + private boolean partialReturn; /** diff --git a/src/java.desktop/share/classes/javax/swing/text/SegmentCache.java b/src/java.desktop/share/classes/javax/swing/text/SegmentCache.java index e5f4571b2f8..3ca5367b79e 100644 --- a/src/java.desktop/share/classes/javax/swing/text/SegmentCache.java +++ b/src/java.desktop/share/classes/javax/swing/text/SegmentCache.java @@ -25,6 +25,7 @@ package javax.swing.text; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -110,7 +111,11 @@ class SegmentCache { public void releaseSegment(Segment segment) { if (segment instanceof CachedSegment) { synchronized(this) { + if (segment.copy) { + Arrays.fill(segment.array, '\u0000'); + } segment.array = null; + segment.copy = false; segment.count = 0; segments.add(segment); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index 51e83275b4c..1c9d12ec620 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -27,13 +27,9 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.ArrayList; import java.util.List; -import java.util.Set; -import java.util.TreeSet; -import java.util.stream.Collectors; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; import javax.lang.model.type.TypeMirror; @@ -46,7 +42,6 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.TagName; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; import jdk.javadoc.internal.doclets.formats.html.markup.Links; -import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; import jdk.javadoc.internal.doclets.formats.html.markup.Table; import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; import jdk.javadoc.internal.doclets.toolkit.Content; @@ -54,15 +49,8 @@ import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; import jdk.javadoc.internal.doclets.toolkit.MemberWriter; import jdk.javadoc.internal.doclets.toolkit.Resources; import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet; -import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; import jdk.javadoc.internal.doclets.toolkit.util.Utils; -import static javax.lang.model.element.Modifier.ABSTRACT; -import static javax.lang.model.element.Modifier.NATIVE; -import static javax.lang.model.element.Modifier.PUBLIC; -import static javax.lang.model.element.Modifier.STRICTFP; -import static javax.lang.model.element.Modifier.SYNCHRONIZED; - /** * The base class for member writers. * @@ -89,7 +77,7 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter, Membe this.writer = writer; this.typeElement = typeElement; this.utils = configuration.utils; - this.contents = configuration.contents; + this.contents = configuration.getContents(); this.resources = configuration.docResources; this.links = writer.links; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java index 4aa82534667..9dd6ffb723d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java @@ -116,12 +116,12 @@ public class AllClassesIndexWriter extends HtmlDocletWriter { .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast) .setId("all-classes-table") .setDefaultTab(resources.getText("doclet.All_Classes")) - .addTab(resources.interfaceSummary, utils::isInterface) - .addTab(resources.classSummary, e -> utils.isOrdinaryClass((TypeElement)e)) - .addTab(resources.enumSummary, utils::isEnum) - .addTab(resources.exceptionSummary, e -> utils.isException((TypeElement)e)) - .addTab(resources.errorSummary, e -> utils.isError((TypeElement)e)) - .addTab(resources.annotationTypeSummary, utils::isAnnotationType); + .addTab(contents.interfaceSummary, utils::isInterface) + .addTab(contents.classSummary, e -> utils.isOrdinaryClass((TypeElement)e)) + .addTab(contents.enumSummary, utils::isEnum) + .addTab(contents.exceptionSummary, e -> utils.isException((TypeElement)e)) + .addTab(contents.errorSummary, e -> utils.isError((TypeElement)e)) + .addTab(contents.annotationTypeSummary, utils::isAnnotationType); for (Character unicode : indexBuilder.getFirstCharacters()) { for (IndexItem indexItem : indexBuilder.getItems(unicode)) { TypeElement typeElement = (TypeElement) indexItem.getElement(); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java index 4b8a0da9a97..93703109028 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllPackagesIndexWriter.java @@ -96,7 +96,7 @@ public class AllPackagesIndexWriter extends HtmlDocletWriter { */ protected void addPackages(Content content) { Table table = new Table(HtmlStyle.summaryTable) - .setCaption(new StringContent(resources.packageSummary)) + .setCaption(new StringContent(contents.packageSummary)) .setHeader(new TableHeader(contents.packageLabel, contents.descriptionLabel)) .setColumnStyles(HtmlStyle.colFirst, HtmlStyle.colLast); for (PackageElement pkg : configuration.packages) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java index 91ddf66ba45..d8ba0b7ac74 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeOptionalMemberWriterImpl.java @@ -66,8 +66,9 @@ public class AnnotationTypeOptionalMemberWriterImpl extends @Override public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { - memberSummaryTree.add( - MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY); + memberSummaryTree.add(selectComment( + MarkerComments.START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY, + MarkerComments.START_OF_ANNOTATION_INTERFACE_OPTIONAL_MEMBER_SUMMARY)); Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, memberTree); return memberTree; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java index 856bb392d63..77adf904496 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -25,11 +25,13 @@ package jdk.javadoc.internal.doclets.formats.html; +import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import jdk.javadoc.internal.doclets.formats.html.markup.Comment; import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -66,8 +68,9 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter @Override public Content getMemberSummaryHeader(TypeElement typeElement, Content memberSummaryTree) { - memberSummaryTree.add( - MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY); + memberSummaryTree.add(selectComment( + MarkerComments.START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY, + MarkerComments.START_OF_ANNOTATION_INTERFACE_REQUIRED_MEMBER_SUMMARY)); Content memberTree = new ContentBuilder(); writer.addSummaryHeader(this, memberTree); return memberTree; @@ -86,7 +89,9 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter @Override public void addAnnotationDetailsMarker(Content memberDetails) { - memberDetails.add(MarkerComments.START_OF_ANNOTATION_TYPE_DETAILS); + memberDetails.add(selectComment( + MarkerComments.START_OF_ANNOTATION_TYPE_DETAILS, + MarkerComments.START_OF_ANNOTATION_INTERFACE_DETAILS)); } @Override @@ -201,6 +206,12 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, member, name); } + protected Comment selectComment(Comment c1, Comment c2) { + HtmlConfiguration configuration = writer.configuration; + SourceVersion sv = configuration.docEnv.getSourceVersion(); + return sv.compareTo(SourceVersion.RELEASE_16) < 0 ? c1 : c2; + } + private TypeMirror getType(Element member) { return utils.isExecutableElement(member) ? utils.getReturnType(typeElement, (ExecutableElement) member) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java index d87b8fab3ec..c59fed2e0bd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java @@ -412,9 +412,13 @@ public class ClassUseWriter extends SubWriterHolderWriter { * @return a content tree representing the class use header */ protected HtmlTree getClassUseHeader() { - String cltype = resources.getText(utils.isInterface(typeElement) - ? "doclet.Interface" - : "doclet.Class"); + String cltype = resources.getText(switch (typeElement.getKind()) { + case ANNOTATION_TYPE -> "doclet.AnnotationType"; + case INTERFACE -> "doclet.Interface"; + case RECORD -> "doclet.RecordClass"; + case ENUM -> "doclet.Enum"; + default -> "doclet.Class"; + }); String clname = utils.getFullyQualifiedName(typeElement); String title = resources.getText("doclet.Window_ClassUse_Header", cltype, clname); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java index 993879defd9..eabfd423311 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java @@ -177,6 +177,15 @@ public class Contents { private final EnumMap navLinkLabels; + public final String annotationTypeSummary; + public final String classSummary; + public final String enumSummary; + public final String errorSummary; + public final String exceptionSummary; + public final String interfaceSummary; + public final String packageSummary; + public final String recordSummary; + private final Resources resources; /** @@ -289,7 +298,7 @@ public class Contents { propertyLabel = getContent("doclet.Property"); propertyDetailsLabel = getContent("doclet.Property_Detail"); propertySummaryLabel = getContent("doclet.Property_Summary"); - record = getContent("doclet.Record"); + record = getContent("doclet.RecordClass"); recordComponents = getContent("doclet.RecordComponents"); referencedIn = getContent("doclet.ReferencedIn"); returns = getContent("doclet.Returns"); @@ -315,6 +324,15 @@ public class Contents { navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField")); navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor")); navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod")); + + this.annotationTypeSummary = resources.getText("doclet.Annotation_Types_Summary"); + this.classSummary = resources.getText("doclet.Class_Summary"); + this.enumSummary = resources.getText("doclet.Enum_Summary"); + this.errorSummary = resources.getText("doclet.Error_Summary"); + this.exceptionSummary = resources.getText("doclet.Exception_Summary"); + this.interfaceSummary = resources.getText("doclet.Interface_Summary"); + this.packageSummary = resources.getText("doclet.Package_Summary"); + this.recordSummary = resources.getText("doclet.Record_Class_Summary"); } /** diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java index e9c394a61ee..2486f1757d1 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/DeprecatedListWriter.java @@ -78,13 +78,13 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { case CLASS: return "class"; case ENUM: - return "enum"; + return "enum.class"; case EXCEPTION: return "exception"; case ERROR: return "error"; case ANNOTATION_TYPE: - return "annotation.type"; + return "annotation.interface"; case FIELD: return "field"; case METHOD: @@ -94,7 +94,7 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { case ENUM_CONSTANT: return "enum.constant"; case ANNOTATION_TYPE_MEMBER: - return "annotation.type.member"; + return "annotation.interface.member"; case RECORD_CLASS: return "record.class"; default: @@ -197,7 +197,7 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { case ANNOTATION_TYPE: return "doclet.AnnotationType"; case RECORD_CLASS: - return "doclet.Record"; + return "doclet.RecordClass"; case FIELD: return "doclet.Field"; case METHOD: @@ -287,17 +287,13 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { throws DocFileIOException { HtmlTree body = getHeader(); bodyContents.addMainContent(getContentsList(deprAPI)); - String memberTableSummary; Content content = new ContentBuilder(); for (DeprElementKind kind : DeprElementKind.values()) { if (deprAPI.hasDocumentation(kind)) { - memberTableSummary = resources.getText("doclet.Member_Table_Summary", - resources.getText(getHeadingKey(kind)), - resources.getText(getSummaryKey(kind))); TableHeader memberTableHeader = new TableHeader( contents.getContent(getHeaderKey(kind)), contents.descriptionLabel); addDeprecatedAPI(deprAPI.getSet(kind), getAnchorName(kind), - getHeadingKey(kind), memberTableSummary, memberTableHeader, content); + getHeadingKey(kind), memberTableHeader, content); } } bodyContents.addMainContent(content); @@ -368,12 +364,11 @@ public class DeprecatedListWriter extends SubWriterHolderWriter { * @param deprList list of deprecated API elements * @param id the id attribute of the table * @param headingKey the caption for the deprecated table - * @param tableSummary the summary for the deprecated table * @param tableHeader table headers for the deprecated table * @param contentTree the content tree to which the deprecated table will be added */ protected void addDeprecatedAPI(SortedSet deprList, String id, String headingKey, - String tableSummary, TableHeader tableHeader, Content contentTree) { + TableHeader tableHeader, Content contentTree) { if (deprList.size() > 0) { Content caption = contents.getContent(headingKey); Table table = new Table(HtmlStyle.summaryTable) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java index 19a354d8694..985c36aa26b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlConfiguration.java @@ -32,7 +32,9 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import javax.lang.model.element.Element; import javax.lang.model.element.PackageElement; @@ -118,7 +120,7 @@ public class HtmlConfiguration extends BaseConfiguration { */ protected DeprecatedAPIListBuilder deprecatedAPIListBuilder; - public final Contents contents; + private Contents contents; protected final Messages messages; @@ -181,7 +183,6 @@ public class HtmlConfiguration extends BaseConfiguration { } messages = new Messages(this, msgResources); - contents = new Contents(this); options = new HtmlOptions(this); Runtime.Version v; @@ -195,6 +196,11 @@ public class HtmlConfiguration extends BaseConfiguration { conditionalPages = EnumSet.noneOf(ConditionalPage.class); } + protected void initConfiguration(DocletEnvironment docEnv, + Function resourceKeyMapper) { + super.initConfiguration(docEnv, resourceKeyMapper); + contents = new Contents(this); + } private final Runtime.Version docletVersion; public final Date startTime = new Date(); @@ -215,7 +221,7 @@ public class HtmlConfiguration extends BaseConfiguration { * @return a utility object providing commonly used fragments of content */ public Contents getContents() { - return contents; + return Objects.requireNonNull(contents); } @Override diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index 95f1b6bcf99..9ad40d5b51d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -26,12 +26,15 @@ package jdk.javadoc.internal.doclets.formats.html; import java.util.*; +import java.util.function.Function; +import javax.lang.model.SourceVersion; import javax.lang.model.element.ModuleElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; import jdk.javadoc.doclet.Doclet; +import jdk.javadoc.doclet.DocletEnvironment; import jdk.javadoc.doclet.Reporter; import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet; import jdk.javadoc.internal.doclets.toolkit.DocletException; @@ -115,6 +118,52 @@ public class HtmlDoclet extends AbstractDoclet { return configuration; } + @Override + protected Function getResourceKeyMapper(DocletEnvironment docEnv) { + SourceVersion sv = docEnv.getSourceVersion(); + Map map = new HashMap<>(); + String[][] pairs = { + // in standard.properties + { "doclet.Enum_Hierarchy", "doclet.Enum_Class_Hierarchy" }, + { "doclet.Annotation_Type_Hierarchy", "doclet.Annotation_Interface_Hierarchy" }, + { "doclet.Href_Enum_Title", "doclet.Href_Enum_Class_Title" }, + { "doclet.Annotation_Types", "doclet.Annotation_Interfaces" }, + { "doclet.Annotation_Type_Members", "doclet.Annotation_Interface_Members" }, + { "doclet.annotation_types", "doclet.annotation_interfaces" }, + { "doclet.annotation_type_members", "doclet.annotation_interface_members" }, + { "doclet.help.enum.intro", "doclet.help.enum.class.intro" }, + { "doclet.help.annotation_type.intro", "doclet.help.annotation_interface.intro" }, + { "doclet.help.annotation_type.declaration", "doclet.help.annotation_interface.declaration" }, + { "doclet.help.annotation_type.description", "doclet.help.annotation_interface.description" }, + + // in doclets.properties + { "doclet.Annotation_Types_Summary", "doclet.Annotation_Interfaces_Summary" }, + { "doclet.Enum_Summary", "doclet.Enum_Class_Summary" }, + { "doclet.Enums", "doclet.EnumClasses" }, + { "doclet.AnnotationType", "doclet.AnnotationInterface" }, + { "doclet.AnnotationTypes", "doclet.AnnotationInterfaces" }, + { "doclet.annotationtype", "doclet.annotationinterface" }, + { "doclet.annotationtypes", "doclet.annotationinterfaces" }, + { "doclet.Enum", "doclet.EnumClass" }, + { "doclet.enum", "doclet.enumclass" }, + { "doclet.enums", "doclet.enumclasses" }, + { "doclet.Annotation_Type_Member", "doclet.Annotation_Interface_Member" }, + { "doclet.enum_values_doc.fullbody", "doclet.enum_class_values_doc.fullbody" }, + { "doclet.enum_values_doc.return", "doclet.enum_class_values_doc.return" }, + { "doclet.enum_valueof_doc.fullbody", "doclet.enum_class_valueof_doc.fullbody" }, + { "doclet.enum_valueof_doc.throws_ila", "doclet.enum_class_valueof_doc.throws_ila" }, + { "doclet.search.types", "doclet.search.classes_and_interfaces"} + }; + for (String[] pair : pairs) { + if (sv.compareTo(SourceVersion.RELEASE_16) >= 0) { + map.put(pair[0], pair[1]); + } else { + map.put(pair[1], pair[0]); + } + } + return (k) -> map.getOrDefault(k, k); + } + @Override // defined by AbstractDoclet public void generateClassFiles(ClassTree classTree) throws DocletException { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index bb7dcc41179..72139a95cd3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -216,7 +216,7 @@ public class HtmlDocletWriter { public HtmlDocletWriter(HtmlConfiguration configuration, DocPath path) { this.configuration = configuration; this.options = configuration.getOptions(); - this.contents = configuration.contents; + this.contents = configuration.getContents(); this.messages = configuration.messages; this.resources = configuration.docResources; this.links = new Links(path, configuration.utils); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MarkerComments.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MarkerComments.java index a23cd867976..af585b611f8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MarkerComments.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MarkerComments.java @@ -97,12 +97,24 @@ public class MarkerComments { public static final Comment START_OF_ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY = new Comment("=========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY ==========="); + /** + * Marker to identify start of annotation interface optional member summary. + */ + public static final Comment START_OF_ANNOTATION_INTERFACE_OPTIONAL_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION INTERFACE OPTIONAL MEMBER SUMMARY ==========="); + /** * Marker to identify start of annotation type required member summary. */ public static final Comment START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = new Comment("=========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY ==========="); + /** + * Marker to identify start of annotation interface required member summary. + */ + public static final Comment START_OF_ANNOTATION_INTERFACE_REQUIRED_MEMBER_SUMMARY = + new Comment("=========== ANNOTATION INTERFACE REQUIRED MEMBER SUMMARY ==========="); + /** * Marker to identify start of constructor summary. */ @@ -140,10 +152,10 @@ public class MarkerComments { new Comment("============ ANNOTATION TYPE MEMBER DETAIL ==========="); /** - * Marker to identify start of annotation type field details. + * Marker to identify start of annotation interface details. */ - public static final Comment START_OF_ANNOTATION_TYPE_FIELD_DETAILS = - new Comment("============ ANNOTATION TYPE FIELD DETAIL ==========="); + public static final Comment START_OF_ANNOTATION_INTERFACE_DETAILS = + new Comment("============ ANNOTATION INTERFACE MEMBER DETAIL ==========="); /** * Marker to identify start of method details. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index 6d0822813af..6581b73f702 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -481,9 +481,6 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW addSummaryHeader(MarkerComments.START_OF_MODULES_SUMMARY, contents.navModules, section); if (display(requires)) { String text = resources.getText("doclet.Requires_Summary"); - String tableSummary = resources.getText("doclet.Member_Table_Summary", - text, - resources.getText("doclet.modules")); Content caption = new StringContent(text); Table table = getTable3(caption, requiresTableHeader); addModulesList(requires, table); @@ -492,9 +489,6 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW // Display indirect modules table in both "api" and "all" mode. if (display(indirectModules)) { String amrText = resources.getText("doclet.Indirect_Requires_Summary"); - String amrTableSummary = resources.getText("doclet.Member_Table_Summary", - amrText, - resources.getText("doclet.modules")); Content amrCaption = new StringContent(amrText); Table amrTable = getTable3(amrCaption, requiresTableHeader); addModulesList(indirectModules, amrTable); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java index c330ce73afb..05c6399c295 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java @@ -116,7 +116,7 @@ public class Navigation { this.configuration = configuration; this.options = configuration.getOptions(); this.element = element; - this.contents = configuration.contents; + this.contents = configuration.getContents(); this.documentedPage = page; this.path = path; this.pathToRoot = path.parent().invert(); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java index 365ff890e6e..c863e0b687a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageUseWriter.java @@ -61,7 +61,6 @@ public class PackageUseWriter extends SubWriterHolderWriter { final PackageElement packageElement; final SortedMap> usingPackageToUsedClasses = new TreeMap<>(); - final String packageUseTableSummary; /** * Constructor. @@ -96,9 +95,6 @@ public class PackageUseWriter extends SubWriterHolderWriter { } } } - - packageUseTableSummary = resources.getText("doclet.Use_Table_Summary", - resources.getText("doclet.packages")); } /** @@ -193,8 +189,6 @@ public class PackageUseWriter extends SubWriterHolderWriter { PackageElement usingPackage = utils.elementUtils.getPackageElement(packageName); HtmlTree section = HtmlTree.SECTION(HtmlStyle.detail) .setId(getPackageAnchorName(usingPackage)); - String tableSummary = resources.getText("doclet.Use_Table_Summary", - resources.getText("doclet.classes")); Content caption = contents.getContent( "doclet.ClassUse_Classes.in.0.used.by.1", getPackageLink(packageElement, utils.getPackageName(packageElement)), diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java index 00b38e8e600..38dd65270bd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -164,43 +164,43 @@ public class PackageWriterImpl extends HtmlDocletWriter @Override public void addInterfaceSummary(SortedSet interfaces, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.interfaceLabel, contents.descriptionLabel); - addClassesSummary(interfaces, resources.interfaceSummary, tableHeader, summaryContentTree); + addClassesSummary(interfaces, contents.interfaceSummary, tableHeader, summaryContentTree); } @Override public void addClassSummary(SortedSet classes, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.classLabel, contents.descriptionLabel); - addClassesSummary(classes, resources.classSummary, tableHeader, summaryContentTree); + addClassesSummary(classes, contents.classSummary, tableHeader, summaryContentTree); } @Override public void addEnumSummary(SortedSet enums, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.enum_, contents.descriptionLabel); - addClassesSummary(enums, resources.enumSummary, tableHeader, summaryContentTree); + addClassesSummary(enums, contents.enumSummary, tableHeader, summaryContentTree); } @Override public void addRecordSummary(SortedSet records, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.record, contents.descriptionLabel); - addClassesSummary(records, resources.recordSummary, tableHeader, summaryContentTree); + addClassesSummary(records, contents.recordSummary, tableHeader, summaryContentTree); } @Override public void addExceptionSummary(SortedSet exceptions, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.exception, contents.descriptionLabel); - addClassesSummary(exceptions, resources.exceptionSummary, tableHeader, summaryContentTree); + addClassesSummary(exceptions, contents.exceptionSummary, tableHeader, summaryContentTree); } @Override public void addErrorSummary(SortedSet errors, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.error, contents.descriptionLabel); - addClassesSummary(errors, resources.errorSummary, tableHeader, summaryContentTree); + addClassesSummary(errors, contents.errorSummary, tableHeader, summaryContentTree); } @Override public void addAnnotationTypeSummary(SortedSet annoTypes, Content summaryContentTree) { TableHeader tableHeader= new TableHeader(contents.annotationType, contents.descriptionLabel); - addClassesSummary(annoTypes, resources.annotationTypeSummary, tableHeader, summaryContentTree); + addClassesSummary(annoTypes, contents.annotationTypeSummary, tableHeader, summaryContentTree); } public void addClassesSummary(SortedSet classes, String label, diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java index f7307426ae8..cab1bddb735 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java @@ -35,9 +35,9 @@ package jdk.javadoc.internal.doclets.formats.html; */ public enum SectionName { - ANNOTATION_TYPE_ELEMENT_DETAIL("annotation.type.element.detail"), - ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY("annotation.type.optional.element.summary"), - ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY("annotation.type.required.element.summary"), + ANNOTATION_TYPE_ELEMENT_DETAIL("annotation.interface.element.detail"), + ANNOTATION_TYPE_OPTIONAL_ELEMENT_SUMMARY("annotation.interface.optional.element.summary"), + ANNOTATION_TYPE_REQUIRED_ELEMENT_SUMMARY("annotation.interface.required.element.summary"), CONSTRUCTOR_DETAIL("constructor.detail"), CONSTRUCTOR_SUMMARY("constructor.summary"), ENUM_CONSTANT_DETAIL("enum.constant.detail"), diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index f62e545b686..3a8844685f5 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -39,11 +39,14 @@ doclet.Class_Hierarchy=Class Hierarchy doclet.Window_Class_Hierarchy=Class Hierarchy doclet.Interface_Hierarchy=Interface Hierarchy doclet.Enum_Hierarchy=Enum Hierarchy +doclet.Enum_Class_Hierarchy=Enum Class Hierarchy doclet.Annotation_Type_Hierarchy=Annotation Type Hierarchy +doclet.Annotation_Interface_Hierarchy=Annotation Interface Hierarchy doclet.Href_Class_Title=class in {0} doclet.Href_Interface_Title=interface in {0} doclet.Href_Annotation_Title=annotation in {0} doclet.Href_Enum_Title=enum in {0} +doclet.Href_Enum_Class_Title=enum class in {0} doclet.Href_Type_Param_Title=type parameter in {0} doclet.Href_Class_Or_Interface_Title=class or interface in {0} doclet.Summary=Summary: @@ -95,10 +98,14 @@ doclet.tag.invalid_usage=invalid usage of tag {0} doclet.Deprecated_API=Deprecated API doclet.For_Removal=For Removal doclet.Annotation_Types=Annotation Types +doclet.Annotation_Interfaces=Annotation Interfaces doclet.Annotation_Type_Members=Annotation Type Elements +doclet.Annotation_Interface_Members=Annotation Interface Elements doclet.for_removal=for removal doclet.annotation_types=annotation types +doclet.annotation_interfaces=annotation interfaces doclet.annotation_type_members=annotation type elements +doclet.annotation_interface_members=annotation interface elements doclet.record_classes=record classes doclet.Generated_Docs_Untitled=Generated Documentation (Untitled) doclet.Other_Packages=Other Packages @@ -212,16 +219,24 @@ doclet.help.footnote=\ This help file applies to API documentation generated by the standard doclet. doclet.help.enum.intro=\ Each enum has its own separate page with the following sections: +doclet.help.enum.class.intro=\ + Each enum class has its own separate page with the following sections: doclet.help.enum.declaration=\ Enum Declaration doclet.help.enum.definition=\ Enum Description doclet.help.annotation_type.intro=\ Each annotation type has its own separate page with the following sections: +doclet.help.annotation_interface.intro=\ + Each annotation interface has its own separate page with the following sections: doclet.help.annotation_type.declaration=\ Annotation Type Declaration +doclet.help.annotation_interface.declaration=\ + Annotation Interface Declaration doclet.help.annotation_type.description=\ Annotation Type Description +doclet.help.annotation_interface.description=\ + Annotation Interface Description doclet.help.search.head=Search # Introduction to Javadoc search features, followed by a list of examples doclet.help.search.intro=You can search for definitions of modules, packages, types, fields, methods, \ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java index d1a21a4a1e3..b7e8602b2e6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java @@ -25,8 +25,10 @@ package jdk.javadoc.internal.doclets.toolkit; +import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; +import java.util.function.Function; import javax.lang.model.SourceVersion; import javax.lang.model.element.PackageElement; @@ -99,7 +101,7 @@ public abstract class AbstractDoclet implements Doclet { @Override public boolean run(DocletEnvironment docEnv) { configuration = getConfiguration(); - configuration.initConfiguration(docEnv); + configuration.initConfiguration(docEnv, getResourceKeyMapper(docEnv)); utils = configuration.utils; messages = configuration.getMessages(); BaseOptions options = configuration.getOptions(); @@ -149,6 +151,10 @@ public abstract class AbstractDoclet implements Doclet { return false; } + protected Function getResourceKeyMapper(DocletEnvironment docEnv) { + return null; + } + private void reportInternalError(Throwable t) { if (getClass().equals(StandardDoclet.class) || getClass().equals(HtmlDoclet.class)) { System.err.println(configuration.getDocResources().getText("doclet.internal.report.bug")); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java index ab3fac18242..ef785603a5e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java @@ -41,6 +41,7 @@ import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; +import java.util.function.Function; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; @@ -237,7 +238,8 @@ public abstract class BaseConfiguration { private boolean initialized = false; - protected void initConfiguration(DocletEnvironment docEnv) { + protected void initConfiguration(DocletEnvironment docEnv, + Function resourceKeyMapper) { if (initialized) { throw new IllegalStateException("configuration previously initialized"); } @@ -251,6 +253,8 @@ public abstract class BaseConfiguration { options.setJavaFX(isJavaFXMode()); } + getDocResources().setKeyMapper(resourceKeyMapper); + // Once docEnv and Utils have been initialized, others should be safe. metakeywords = new MetaKeywords(this); cmtUtils = new CommentUtils(this); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Resources.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Resources.java index 4e9fb0fb67a..daa72fb631b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Resources.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Resources.java @@ -29,6 +29,7 @@ import java.text.MessageFormat; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.function.Function; /** * Access to the localizable resources used by a doclet. @@ -39,17 +40,10 @@ import java.util.ResourceBundle; * HTML doclet. */ public class Resources { - public final String annotationTypeSummary; - public final String classSummary; - public final String enumSummary; - public final String errorSummary; - public final String exceptionSummary; - public final String interfaceSummary; - public final String packageSummary; - public final String recordSummary; - protected ResourceBundle commonBundle; - protected ResourceBundle docletBundle; + protected final ResourceBundle commonBundle; + protected final ResourceBundle docletBundle; + protected Function mapper; /** * Creates a {@code Resources} object to provide access the resource @@ -65,20 +59,17 @@ public class Resources { public Resources(Locale locale, String commonBundleName, String docletBundleName) { this.commonBundle = ResourceBundle.getBundle(commonBundleName, locale); this.docletBundle = ResourceBundle.getBundle(docletBundleName, locale); + } - this.annotationTypeSummary = getText("doclet.Annotation_Types_Summary"); - this.classSummary = getText("doclet.Class_Summary"); - this.enumSummary = getText("doclet.Enum_Summary"); - this.errorSummary = getText("doclet.Error_Summary"); - this.exceptionSummary = getText("doclet.Exception_Summary"); - this.interfaceSummary = getText("doclet.Interface_Summary"); - this.packageSummary = getText("doclet.Package_Summary"); - this.recordSummary = getText("doclet.Record_Summary"); + public void setKeyMapper(Function mapper) { + this.mapper = mapper; } /** * Returns the string for the given key from one of the doclet's - * resource bundles. + * resource bundles. If the current {@code mapper} is not {@code null}, + * it will be applied to the {@code key} before looking up the resulting + * key in the resource bundle(s). * * The more specific bundle is checked first; * if it is not there, the common bundle is then checked. @@ -89,13 +80,17 @@ public class Resources { * bundle. */ public String getText(String key) throws MissingResourceException { - if (docletBundle.containsKey(key)) - return docletBundle.getString(key); + String mKey = mapper == null ? key : mapper.apply(key); - return commonBundle.getString(key); + if (docletBundle.containsKey(mKey)) + return docletBundle.getString(mKey); + + return commonBundle.getString(mKey); } + /** - * Returns the string for the given key from one of the doclet's + * Returns the string for the given key (after applying the current + * {@code mapper} if it is not {@code null}) from one of the doclet's * resource bundles, substituting additional arguments into * into the resulting string with {@link MessageFormat#format}. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java index 8957d1956c4..62ab25ffbb0 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java @@ -25,13 +25,10 @@ package jdk.javadoc.internal.doclets.toolkit; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -48,14 +45,10 @@ import javax.lang.model.util.Types; import javax.tools.FileObject; import javax.tools.JavaFileManager.Location; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; -import com.sun.tools.javac.api.BasicJavacTask; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Scope; -import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; @@ -66,11 +59,9 @@ import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.model.JavacElements; -import com.sun.tools.javac.model.JavacTypes; import com.sun.tools.javac.util.Names; import jdk.javadoc.internal.doclets.toolkit.util.Utils; -import jdk.javadoc.internal.doclint.DocLint; import jdk.javadoc.internal.tool.ToolEnvironment; import jdk.javadoc.internal.tool.DocEnvImpl; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java index 3bdd623f9da..e98c8c0a93a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ClassBuilder.java @@ -128,7 +128,7 @@ public class ClassBuilder extends AbstractBuilder { key = "doclet.Enum"; break; case RECORD: - key = "doclet.Record"; + key = "doclet.RecordClass"; break; case ANNOTATION_TYPE: key = "doclet.AnnotationType"; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index a769439428b..b106aa88646 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -127,7 +127,9 @@ doclet.Uses_Summary=Uses doclet.Provides_Summary=Provides doclet.Interface_Summary=Interface Summary doclet.Annotation_Types_Summary=Annotation Types Summary +doclet.Annotation_Interfaces_Summary=Annotation Interfaces Summary doclet.Enum_Summary=Enum Summary +doclet.Enum_Class_Summary=Enum Class Summary doclet.Exception_Summary=Exception Summary doclet.Error_Summary=Error Summary doclet.Class_Summary=Class Summary @@ -139,11 +141,13 @@ doclet.Property_Summary=Property Summary doclet.Enum_Constant_Summary=Enum Constant Summary doclet.Constructor_Summary=Constructor Summary doclet.Method_Summary=Method Summary -doclet.Record_Summary=Record Summary +doclet.Record_Class_Summary=Record Class Summary doclet.Interfaces=Interfaces doclet.Enums=Enums +doclet.EnumClasses=Enum Classes doclet.RecordClasses=Record Classes doclet.AnnotationTypes=Annotation Types +doclet.AnnotationInterfaces=Annotation Interfaces doclet.Exceptions=Exceptions doclet.Errors=Errors doclet.Classes=Classes @@ -155,17 +159,23 @@ doclet.All_Implemented_Interfaces=All Implemented Interfaces: doclet.Interface=Interface doclet.Class=Class doclet.AnnotationType=Annotation Type +doclet.AnnotationInterface=Annotation Interface doclet.annotationtype=annotation type +doclet.annotationinterface=annotation interface doclet.annotationtypes=annotation types +doclet.annotationinterfaces=annotation interfaces doclet.Enum=Enum +doclet.EnumClass=Enum Class doclet.enum=enum +doclet.enumclass=enum class doclet.enums=enums +doclet.enumclasses=enum classes doclet.interface=interface doclet.interfaces=interfaces doclet.class=class doclet.classes=classes -doclet.Record=Record -doclet.record=record +doclet.RecordClass=Record Class +doclet.recordclass=record class doclet.Error=Error doclet.error=error doclet.errors=errors @@ -206,8 +216,6 @@ doclet.value_tag_invalid_constant=@value tag (which references {0}) can only be doclet.value_tag_invalid_use=@value tag cannot be used here. doclet.dest_dir_create=Creating destination directory: "{0}" doclet.in={0} in {1} -doclet.Use_Table_Summary=Use table, listing {0}, and an explanation -doclet.Member_Table_Summary={0} table, listing {1}, and an explanation doclet.fields=fields doclet.Fields=Fields doclet.Properties=Properties @@ -239,6 +247,7 @@ doclet.Method=Method doclet.Annotation_Type_Optional_Member=Optional Element doclet.Annotation_Type_Required_Member=Required Element doclet.Annotation_Type_Member=Annotation Type Element +doclet.Annotation_Interface_Member=Annotation Interface Element doclet.Enum_Constant=Enum Constant doclet.Description=Description doclet.ConstantField=Constant Field @@ -253,15 +262,25 @@ doclet.urlRedirected=URL {0} was redirected to {1} -- Update the command-line op doclet.enum_values_doc.fullbody=\ Returns an array containing the constants of this enum type, in\n\ the order they are declared. +doclet.enum_class_values_doc.fullbody=\ + Returns an array containing the constants of this enum class, in\n\ + the order they are declared. doclet.enum_values_doc.return=\ an array containing the constants of this enum type, in the order they are declared +doclet.enum_class_values_doc.return=\ +an array containing the constants of this enum class, in the order they are declared doclet.enum_valueof_doc.fullbody=\ Returns the enum constant of this type with the specified name.\n\ The string must match exactly an identifier used to declare an\n\ enum constant in this type. (Extraneous whitespace characters are \n\ not permitted.) +doclet.enum_class_valueof_doc.fullbody=\ + Returns the enum constant of this class with the specified name.\n\ + The string must match exactly an identifier used to declare an\n\ + enum constant in this class. (Extraneous whitespace characters are \n\ + not permitted.) doclet.enum_valueof_doc.param_name=\ the name of the enum constant to be returned. @@ -271,6 +290,8 @@ doclet.enum_valueof_doc.return=\ doclet.enum_valueof_doc.throws_ila=\ if this enum type has no constant with the specified name +doclet.enum_class_valueof_doc.throws_ila=\ + if this enum class has no constant with the specified name doclet.enum_valueof_doc.throws_npe=\ if the argument is null @@ -278,7 +299,7 @@ doclet.enum_valueof_doc.throws_npe=\ #Documentation for records doclet.record_constructor_doc.fullbody=\ - Creates an instance of a {0} record. + Creates an instance of a {0} record class. doclet.record_constructor_doc.param_name=\ the value for the {0} record component @@ -294,10 +315,10 @@ doclet.record_equals_doc.fullbody.tail.both=\ primitive components are compared with '=='. doclet.record_equals_doc.fullbody.tail.primitive=\ - All components in this record are compared with '=='. + All components in this record class are compared with '=='. doclet.record_equals_doc.fullbody.tail.reference=\ - All components in this record are compared with \ + All components in this record class are compared with \ {@link java.util.Objects#equals(Object,Object) Objects::equals(Object,Object)}. doclet.record_equals_doc.param_name=\ @@ -314,8 +335,8 @@ doclet.record_hashCode_doc.return=\ a hash code value for this object doclet.record_toString_doc.fullbody=\ - Returns a string representation of this record. \ - The representation contains the name of the type, followed by \ + Returns a string representation of this record class. \ + The representation contains the name of the class, followed by \ the name and value of each of the record components. doclet.record_toString_doc.return=\ @@ -338,6 +359,7 @@ doclet.search.no_results=No results found doclet.search.loading=Loading search index... doclet.search.modules=Modules doclet.search.packages=Packages +doclet.search.classes_and_interfaces=Classes and Interfaces doclet.search.types=Types doclet.search.members=Members doclet.search.search_tags=Search Tags \ No newline at end of file diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index bc4b5d5bbec..28824ad7205 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1362,7 +1362,7 @@ public class Utils { case INTERFACE -> "doclet.Interface"; case RECORD -> - "doclet.Record"; + "doclet.RecordClass"; case CLASS -> isException(te) ? "doclet.Exception" : isError(te) ? "doclet.Error" diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java index 5ad64b826b4..ea30748cf2f 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java @@ -25,20 +25,28 @@ package jdk.javadoc.internal.doclets.toolkit.util; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ExecutableType; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.WildcardType; import javax.lang.model.util.Elements; import javax.lang.model.util.SimpleElementVisitor14; +import javax.lang.model.util.SimpleTypeVisitor14; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.Collections; import java.util.EnumMap; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -582,14 +590,10 @@ public class VisibleMemberTable { return false; } - TypeMirror inheritedMethodReturn = inheritedMethod.getReturnType(); - TypeMirror lMethodReturn = lMethod.getReturnType(); - boolean covariantReturn = - lMethodReturn.getKind() == TypeKind.DECLARED - && inheritedMethodReturn.getKind() == TypeKind.DECLARED - && !utils.typeUtils.isSameType(lMethodReturn, inheritedMethodReturn) - && utils.typeUtils.isSubtype(lMethodReturn, inheritedMethodReturn); - boolean simpleOverride = covariantReturn ? false : utils.isSimpleOverride(lMethod); + // Even with --override-methods=summary we want to include details of + // overriding method if something noteworthy has been added or changed. + boolean simpleOverride = utils.isSimpleOverride(lMethod) + && !overridingSignatureChanged(lMethod, inheritedMethod); overriddenMethodTable.computeIfAbsent(lMethod, l -> new OverridingMethodInfo(inheritedMethod, simpleOverride)); return simpleOverride; @@ -598,6 +602,90 @@ public class VisibleMemberTable { return true; } + // Check whether the signature of an overriding method has any changes worth + // being documented compared to the overridden method. + private boolean overridingSignatureChanged(ExecutableElement method, ExecutableElement overriddenMethod) { + // Covariant return type + TypeMirror overriddenMethodReturn = overriddenMethod.getReturnType(); + TypeMirror methodReturn = method.getReturnType(); + if (methodReturn.getKind() == TypeKind.DECLARED + && overriddenMethodReturn.getKind() == TypeKind.DECLARED + && !utils.typeUtils.isSameType(methodReturn, overriddenMethodReturn) + && utils.typeUtils.isSubtype(methodReturn, overriddenMethodReturn)) { + return true; + } + // Modifiers changed from protected to public, non-final to final, or change in abstractness + Set modifiers = method.getModifiers(); + Set overriddenModifiers = overriddenMethod.getModifiers(); + if ((modifiers.contains(Modifier.PUBLIC) && overriddenModifiers.contains(Modifier.PROTECTED)) + || modifiers.contains(Modifier.FINAL) + || modifiers.contains(Modifier.ABSTRACT) != overriddenModifiers.contains(Modifier.ABSTRACT)) { + return true; + } + // Change in thrown types + if (!method.getThrownTypes().equals(overriddenMethod.getThrownTypes())) { + return true; + } + // Documented annotations added anywhere in the method signature + return !getDocumentedAnnotations(method).equals(getDocumentedAnnotations(overriddenMethod)); + } + + private Set getDocumentedAnnotations(ExecutableElement element) { + Set annotations = new HashSet<>(); + addDocumentedAnnotations(annotations, element.getAnnotationMirrors()); + + new SimpleTypeVisitor14() { + @Override + protected Void defaultAction(TypeMirror e, Void v) { + addDocumentedAnnotations(annotations, e.getAnnotationMirrors()); + return null; + } + + @Override + public Void visitArray(ArrayType t, Void unused) { + if (t.getComponentType() != null) { + visit(t.getComponentType()); + } + return super.visitArray(t, unused); + } + + @Override + public Void visitDeclared(DeclaredType t, Void unused) { + t.getTypeArguments().forEach(this::visit); + return super.visitDeclared(t, unused); + } + + @Override + public Void visitWildcard(WildcardType t, Void unused) { + if (t.getExtendsBound() != null) { + visit(t.getExtendsBound()); + } + if (t.getSuperBound() != null) { + visit(t.getSuperBound()); + } + return super.visitWildcard(t, unused); + } + + @Override + public Void visitExecutable(ExecutableType t, Void unused) { + t.getParameterTypes().forEach(this::visit); + t.getTypeVariables().forEach(this::visit); + visit(t.getReturnType()); + return super.visitExecutable(t, unused); + } + }.visit(element.asType()); + + return annotations; + } + + private void addDocumentedAnnotations(Set annotations, List annotationMirrors) { + annotationMirrors.forEach(annotation -> { + if (utils.isDocumentedAnnotation((TypeElement) annotation.getAnnotationType().asElement())) { + annotations.add(annotation); + } + }); + } + /* * This class encapsulates the details of local members, orderedMembers * contains the members in the declaration order, additionally a diff --git a/test/hotspot/jtreg/compiler/codegen/TestCharVect2.java b/test/hotspot/jtreg/compiler/codegen/TestCharVect2.java index 2b9789f239c..d58568fadea 100644 --- a/test/hotspot/jtreg/compiler/codegen/TestCharVect2.java +++ b/test/hotspot/jtreg/compiler/codegen/TestCharVect2.java @@ -26,18 +26,10 @@ * @bug 8001183 * @summary incorrect results of char vectors right shift operation * - * @run main/othervm/timeout=400 -Xbatch -Xmx128m compiler.codegen.TestCharVect2 - */ - -/** - * @test - * @bug 8001183 - * @summary incorrect results of char vectors right shift operation - * @requires vm.compiler2.enabled | vm.graal.enabled - * - * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=8 compiler.codegen.TestCharVect2 - * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=16 compiler.codegen.TestCharVect2 - * @run main/othervm/timeout=400 -Xbatch -Xmx128m -XX:MaxVectorSize=32 compiler.codegen.TestCharVect2 + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::test() -Xmx128m compiler.codegen.TestCharVect2 + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::test() -Xmx128m -XX:MaxVectorSize=8 compiler.codegen.TestCharVect2 + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::test() -Xmx128m -XX:MaxVectorSize=16 compiler.codegen.TestCharVect2 + * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::test() -Xmx128m -XX:MaxVectorSize=32 compiler.codegen.TestCharVect2 */ package compiler.codegen; diff --git a/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java b/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java index e235f81bece..ab7194713d5 100644 --- a/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java +++ b/test/jdk/java/lang/ClassLoader/nativeLibrary/NativeLibraryTest.java @@ -60,6 +60,7 @@ public class NativeLibraryTest { setup(); for (int count=1; count <= 5; count++) { + System.out.println("count: " + count); // create a class loader and load a native library runTest(); // Unload the class loader and native library, and give the Cleaner diff --git a/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java b/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java index 084ed563809..b06fc387991 100644 --- a/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java +++ b/test/jdk/java/lang/annotation/typeAnnotations/GetAnnotatedReceiverType.java @@ -23,12 +23,10 @@ /* * @test - * @bug 8024915 8044629 + * @bug 8024915 8044629 8256693 */ -import java.lang.reflect.AnnotatedType; -import java.lang.reflect.Executable; -import java.util.Arrays; +import java.lang.reflect.*; public class GetAnnotatedReceiverType { public void method() {} @@ -62,9 +60,15 @@ public class GetAnnotatedReceiverType { public class Inner2 { public Inner2() { } + public void innerMethod2(GetAnnotatedReceiverType.Inner2 this) {} public class Inner3 { public Inner3() { } + public void innerMethod3(GetAnnotatedReceiverType.Inner2.Inner3 this) {} + + public class Inner7 { + public void innerMethod7(GetAnnotatedReceiverType.Inner2.Inner3.Inner7 this) {} + } public Class getLocalClass () { class InnerLocal { public InnerLocal() {} } @@ -86,8 +90,23 @@ public class GetAnnotatedReceiverType { } } + public class Inner4 { + public Inner4(GetAnnotatedReceiverType GetAnnotatedReceiverType.this) {} + public void innerMethod4(GetAnnotatedReceiverType.Inner4 this) {} + + public class Inner5 { + public Inner5(GetAnnotatedReceiverType.Inner4 GetAnnotatedReceiverType.Inner4.this) {} + public void innerMethod5(GetAnnotatedReceiverType.Inner4.Inner5 this) {} + + public class Inner6 { + public Inner6(GetAnnotatedReceiverType.Inner4.Inner5 GetAnnotatedReceiverType.Inner4.Inner5.this) {} + } + } + } + private static int failures = 0; private static int tests = 0; + private static final int EXPECTED_TEST_CASES = 25; public static void main(String[] args) throws NoSuchMethodException { checkEmptyAT(GetAnnotatedReceiverType.class.getMethod("method"), @@ -132,9 +151,35 @@ public class GetAnnotatedReceiverType { checkNull(instance3.getAnonymousClass().getDeclaredConstructors()[0], "getAnnotatedReceiverType() on a constructor for an anonymous class should return null"); + Inner4 instance4 = outer.new Inner4(); + Inner4.Inner5 instance5 = instance4.new Inner5(); + Inner4.Inner5.Inner6 instance6 = instance5.new Inner6(); + + checkAnnotatedReceiverType(instance4.getClass().getConstructors()[0], false, + "The type of .getAnnotatedReceiverType().getType() for this constructor should be"); + checkAnnotatedReceiverType(instance5.getClass().getConstructors()[0], true, + "The type of .getAnnotatedReceiverType().getType() for this constructor should be"); + checkAnnotatedReceiverType(instance6.getClass().getConstructors()[0], true, + "The type of .getAnnotatedReceiverType().getType() for this constructor should be"); + checkAnnotatedReceiverType(outer.getClass().getMethod("method0"), false, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + checkAnnotatedReceiverType(instance4.getClass().getMethod("innerMethod4"), true, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + checkAnnotatedReceiverType(instance5.getClass().getMethod("innerMethod5"), true, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + checkAnnotatedReceiverType(instance2.getClass().getMethod("innerMethod2"), false, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + checkAnnotatedReceiverType(instance3.getClass().getMethod("innerMethod3"), false, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + + Inner2.Inner3.Inner7 instance7 = instance3.new Inner7(); + checkAnnotatedReceiverType(instance7.getClass().getMethod("innerMethod7"), true, + "The type of .getAnnotatedReceiverType().getType() for this method should be"); + recursiveCheckAnnotatedOwnerTypes(instance7.getClass().getMethod("innerMethod7").getAnnotatedReceiverType()); + if (failures != 0) throw new RuntimeException("Test failed, see log for details"); - else if (tests != 15) + else if (tests != EXPECTED_TEST_CASES) throw new RuntimeException("Not all cases ran, failing"); } @@ -155,4 +200,41 @@ public class GetAnnotatedReceiverType { } tests++; } + + private static void checkAnnotatedReceiverType(Executable e, boolean shouldBeParameterized, String msg) { + Type t = e.getAnnotatedReceiverType().getType(); + if (shouldBeParameterized != (t instanceof ParameterizedType)) { + failures++; + System.err.println(e + ", " + msg + " " + (shouldBeParameterized ? "ParameterizedType" : "Class") + ", found: " + t.getClass().getSimpleName()); + } + + // Test we can get the potentially empty annotated actual type arguments array + if (shouldBeParameterized) { + try { + ParameterizedType t1 = (ParameterizedType)t; + AnnotatedParameterizedType at1 = (AnnotatedParameterizedType)e.getAnnotatedReceiverType(); + + if (t1.getActualTypeArguments().length != at1.getAnnotatedActualTypeArguments().length) { + System.err.println(t1 + "'s actual type arguments can't match " + at1); + failures++; + } + } catch (ClassCastException cce) { + System.err.println("Couldn't get potentially empty actual type arguments: " + cce.getMessage()); + failures++; + } + } + tests++; + } + + private static void recursiveCheckAnnotatedOwnerTypes(AnnotatedType t) { + AnnotatedType check = t.getAnnotatedOwnerType(); + do { + if (!(check.getType() instanceof Class)) { + failures++; + System.err.println("Expecting only instances of Class returned for .getType() found " + check.getType().getClass().getSimpleName()); + } + check = check.getAnnotatedOwnerType(); + } while (check != null); + tests++; + } } diff --git a/test/jdk/java/util/regex/RegExTest.java b/test/jdk/java/util/regex/RegExTest.java index 387b01e5f62..a70cf328c3a 100644 --- a/test/jdk/java/util/regex/RegExTest.java +++ b/test/jdk/java/util/regex/RegExTest.java @@ -36,7 +36,7 @@ * 8151481 4867170 7080302 6728861 6995635 6736245 4916384 6328855 6192895 * 6345469 6988218 6693451 7006761 8140212 8143282 8158482 8176029 8184706 * 8194667 8197462 8184692 8221431 8224789 8228352 8230829 8236034 8235812 - * 8216332 8214245 8237599 8241055 8247546 + * 8216332 8214245 8237599 8241055 8247546 8258259 * * @library /test/lib * @library /lib/testlibrary/java/lang @@ -5063,7 +5063,15 @@ public class RegExTest { report("surrogatePairWithCanonEq"); } - // This test is for 8235812 + private static String s2x(String s) { + StringBuilder sb = new StringBuilder(); + for (char ch : s.toCharArray()) { + sb.append(String.format("\\u%04x", (int)ch)); + } + return sb.toString(); + } + + // This test is for 8235812, with cases excluded by 8258259 private static void lineBreakWithQuantifier() { // key: pattern // value: lengths of input that must match the pattern @@ -5073,12 +5081,12 @@ public class RegExTest { Map.entry("\\R+", List.of(1, 2, 3)), Map.entry("\\R{0}", List.of(0)), Map.entry("\\R{1}", List.of(1)), - Map.entry("\\R{2}", List.of(2)), - Map.entry("\\R{3}", List.of(3)), +// Map.entry("\\R{2}", List.of(2)), // 8258259 +// Map.entry("\\R{3}", List.of(3)), // 8258259 Map.entry("\\R{0,}", List.of(0, 1, 2, 3)), Map.entry("\\R{1,}", List.of(1, 2, 3)), - Map.entry("\\R{2,}", List.of(2, 3)), - Map.entry("\\R{3,}", List.of(3)), +// Map.entry("\\R{2,}", List.of(2, 3)), // 8258259 +// Map.entry("\\R{3,}", List.of(3)), // 8258259 Map.entry("\\R{0,0}", List.of(0)), Map.entry("\\R{0,1}", List.of(0, 1)), Map.entry("\\R{0,2}", List.of(0, 1, 2)), @@ -5086,9 +5094,9 @@ public class RegExTest { Map.entry("\\R{1,1}", List.of(1)), Map.entry("\\R{1,2}", List.of(1, 2)), Map.entry("\\R{1,3}", List.of(1, 2, 3)), - Map.entry("\\R{2,2}", List.of(2)), - Map.entry("\\R{2,3}", List.of(2, 3)), - Map.entry("\\R{3,3}", List.of(3)), +// Map.entry("\\R{2,2}", List.of(2)), // 8258259 +// Map.entry("\\R{2,3}", List.of(2, 3)), // 8258259 +// Map.entry("\\R{3,3}", List.of(3)), // 8258259 Map.entry("\\R", List.of(1)), Map.entry("\\R\\R", List.of(2)), Map.entry("\\R\\R\\R", List.of(3)) @@ -5131,7 +5139,7 @@ public class RegExTest { if (!m.reset(in).matches()) { failCount++; System.err.println("Expected to match '" + - in + "' =~ /" + p + "/"); + s2x(in) + "' =~ /" + p + "/"); } } } diff --git a/test/jdk/javax/swing/JPasswordField/CheckCommonUseCases.java b/test/jdk/javax/swing/JPasswordField/CheckCommonUseCases.java new file mode 100644 index 00000000000..f8a615cc94a --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/CheckCommonUseCases.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020, 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. + */ + +import java.awt.EventQueue; +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.swing.JPasswordField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/** + * @test + * @bug 8258373 + */ +public final class CheckCommonUseCases { + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + JPasswordField pf = new JPasswordField(); + // check that pf work if the new text is longer/shorter than the old + checkDifferentTextLength(pf); + // count the listeners called by the setText(); + countListeners(pf); + }); + } + + private static void countListeners(JPasswordField pf) { + AtomicInteger insert = new AtomicInteger(); + AtomicInteger update = new AtomicInteger(); + AtomicInteger remove = new AtomicInteger(); + pf.getDocument().addDocumentListener(new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + insert.incrementAndGet(); + System.err.println("e = " + e); + } + + @Override + public void removeUpdate(DocumentEvent e) { + remove.incrementAndGet(); + System.err.println("e = " + e); + } + + @Override + public void changedUpdate(DocumentEvent e) { + update.incrementAndGet(); + System.err.println("e = " + e); + } + }); + // set the new text + pf.setText("aaa"); + if (remove.get() != 0 || update.get() != 0 || insert.get() > 1) { + System.err.println("remove = " + remove); + System.err.println("update = " + update); + System.err.println("insert = " + insert); + throw new RuntimeException("Unexpected number of listeners"); + } + insert.set(0); + update.set(0); + remove.set(0); + + // replace the old text + pf.setText("bbb"); + if (remove.get() > 1 || update.get() > 1 || insert.get() > 1) { + System.err.println("remove = " + remove); + System.err.println("update = " + update); + System.err.println("insert = " + insert); + throw new RuntimeException("Unexpected number of listeners"); + } + insert.set(0); + update.set(0); + remove.set(0); + + // remove the text + pf.setText(""); + if (remove.get() > 1 || update.get() > 0 || insert.get() > 0) { + System.err.println("remove = " + remove); + System.err.println("update = " + update); + System.err.println("insert = " + insert); + throw new RuntimeException("Unexpected number of listeners"); + } + } + + private static void checkDifferentTextLength(JPasswordField pf) { + // forward + for (int i = 0 ; i < 100; ++i){ + String expected = ("" + i).repeat(i); + pf.setText(expected); + String actual = Arrays.toString(pf.getPassword()); + if (actual.equals(expected)){ + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException(); + } + } + // backward + for (int i = 99; i >= 0; --i){ + String expected = ("" + i).repeat(i); + pf.setText(expected); + String actual = Arrays.toString(pf.getPassword()); + if (actual.equals(expected)){ + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException(); + } + } + } +} diff --git a/test/jdk/javax/swing/JPasswordField/CleanInternalStorageOnSetText.java b/test/jdk/javax/swing/JPasswordField/CleanInternalStorageOnSetText.java new file mode 100644 index 00000000000..641a84d85ce --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/CleanInternalStorageOnSetText.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2020, 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. + */ + +import java.awt.EventQueue; +import java.util.ArrayList; +import java.util.Arrays; + +import javax.swing.JPasswordField; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.GapContent; +import javax.swing.text.PlainDocument; +import javax.swing.text.Segment; +import javax.swing.text.StringContent; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.StyleSheet; + +/** + * @test + * @bug 8258373 + * @summary The JPasswordField#setText() should reset the old internal storage + */ +public final class CleanInternalStorageOnSetText { + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + // default case + testStorage(false, new JPasswordField()); + testStorage(true, new JPasswordField()); + + // custom Plain String document + Document document = new PlainDocument(new StringContent()); + testStorage(false, new JPasswordField(document, "", 10)); + document = new PlainDocument(new StringContent()); + testStorage(true, new JPasswordField(document, "", 10)); + + // custom Plain GAP document + document = new PlainDocument(new GapContent()); + testStorage(false, new JPasswordField(document, "", 10)); + document = new PlainDocument(new GapContent()); + testStorage(true, new JPasswordField(document, "", 10)); + + // custom HTMLDocument String document + document = new HTMLDocument(new StringContent(), new StyleSheet()); + testStorage(false, new JPasswordField(document, "", 10)); + document = new HTMLDocument(new StringContent(), new StyleSheet()); + testStorage(true, new JPasswordField(document, "", 10)); + + // custom HTMLDocument GAP document + document = new HTMLDocument(new GapContent(), new StyleSheet()); + testStorage(false, new JPasswordField(document, "", 10)); + document = new HTMLDocument(new GapContent(), new StyleSheet()); + testStorage(true, new JPasswordField(document, "", 10)); + }); + } + + private static void testStorage(boolean makeGap, JPasswordField pf) { + test(pf, "123", makeGap); + test(pf, "1234567", makeGap); + test(pf, "1234567890", makeGap); + test(pf, "1".repeat(100), makeGap); + test(pf, "1234567890", makeGap); + test(pf, "1234567", makeGap); + test(pf, "123", makeGap); + test(pf, "", makeGap); + } + + private static void test(JPasswordField pf, String text, boolean makeGap) { + pf.setText(text); + if (makeGap && text.length() > 3) { + try { + pf.getDocument().remove(1, 2); + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + } + // if no gaps we can check whole array + char[] internalArray = getInternalArray(pf); + ArrayList segments = new ArrayList<>(); + if (makeGap) { + // if gaps exists we can check only part of the array + Document doc = pf.getDocument(); + int nleft = doc.getLength(); + Segment sgm = new Segment(); + sgm.setPartialReturn(true); + int offs = 0; + try { + while (nleft > 0) { + doc.getText(offs, nleft, sgm); + segments.add(sgm); + nleft -= sgm.count; + offs += sgm.count; + } + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + } + System.err.println("Before = " + Arrays.toString(internalArray)); + pf.setText(""); + System.err.println("After = " + Arrays.toString(internalArray)); + + if (!makeGap) { + for (char c : internalArray) { + if (c != '\u0000' && c != '\n') { + throw new RuntimeException(Arrays.toString(internalArray)); + } + } + } else { + for (Segment sgm : segments) { + for (int i = sgm.offset; i < sgm.count + sgm.offset; i++) { + char c = sgm.array[i]; + if (c != '\u0000' && c != '\n') { + throw new RuntimeException(Arrays.toString(sgm.array)); + } + } + } + } + } + + /** + * This method returns the reference to the internal data stored by the + * document inside JPasswordField. + */ + private static char[] getInternalArray(JPasswordField pf) { + Document doc = pf.getDocument(); + int nleft = doc.getLength(); + Segment text = new Segment(); + int offs = 0; + text.setPartialReturn(true); + try { + doc.getText(offs, nleft, text); + } catch (BadLocationException e) { + throw new RuntimeException(e); + } + return text.array; + } +} diff --git a/test/jdk/javax/swing/JPasswordField/TextBeanProperty.java b/test/jdk/javax/swing/JPasswordField/TextBeanProperty.java new file mode 100644 index 00000000000..edc2879700a --- /dev/null +++ b/test/jdk/javax/swing/JPasswordField/TextBeanProperty.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, 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. + */ + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import javax.swing.JPasswordField; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.text.JTextComponent; + +/** + * @test + * @bug 8258373 + * @summary The "text" property should not be "bound" + */ +public final class TextBeanProperty { + + public static void main(String[] args) throws Exception { + test(JTextComponent.class); + test(JTextField.class); + test(JTextArea.class); + test(JPasswordField.class); + } + + private static void test(Class beanClass) throws Exception { + BeanInfo info = Introspector.getBeanInfo(beanClass); + PropertyDescriptor[] pd = info.getPropertyDescriptors(); + int i; + for (i = 0; i < pd.length; i++) { + if (pd[i].getName().equals("text")) { + break; + } + } + if (pd[i].isBound()) { + System.err.println("Property: " + pd[i]); + throw new RuntimeException("text property is flagged as bound"); + } + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java b/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java index d0b324b73a0..488cb9238c4 100644 --- a/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java +++ b/test/langtools/jdk/javadoc/doclet/testAnnotationOptional/TestAnnotationOptional.java @@ -50,6 +50,6 @@ public class TestAnnotationOptional extends JavadocTester { checkOutput("pkg/AnnotationOptional.html", true, """ -

"""); +
"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java index 27875f171a2..ae17feafd90 100644 --- a/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testAnnotationTypes/TestAnnotationTypes.java @@ -79,11 +79,11 @@ public class TestAnnotationTypes extends JavadocTester {
  • Field | 
  • """); checkOutput("pkg/AnnotationType.html", true, - "", + "", "