());
* }
*
* The following example uses {@code allUntil} to wait for all subtasks to
* complete without any cancellation. This is similar to {@link #awaitAll()}
- * except that it yields a stream of the completed subtasks.
+ * except that it yields a list of the completed subtasks.
* {@snippet lang=java :
* List> invokeAll(Collection> tasks) throws InterruptedException {
* try (var scope = StructuredTaskScope.open(Joiner.allUntil(_ -> false))) {
diff --git a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java
index 168f76fad8f..32399310bd3 100644
--- a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java
+++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java
@@ -60,44 +60,6 @@ public class FloatingDecimal{
static final int INT_DECIMAL_DIGITS = 9;
- /**
- * Converts a double precision floating point value to a String.
- *
- * @param d The double precision value.
- * @return The value converted to a String.
- */
- public static String toJavaFormatString(double d) {
- return getBinaryToASCIIConverter(d).toJavaFormatString();
- }
-
- /**
- * Converts a single precision floating point value to a String.
- *
- * @param f The single precision value.
- * @return The value converted to a String.
- */
- public static String toJavaFormatString(float f) {
- return getBinaryToASCIIConverter(f).toJavaFormatString();
- }
-
- /**
- * Appends a double precision floating point value to an Appendable.
- * @param d The double precision value.
- * @param buf The Appendable with the value appended.
- */
- public static void appendTo(double d, Appendable buf) {
- getBinaryToASCIIConverter(d).appendTo(buf);
- }
-
- /**
- * Appends a single precision floating point value to an Appendable.
- * @param f The single precision value.
- * @param buf The Appendable with the value appended.
- */
- public static void appendTo(float f, Appendable buf) {
- getBinaryToASCIIConverter(f).appendTo(buf);
- }
-
/**
* Converts a String to a double precision floating point value.
*
@@ -131,7 +93,7 @@ public class FloatingDecimal{
* @param length Number of digits to use
* @return The double-precision value of the conversion
*/
- public static double parseDoubleSignlessDigits(int decExp, char[] digits, int length) {
+ public static double parseDoubleSignlessDigits(int decExp, byte[] digits, int length) {
return readDoubleSignlessDigits(decExp, digits, length).doubleValue();
}
@@ -140,17 +102,7 @@ public class FloatingDecimal{
* values into an ASCII String representation.
*/
public interface BinaryToASCIIConverter {
- /**
- * Converts a floating point value into an ASCII String.
- * @return The value converted to a String.
- */
- String toJavaFormatString();
-
- /**
- * Appends a floating point value to an Appendable.
- * @param buf The Appendable to receive the value.
- */
- void appendTo(Appendable buf);
+ int getChars(byte[] result);
/**
* Retrieves the decimal exponent most closely corresponding to this value.
@@ -209,19 +161,10 @@ public class FloatingDecimal{
}
@Override
- public String toJavaFormatString() {
- return image;
- }
-
- @Override
- public void appendTo(Appendable buf) {
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(image);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(image);
- } else {
- assert false;
- }
+ @SuppressWarnings("deprecation")
+ public int getChars(byte[] chars) {
+ image.getBytes(0, image.length(), chars, 0);
+ return image.length();
}
@Override
@@ -261,8 +204,8 @@ public class FloatingDecimal{
private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
- private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
- private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new byte[]{'0'});
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new byte[]{'0'});
/**
* A buffered implementation of BinaryToASCIIConverter.
@@ -272,8 +215,7 @@ public class FloatingDecimal{
private int decExponent;
private int firstDigitIndex;
private int nDigits;
- private final char[] digits;
- private final char[] buffer = new char[26];
+ private final byte[] digits;
//
// The fields below provide additional information about the result of
@@ -293,13 +235,13 @@ public class FloatingDecimal{
* BinaryToASCIIBuffer may be thread-local and reused
*/
BinaryToASCIIBuffer(){
- this.digits = new char[20];
+ this.digits = new byte[20];
}
/**
* Creates a specialized value (positive and negative zeros).
*/
- BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+ BinaryToASCIIBuffer(boolean isNegative, byte[] digits){
this.isNegative = isNegative;
this.decExponent = 0;
this.digits = digits;
@@ -307,24 +249,6 @@ public class FloatingDecimal{
this.nDigits = digits.length;
}
- @Override
- public String toJavaFormatString() {
- int len = getChars(buffer);
- return new String(buffer, 0, len);
- }
-
- @Override
- public void appendTo(Appendable buf) {
- int len = getChars(buffer);
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(buffer, 0, len);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(buffer, 0, len);
- } else {
- assert false;
- }
- }
-
@Override
public int getDecimalExponent() {
return decExponent;
@@ -403,12 +327,12 @@ public class FloatingDecimal{
ivalue /= 10;
}
while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
+ digits[digitno--] = (byte)(c+'0');
decExponent++;
c = ivalue%10;
ivalue /= 10;
}
- digits[digitno] = (char)(c+'0');
+ digits[digitno] = (byte)(c+'0');
} else {
// same algorithm as above (same bugs, too )
// but using long arithmetic.
@@ -420,12 +344,12 @@ public class FloatingDecimal{
lvalue /= 10L;
}
while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
+ digits[digitno--] = (byte) (c+'0');
decExponent++;
c = (int)(lvalue%10L);
lvalue /= 10;
}
- digits[digitno] = (char)(c+'0');
+ digits[digitno] = (byte)(c+'0');
}
this.decExponent = decExponent+1;
this.firstDigitIndex = digitno;
@@ -626,7 +550,7 @@ public class FloatingDecimal{
// oops. Usually ignore leading zero.
decExp--;
} else {
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
//
// HACK! Java spec sez that we always have at least
@@ -654,7 +578,7 @@ public class FloatingDecimal{
low = true;
high = true;
}
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
lowDigitDifference = (b<<1) - tens;
exactDecimalConversion = (b == 0);
@@ -680,7 +604,7 @@ public class FloatingDecimal{
// oops. Usually ignore leading zero.
decExp--;
} else {
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
//
// HACK! Java spec sez that we always have at least
@@ -708,7 +632,7 @@ public class FloatingDecimal{
low = true;
high = true;
}
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
lowDigitDifference = (b<<1) - tens;
exactDecimalConversion = (b == 0);
@@ -741,7 +665,7 @@ public class FloatingDecimal{
// oops. Usually ignore leading zero.
decExp--;
} else {
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
//
// HACK! Java spec sez that we always have at least
@@ -758,7 +682,7 @@ public class FloatingDecimal{
Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
low = (Bval.cmp( Mval ) < 0);
high = tenSval.addAndCmp(Bval,Mval)<=0;
- digits[ndigit++] = (char)('0' + q);
+ digits[ndigit++] = (byte)('0' + q);
}
if ( high && low ){
Bval = Bval.leftShift(1);
@@ -812,7 +736,7 @@ public class FloatingDecimal{
}
// else fall through.
}
- digits[i] = (char) (q + 1);
+ digits[i] = (byte) (q + 1);
decimalDigitsRoundedUp = true;
}
@@ -845,19 +769,8 @@ public class FloatingDecimal{
}
}
- private static int insignificantDigits(long insignificant) {
- int i;
- for ( i = 0; insignificant >= 10L; i++ ) {
- insignificant /= 10L;
- }
- return i;
- }
-
/**
* Calculates
- *
- * insignificantDigitsForPow2(v) == insignificantDigits(1L<
*/
private static int insignificantDigitsForPow2(int p2) {
if (p2 > 1 && p2 < insignificantDigitsNumber.length) {
@@ -913,7 +826,14 @@ public class FloatingDecimal{
61,
};
- private int getChars(char[] result) {
+ /**
+ * Converts the decimal representation of a floating-point number into its
+ * ASCII character representation and stores it in the provided byte array.
+ *
+ * @param result the byte array to store the ASCII representation, must have length at least 26
+ * @return the number of characters written to the result array
+ */
+ public int getChars(byte[] result) {
assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
int i = 0;
if (isNegative) {
@@ -927,7 +847,7 @@ public class FloatingDecimal{
i += charLength;
if (charLength < decExponent) {
charLength = decExponent - charLength;
- Arrays.fill(result,i,i+charLength,'0');
+ Arrays.fill(result, i, i + charLength, (byte) '0');
i += charLength;
result[i++] = '.';
result[i++] = '0';
@@ -935,7 +855,7 @@ public class FloatingDecimal{
result[i++] = '.';
if (charLength < nDigits) {
int t = nDigits - charLength;
- System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+ System.arraycopy(digits, firstDigitIndex + charLength, result, i, t);
i += t;
} else {
result[i++] = '0';
@@ -945,7 +865,7 @@ public class FloatingDecimal{
result[i++] = '0';
result[i++] = '.';
if (decExponent != 0) {
- Arrays.fill(result, i, i-decExponent, '0');
+ Arrays.fill(result, i, i-decExponent, (byte) '0');
i -= decExponent;
}
System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
@@ -969,15 +889,15 @@ public class FloatingDecimal{
}
// decExponent has 1, 2, or 3, digits
if (e <= 9) {
- result[i++] = (char) (e + '0');
+ result[i++] = (byte) (e + '0');
} else if (e <= 99) {
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
+ result[i++] = (byte) (e / 10 + '0');
+ result[i++] = (byte) (e % 10 + '0');
} else {
- result[i++] = (char) (e / 100 + '0');
+ result[i++] = (byte) (e / 100 + '0');
e %= 100;
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
+ result[i++] = (byte) (e / 10 + '0');
+ result[i++] = (byte) (e % 10 + '0');
}
}
return i;
@@ -1043,10 +963,10 @@ public class FloatingDecimal{
* A buffered implementation of ASCIIToBinaryConverter.
*/
static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
- boolean isNegative;
- int decExponent;
- byte[] digits;
- int nDigits;
+ final boolean isNegative;
+ final int decExponent;
+ final byte[] digits;
+ int nDigits;
ASCIIToBinaryBuffer( boolean negSign, int decExponent, byte[] digits, int n)
{
@@ -1765,10 +1685,10 @@ public class FloatingDecimal{
buf.decimalDigitsRoundedUp = dec.getAway();
long f = dec.getSignificand();
- char[] digits = buf.digits;
+ byte[] digits = buf.digits;
for (int i = buf.nDigits - 1; i >= 0; --i) {
long q = f / 10;
- digits[i] = (char) ((f - 10 * q) + '0');
+ digits[i] = (byte) ((f - 10 * q) + '0');
f = q;
}
return buf;
@@ -1819,58 +1739,14 @@ public class FloatingDecimal{
return buf;
}
- private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
- int fBits = Float.floatToRawIntBits( f );
- boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
- int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
- int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
- // Discover obvious special cases of NaN and Infinity.
- if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
- if ( fractBits == 0L ){
- return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
- } else {
- return B2AC_NOT_A_NUMBER;
- }
- }
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- int nSignificantBits;
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
- }
- int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
- int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
- fractBits <<= shift;
- binExp = 1 - shift;
- nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
- } else {
- fractBits |= SINGLE_FRACT_HOB;
- nSignificantBits = SINGLE_EXP_SHIFT+1;
- }
- binExp -= FloatConsts.EXP_BIAS;
- BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
- buf.setSign(isNegative);
- // call the routine that actually does all the hard work.
- buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
- return buf;
- }
-
- static ASCIIToBinaryConverter readDoubleSignlessDigits(int decExp, char[] digits, int length) {
+ static ASCIIToBinaryConverter readDoubleSignlessDigits(int decExp, byte[] digits, int length) {
// Prevent an extreme negative exponent from causing overflow issues in doubleValue().
// Large positive values are handled within doubleValue();
if (decExp < MIN_DECIMAL_EXPONENT) {
return A2BC_POSITIVE_ZERO;
}
- byte[] buf = new byte[length];
- for (int i = 0; i < length; i++) {
- buf[i] = (byte) digits[i];
- }
- return new ASCIIToBinaryBuffer(false, decExp, buf, length);
+ return new ASCIIToBinaryBuffer(false, decExp, digits, length);
}
/**
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributes.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributes.java
index 6fc86b66735..48dc4c07d0d 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributes.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributes.java
@@ -81,8 +81,11 @@ class UnixFileAttributes
return attrs;
}
- // get the UnixFileAttributes for a given file. Returns null if the file does not exist.
- static UnixFileAttributes getIfExists(UnixPath path) throws UnixException {
+ // get the UnixFileAttributes for a given file.
+ // Returns null if the file does not exist.
+ static UnixFileAttributes getIfExists(UnixPath path)
+ throws UnixException
+ {
UnixFileAttributes attrs = new UnixFileAttributes();
int errno = UnixNativeDispatcher.stat2(path, attrs);
if (errno == 0) {
@@ -94,6 +97,26 @@ class UnixFileAttributes
}
}
+ // get the UnixFileAttributes for a given file, optionally following links.
+ // Returns null if the file does not exist.
+ static UnixFileAttributes getIfExists(UnixPath path, boolean followLinks)
+ throws UnixException
+ {
+ UnixFileAttributes attrs = new UnixFileAttributes();
+ int flag = (followLinks) ? 0 : UnixConstants.AT_SYMLINK_NOFOLLOW;
+ try {
+ UnixNativeDispatcher.fstatat(UnixConstants.AT_FDCWD,
+ path.asByteArray(), flag, attrs);
+ } catch (UnixException x) {
+ if (x.errno() == UnixConstants.ENOENT)
+ return null;
+
+ throw x;
+ }
+
+ return attrs;
+ }
+
// get the UnixFileAttributes for an open file
static UnixFileAttributes get(int fd) throws UnixException {
UnixFileAttributes attrs = new UnixFileAttributes();
diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java
index beb9a1af41b..a1c68934604 100644
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, 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
@@ -53,6 +53,7 @@ import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.spi.FileTypeDetector;
import java.util.Map;
+import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -348,8 +349,32 @@ public abstract class UnixFileSystemProvider
return access(file, X_OK) == 0;
}
+ // find the key of the last accessible link in the chain
+ private UnixFileKey lastFileKey(UnixPath path) throws UnixException {
+ var fileKeys = new HashSet();
+ UnixFileKey lastFileKey = null;
+ while (path != null) {
+ UnixFileAttributes attrs = UnixFileAttributes.getIfExists(path, false);
+ if (attrs == null) {
+ break;
+ }
+ UnixFileKey fileKey = attrs.fileKey();
+ if (!attrs.isSymbolicLink()) {
+ break;
+ }
+ if (!fileKeys.add(fileKey)) {
+ throw new UnixException(ELOOP);
+ }
+ lastFileKey = fileKey;
+ byte[] target = readlink(path);
+ path = new UnixPath(theFileSystem, target);
+ }
+ return lastFileKey;
+ }
+
@Override
public boolean isSameFile(Path obj1, Path obj2) throws IOException {
+ // toUnixPath verifies its argument is a non-null UnixPath
UnixPath file1 = UnixPath.toUnixPath(obj1);
if (file1.equals(obj2))
return true;
@@ -358,21 +383,28 @@ public abstract class UnixFileSystemProvider
if (!(obj2 instanceof UnixPath file2))
return false;
- UnixFileAttributes attrs1;
- UnixFileAttributes attrs2;
+ UnixFileKey key1;
try {
- attrs1 = UnixFileAttributes.get(file1, true);
- } catch (UnixException x) {
- x.rethrowAsIOException(file1);
- return false; // keep compiler happy
+ UnixFileAttributes attrs = UnixFileAttributes.getIfExists(file1);
+ key1 = (attrs != null) ? attrs.fileKey() : lastFileKey(file1);
+ } catch (UnixException e) {
+ e.rethrowAsIOException(file1);
+ return false;
}
+
+ if (key1 == null)
+ return false;
+
+ UnixFileKey key2;
try {
- attrs2 = UnixFileAttributes.get(file2, true);
- } catch (UnixException x) {
- x.rethrowAsIOException(file2);
- return false; // keep compiler happy
+ UnixFileAttributes attrs = UnixFileAttributes.getIfExists(file2);
+ key2 = (attrs != null) ? attrs.fileKey() : lastFileKey(file2);
+ } catch (UnixException e) {
+ e.rethrowAsIOException(file2);
+ return false;
}
- return attrs1.isSameFile(attrs2);
+
+ return key1.equals(key2);
}
@Override
diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
index 3a1bb416fe7..5e740ec1f4d 100644
--- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
+++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, 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
@@ -434,8 +434,15 @@ class WindowsFileSystemProvider
try {
h1 = file1.openForReadAttributeAccess(true);
} catch (WindowsException x) {
- x.rethrowAsIOException(file1);
+ if (x.lastError() != ERROR_FILE_NOT_FOUND &&
+ x.lastError() != ERROR_PATH_NOT_FOUND)
+ x.rethrowAsIOException(file1);
}
+
+ // if file1 does not exist, it cannot equal file2
+ if (h1 == 0L)
+ return false;
+
try {
WindowsFileAttributes attrs1 = null;
try {
@@ -447,8 +454,15 @@ class WindowsFileSystemProvider
try {
h2 = file2.openForReadAttributeAccess(true);
} catch (WindowsException x) {
- x.rethrowAsIOException(file2);
+ if (x.lastError() != ERROR_FILE_NOT_FOUND &&
+ x.lastError() != ERROR_PATH_NOT_FOUND)
+ x.rethrowAsIOException(file2);
}
+
+ // if file2 does not exist, it cannot equal file1, which does
+ if (h2 == 0L)
+ return false;
+
try {
WindowsFileAttributes attrs2 = null;
try {
diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java
index 9558991b767..e009e33d8a0 100644
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java
@@ -734,6 +734,7 @@ public class GIFImageWriter extends ImageWriter {
if (writeTrailer) {
writeTrailer();
}
+ stream.flush();
}
/**
diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java
index e2227ee6b48..d56bc89035b 100644
--- a/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java
+++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java
@@ -2327,6 +2327,7 @@ public class TIFFImageWriter extends ImageWriter {
if (abortRequested()) {
resetPositions();
}
+ stream.flush();
}
private void writeHeader() throws IOException {
diff --git a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java
index 5e1e149eb9e..91e0f8dc54d 100644
--- a/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java
+++ b/src/java.desktop/share/classes/com/sun/java/swing/SwingUtilities3.java
@@ -69,10 +69,6 @@ public class SwingUtilities3 {
private static final Object DELEGATE_REPAINT_MANAGER_KEY =
new StringBuilder("DelegateRepaintManagerKey");
- private static Color disabledForeground;
- private static Color acceleratorSelectionForeground;
- private static Color acceleratorForeground;
-
/**
* Registers delegate RepaintManager for {@code JComponent}.
*/
@@ -204,7 +200,10 @@ public class SwingUtilities3 {
public static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
- MenuItemLayoutHelper.LayoutResult lr) {
+ MenuItemLayoutHelper.LayoutResult lr,
+ Color disabledForeground,
+ Color acceleratorSelectionForeground,
+ Color acceleratorForeground) {
if (!lh.getAccText().isEmpty()) {
ButtonModel model = lh.getMenuItem().getModel();
g.setFont(lh.getAccFontMetrics().getFont());
@@ -243,18 +242,6 @@ public class SwingUtilities3 {
}
}
- public static void setDisabledForeground(Color disabledFg) {
- disabledForeground = disabledFg;
- }
-
- public static void setAcceleratorSelectionForeground(Color acceleratorSelectionFg) {
- acceleratorSelectionForeground = acceleratorSelectionFg;
- }
-
- public static void setAcceleratorForeground(Color acceleratorFg) {
- acceleratorForeground = acceleratorFg;
- }
-
public static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr,
Color foreground) {
diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
index 524f0337a8f..d361906b291 100644
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicMenuItemUI.java
@@ -716,11 +716,10 @@ public class BasicMenuItemUI extends MenuItemUI
private void paintAccText(Graphics g, MenuItemLayoutHelper lh,
MenuItemLayoutHelper.LayoutResult lr) {
- SwingUtilities3.setDisabledForeground(disabledForeground);
- SwingUtilities3.setAcceleratorSelectionForeground(
- acceleratorSelectionForeground);
- SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
- SwingUtilities3.paintAccText(g, lh, lr);
+ SwingUtilities3.paintAccText(g, lh, lr,
+ disabledForeground,
+ acceleratorSelectionForeground,
+ acceleratorForeground);
}
private void paintText(Graphics g, MenuItemLayoutHelper lh,
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
index f59a59a5125..02054575d77 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java
@@ -84,7 +84,9 @@ public final class WindowsCheckBoxMenuItemUI extends BasicCheckBoxMenuItemUI {
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
- arrowIcon, background, foreground, defaultTextIconGap,
+ arrowIcon, background, foreground,
+ disabledForeground, acceleratorSelectionForeground,
+ acceleratorForeground, defaultTextIconGap,
menuItem, getPropertyPrefix());
return;
}
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
index a8bafc54c33..aa90b2f35b3 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java
@@ -67,9 +67,6 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
* The instance of {@code PropertyChangeListener}.
*/
private PropertyChangeListener changeListener;
- private static Color disabledForeground;
- private static Color acceleratorSelectionForeground;
- private static Color acceleratorForeground;
final WindowsMenuItemUIAccessor accessor =
new WindowsMenuItemUIAccessor() {
@@ -167,36 +164,6 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
changeListener = null;
}
- private static void applyInsets(Rectangle rect, Insets insets) {
- SwingUtilities3.applyInsets(rect, insets);
- }
-
- private static void paintCheckIcon(Graphics g, MenuItemLayoutHelper lh,
- MenuItemLayoutHelper.LayoutResult lr,
- Color holdc, Color foreground) {
- SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
- }
-
- private static void paintIcon(Graphics g, MenuItemLayoutHelper lh,
- MenuItemLayoutHelper.LayoutResult lr, Color holdc) {
- SwingUtilities3.paintIcon(g, lh, lr, holdc);
- }
-
- private static void paintAccText(Graphics g, MenuItemLayoutHelper lh,
- MenuItemLayoutHelper.LayoutResult lr) {
- SwingUtilities3.setDisabledForeground(disabledForeground);
- SwingUtilities3.setAcceleratorSelectionForeground(
- acceleratorSelectionForeground);
- SwingUtilities3.setAcceleratorForeground(acceleratorForeground);
- SwingUtilities3.paintAccText(g, lh, lr);
- }
-
- private static void paintArrowIcon(Graphics g, MenuItemLayoutHelper lh,
- MenuItemLayoutHelper.LayoutResult lr,
- Color foreground) {
- SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
- }
-
protected void paintMenuItem(Graphics g, JComponent c,
Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
@@ -204,7 +171,8 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
arrowIcon, background, foreground,
- defaultTextIconGap, menuItem,
+ disabledForeground, acceleratorSelectionForeground,
+ acceleratorForeground, defaultTextIconGap, menuItem,
getPropertyPrefix());
return;
}
@@ -215,6 +183,9 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g,
JComponent c, Icon checkIcon, Icon arrowIcon,
Color background, Color foreground,
+ Color disabledForeground,
+ Color acceleratorSelectionForeground,
+ Color acceleratorForeground,
int defaultTextIconGap, JMenuItem menuItem, String prefix) {
// Save original graphics font and color
Font holdf = g.getFont();
@@ -224,7 +195,7 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
g.setFont(mi.getFont());
Rectangle viewRect = new Rectangle(0, 0, mi.getWidth(), mi.getHeight());
- applyInsets(viewRect, mi.getInsets());
+ SwingUtilities3.applyInsets(viewRect, mi.getInsets());
String acceleratorDelimiter =
UIManager.getString("MenuItem.acceleratorDelimiter");
@@ -242,8 +213,8 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
MenuItemLayoutHelper.LayoutResult lr = lh.layoutMenuItem();
paintBackground(accessor, g, mi, background);
- paintCheckIcon(g, lh, lr, holdc, foreground);
- paintIcon(g, lh, lr, holdc);
+ SwingUtilities3.paintCheckIcon(g, lh, lr, holdc, foreground);
+ SwingUtilities3.paintIcon(g, lh, lr, holdc);
if (lh.getCheckIcon() != null && lh.useCheckAndArrow()) {
Rectangle rect = lr.getTextRect();
@@ -267,8 +238,10 @@ public final class WindowsMenuItemUI extends BasicMenuItemUI {
rect.x += lh.getAfterCheckIconGap();
lr.setAccRect(rect);
}
- paintAccText(g, lh, lr);
- paintArrowIcon(g, lh, lr, foreground);
+ SwingUtilities3.paintAccText(g, lh, lr, disabledForeground,
+ acceleratorSelectionForeground,
+ acceleratorForeground);
+ SwingUtilities3.paintArrowIcon(g, lh, lr, foreground);
// Restore original graphics font and color
g.setColor(holdc);
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
index 81c01c11036..1476c6fc152 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java
@@ -140,7 +140,8 @@ public final class WindowsMenuUI extends BasicMenuUI {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon,
background, foreground,
- defaultTextIconGap, menuItem,
+ disabledForeground, acceleratorSelectionForeground,
+ acceleratorForeground, defaultTextIconGap, menuItem,
getPropertyPrefix());
return;
}
diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
index 385ab6b3634..628a4be1637 100644
--- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
+++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java
@@ -84,7 +84,9 @@ public final class WindowsRadioButtonMenuItemUI extends BasicRadioButtonMenuItem
int defaultTextIconGap) {
if (WindowsMenuItemUI.isVistaPainting()) {
WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon,
- arrowIcon, background, foreground, defaultTextIconGap,
+ arrowIcon, background, foreground,
+ disabledForeground, acceleratorSelectionForeground,
+ acceleratorForeground, defaultTextIconGap,
menuItem, getPropertyPrefix());
return;
}
diff --git a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java
index e893a58f9ed..0e4e5bd585e 100644
--- a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java
@@ -44,6 +44,8 @@ import java.util.Map;
import sun.awt.AWTAccessor;
import sun.awt.AWTAccessor.ComponentAccessor;
import sun.awt.im.InputMethodAdapter;
+import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
final class WInputMethod extends InputMethodAdapter
{
@@ -124,6 +126,8 @@ final class WInputMethod extends InputMethodAdapter
public WInputMethod()
{
context = createNativeContext();
+ disposerRecord = new ContextDisposerRecord(context);
+ Disposer.addRecord(this, disposerRecord);
cmode = getConversionStatus(context);
open = getOpenStatus(context);
currentLocale = getNativeLocale();
@@ -132,16 +136,23 @@ final class WInputMethod extends InputMethodAdapter
}
}
- @Override
- @SuppressWarnings("removal")
- protected void finalize() throws Throwable
- {
- // Release the resources used by the native input context.
- if (context!=0) {
- destroyNativeContext(context);
- context=0;
+ private final ContextDisposerRecord disposerRecord;
+
+ private static final class ContextDisposerRecord implements DisposerRecord {
+
+ private final int context;
+ private volatile boolean disposed;
+
+ ContextDisposerRecord(int c) {
+ context = c;
+ }
+
+ public synchronized void dispose() {
+ if (!disposed) {
+ destroyNativeContext(context);
+ }
+ disposed = true;
}
- super.finalize();
}
@Override
@@ -151,9 +162,7 @@ final class WInputMethod extends InputMethodAdapter
@Override
public void dispose() {
- // Due to a memory management problem in Windows 98, we should retain
- // the native input context until this object is finalized. So do
- // nothing here.
+ disposerRecord.dispose();
}
/**
@@ -448,6 +457,7 @@ final class WInputMethod extends InputMethodAdapter
@Override
public void removeNotify() {
endCompositionNative(context, DISCARD_INPUT);
+ disableNativeIME(awtFocussedComponentPeer);
awtFocussedComponent = null;
awtFocussedComponentPeer = null;
}
@@ -658,8 +668,8 @@ final class WInputMethod extends InputMethodAdapter
}
- private native int createNativeContext();
- private native void destroyNativeContext(int context);
+ private static native int createNativeContext();
+ private static native void destroyNativeContext(int context);
private native void enableNativeIME(WComponentPeer peer, int context, boolean useNativeCompWindow);
private native void disableNativeIME(WComponentPeer peer);
private native void handleNativeIMEEvent(WComponentPeer peer, AWTEvent e);
diff --git a/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp b/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp
index fcc6e4c2cb8..87087870b5d 100644
--- a/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp
+++ b/src/java.desktop/windows/native/libawt/windows/awt_InputMethod.cpp
@@ -52,7 +52,7 @@ extern BOOL g_bUserHasChangedInputLang;
* Signature: ()I
*/
JNIEXPORT jint JNICALL
-Java_sun_awt_windows_WInputMethod_createNativeContext(JNIEnv *env, jobject self)
+Java_sun_awt_windows_WInputMethod_createNativeContext(JNIEnv *env, jclass cls)
{
TRY;
@@ -69,7 +69,7 @@ Java_sun_awt_windows_WInputMethod_createNativeContext(JNIEnv *env, jobject self)
* Signature: (I)V
*/
JNIEXPORT void JNICALL
-Java_sun_awt_windows_WInputMethod_destroyNativeContext(JNIEnv *env, jobject self, jint context)
+Java_sun_awt_windows_WInputMethod_destroyNativeContext(JNIEnv *env, jclass cls, jint context)
{
TRY_NO_VERIFY;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
index 980ce060c33..65ce640ef76 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, 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
@@ -412,6 +412,7 @@ public class JavacTaskImpl extends BasicJavacTask {
f.run(compiler.todo, classes);
}
} finally {
+ compiler.log.reportOutstandingWarnings();
compiler.log.flush();
}
return results;
@@ -483,8 +484,10 @@ public class JavacTaskImpl extends BasicJavacTask {
}
}
finally {
- if (compiler != null)
+ if (compiler != null) {
+ compiler.log.reportOutstandingWarnings();
compiler.log.flush();
+ }
}
return results;
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java
index 6214c3775d3..65772cdccb3 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java
@@ -55,6 +55,7 @@ import com.sun.source.util.TaskEvent.Kind;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
@@ -268,6 +269,7 @@ public class JavacTaskPool {
if (ht.get(Log.logKey) instanceof ReusableLog) {
//log already inited - not first round
Log.instance(this).clear();
+ LintMapper.instance(this).clear();
Enter.instance(this).newRound();
((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
Types.instance(this).newRound();
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
index 4ced466d938..2eca26de838 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java
@@ -360,9 +360,14 @@ public class JavacTrees extends DocTrees {
Log.DeferredDiagnosticHandler deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
try {
Env env = getAttrContext(path.getTreePath());
- Type t = attr.attribType(dcReference.qualifierExpression, env);
- if (t != null && !t.isErroneous()) {
- return t;
+ JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
+ try {
+ Type t = attr.attribType(dcReference.qualifierExpression, env);
+ if (t != null && !t.isErroneous()) {
+ return t;
+ }
+ } finally {
+ log.useSource(prevSource);
}
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
@@ -388,6 +393,7 @@ public class JavacTrees extends DocTrees {
return null;
}
Log.DeferredDiagnosticHandler deferredDiagnosticHandler = log.new DeferredDiagnosticHandler();
+ JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
try {
final TypeSymbol tsym;
final Name memberName;
@@ -509,6 +515,7 @@ public class JavacTrees extends DocTrees {
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
} finally {
+ log.useSource(prevSource);
log.popDiagnosticHandler(deferredDiagnosticHandler);
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java
deleted file mode 100644
index 11544b92b7f..00000000000
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.javac.code;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Optional;
-import java.util.function.Consumer;
-
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.Tag;
-import com.sun.tools.javac.util.Assert;
-import com.sun.tools.javac.util.Context;
-
-/**
- * Holds pending {@link Lint} warnings until the {@lint Lint} instance associated with the containing
- * module, package, class, method, or variable declaration is known so that {@link @SupressWarnings}
- * suppressions may be applied.
- *
- *
- * Warnings are regsistered at any time prior to attribution via {@link #report}. The warning will be
- * associated with the declaration placed in context by the most recent invocation of {@link #push push()}
- * not yet {@link #pop}'d. Warnings are actually emitted later, during attribution, via {@link #flush}.
- *
- *
- * There is also an "immediate" mode, where warnings are emitted synchronously; see {@link #pushImmediate}.
- *
- *
- * Deferred warnings are grouped by the innermost containing module, package, class, method, or variable
- * declaration (represented by {@link JCTree} nodes), so that the corresponding {@link Lint} configuration
- * can be applied when the warning is eventually generated.
- *
- *
This is NOT part of any supported API.
- * If you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.
- */
-public class DeferredLintHandler {
-
- protected static final Context.Key deferredLintHandlerKey = new Context.Key<>();
-
- public static DeferredLintHandler instance(Context context) {
- DeferredLintHandler instance = context.get(deferredLintHandlerKey);
- if (instance == null)
- instance = new DeferredLintHandler(context);
- return instance;
- }
-
- /**
- * Registered {@link LintLogger}s grouped by the innermost containing module, package, class,
- * method, or variable declaration.
- */
- private final HashMap> deferralMap = new HashMap<>();
-
- /**
- * The current "reporter" stack, reflecting calls to {@link #push} and {@link #pop}.
- *
- *
- * The top of the stack determines how calls to {@link #report} are handled.
- */
- private final ArrayDeque> reporterStack = new ArrayDeque<>();
-
- @SuppressWarnings("this-escape")
- protected DeferredLintHandler(Context context) {
- context.put(deferredLintHandlerKey, this);
- Lint rootLint = Lint.instance(context);
- pushImmediate(rootLint); // default to "immediate" mode
- }
-
-// LintLogger
-
- /**An interface for deferred lint reporting - loggers passed to
- * {@link #report(LintLogger) } will be called when
- * {@link #flush(DiagnosticPosition) } is invoked.
- */
- public interface LintLogger {
-
- /**
- * Generate a warning if appropriate.
- *
- * @param lint the applicable lint configuration
- */
- void report(Lint lint);
- }
-
-// Reporter Stack
-
- /**
- * Defer {@link #report}ed warnings until the given declaration is flushed.
- *
- * @param decl module, package, class, method, or variable declaration
- * @see #pop
- */
- public void push(JCTree decl) {
- Assert.check(decl.getTag() == Tag.MODULEDEF
- || decl.getTag() == Tag.PACKAGEDEF
- || decl.getTag() == Tag.CLASSDEF
- || decl.getTag() == Tag.METHODDEF
- || decl.getTag() == Tag.VARDEF);
- reporterStack.push(logger -> deferralMap
- .computeIfAbsent(decl, s -> new ArrayList<>())
- .add(logger));
- }
-
- /**
- * Enter "immediate" mode so that {@link #report}ed warnings are emitted synchonously.
- *
- * @param lint lint configuration to use for reported warnings
- */
- public void pushImmediate(Lint lint) {
- reporterStack.push(logger -> logger.report(lint));
- }
-
- /**
- * Revert to the previous configuration in effect prior to the most recent invocation
- * of {@link #push} or {@link #pushImmediate}.
- *
- * @see #pop
- */
- public void pop() {
- Assert.check(reporterStack.size() > 1); // the bottom stack entry should never be popped
- reporterStack.pop();
- }
-
- /**
- * Report a warning.
- *
- *
- * In immediate mode, the warning is emitted synchronously. Otherwise, the warning is emitted later
- * when the current declaration is flushed.
- */
- public void report(LintLogger logger) {
- Assert.check(!reporterStack.isEmpty());
- reporterStack.peek().accept(logger);
- }
-
-// Warning Flush
-
- /**
- * Emit deferred warnings encompassed by the given declaration.
- *
- * @param decl module, package, class, method, or variable declaration
- * @param lint lint configuration corresponding to {@code decl}
- */
- public void flush(JCTree decl, Lint lint) {
- Optional.of(decl)
- .map(deferralMap::remove)
- .stream()
- .flatMap(ArrayList::stream)
- .forEach(logger -> logger.report(lint));
- }
-}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
index 6d83f95fce4..8eab238f82a 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
@@ -374,11 +374,8 @@ public class Lint {
/**
* Warn about issues relating to use of text blocks
- *
- *
- * This category is not supported by {@code @SuppressWarnings} (yet - see JDK-8224228).
*/
- TEXT_BLOCKS("text-blocks", false),
+ TEXT_BLOCKS("text-blocks"),
/**
* Warn about possible 'this' escapes before subclass instance is fully initialized.
@@ -476,27 +473,6 @@ public class Lint {
return suppressedValues.contains(lc);
}
- /**
- * Helper method. Log a lint warning if its lint category is enabled.
- *
- * @param warning key for the localized warning message
- */
- public void logIfEnabled(LintWarning warning) {
- logIfEnabled(null, warning);
- }
-
- /**
- * Helper method. Log a lint warning if its lint category is enabled.
- *
- * @param pos source position at which to report the warning
- * @param warning key for the localized warning message
- */
- public void logIfEnabled(DiagnosticPosition pos, LintWarning warning) {
- if (isEnabled(warning.getLintCategory())) {
- log.warning(pos, warning);
- }
- }
-
/**
* Obtain the set of recognized lint warning categories suppressed at the given symbol's declaration.
*
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java
new file mode 100644
index 00000000000..b15ddae02e1
--- /dev/null
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/LintMapper.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.code;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.tree.EndPosTable;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeScanner;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+
+/**
+ * Maps source code positions to the applicable {@link Lint} instance.
+ *
+ *
+ * Because {@code @SuppressWarnings} is a Java symbol, in general this mapping can't be
+ * calculated until after attribution. As each top-level declaration (class, package, or module)
+ * is attributed, this singleton is notified and the {@link Lint}s that apply to every source
+ * position within that top-level declaration are calculated.
+ *
+ *
+ * The method {@link #lintAt} returns the {@link Lint} instance applicable to source position;
+ * if it can't be determined yet, an empty {@link Optional} is returned.
+ *
+ *
This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.
+ */
+public class LintMapper {
+
+ // The key for the context singleton
+ private static final Context.Key CONTEXT_KEY = new Context.Key<>();
+
+ // Per-source file information. Note: during the parsing of a file, an entry exists but the FileInfo value is null
+ private final Map fileInfoMap = new HashMap<>();
+
+ // Compiler context
+ private final Context context;
+
+ // These are initialized lazily; see initializeIfNeeded()
+ private Lint rootLint;
+
+ /**
+ * Obtain the {@link LintMapper} context singleton.
+ */
+ public static LintMapper instance(Context context) {
+ LintMapper instance = context.get(CONTEXT_KEY);
+ if (instance == null)
+ instance = new LintMapper(context);
+ return instance;
+ }
+
+ /**
+ * Constructor.
+ */
+ @SuppressWarnings("this-escape")
+ protected LintMapper(Context context) {
+ context.put(CONTEXT_KEY, this);
+ this.context = context;
+ }
+
+ // Lazy initialization to avoid dependency loops
+ private void initializeIfNeeded() {
+ if (rootLint == null)
+ rootLint = Lint.instance(context);
+ }
+
+// Lint Operations
+
+ /**
+ * Determine if the given file is known to this instance.
+ *
+ * @param sourceFile source file
+ * @return true if file is recognized
+ */
+ public boolean isKnown(JavaFileObject sourceFile) {
+ return fileInfoMap.containsKey(sourceFile);
+ }
+
+ /**
+ * Obtain the {@link Lint} configuration that applies at the given position, if known.
+ *
+ * @param sourceFile source file
+ * @param pos source position
+ * @return the applicable {@link Lint}, if known, otherwise empty
+ */
+ public Optional lintAt(JavaFileObject sourceFile, DiagnosticPosition pos) {
+ initializeIfNeeded();
+ return Optional.of(sourceFile)
+ .map(fileInfoMap::get)
+ .flatMap(fileInfo -> fileInfo.lintAt(pos));
+ }
+
+ /**
+ * Calculate {@lint Lint} configurations for all positions within the given top-level declaration.
+ *
+ * @param sourceFile source file
+ * @param tree top-level declaration (class, package, or module)
+ */
+ public void calculateLints(JavaFileObject sourceFile, JCTree tree, EndPosTable endPositions) {
+ Assert.check(rootLint != null);
+ fileInfoMap.get(sourceFile).afterAttr(tree, endPositions);
+ }
+
+ /**
+ * Reset this instance.
+ */
+ public void clear() {
+ fileInfoMap.clear();
+ }
+
+// Parsing Notifications
+
+ /**
+ * Invoked when file parsing starts to create an entry for the new file (but with a null value).
+ */
+ public void startParsingFile(JavaFileObject sourceFile) {
+ initializeIfNeeded();
+ fileInfoMap.put(sourceFile, null);
+ }
+
+ /**
+ * Invoked when file parsing completes to put in place a corresponding {@link FileInfo}.
+ */
+ public void finishParsingFile(JCCompilationUnit tree) {
+ Assert.check(rootLint != null);
+ fileInfoMap.put(tree.sourcefile, new FileInfo(rootLint, tree));
+ }
+
+// FileInfo
+
+ /**
+ * Holds {@link Lint} information for a fully parsed source file.
+ *
+ *
+ * Initially (immediately after parsing), "unmappedDecls" contains a {@link Span} corresponding to each
+ * top-level declaration in the source file. As each top-level declaration is attributed, the corresponding
+ * {@link Span} is removed and the corresponding {@link LintRange} subtree is populated under "rootRange".
+ */
+ private static class FileInfo {
+
+ final LintRange rootRange; // the root LintRange (covering the entire source file)
+ final List unmappedDecls = new ArrayList<>(); // unmapped top-level declarations awaiting attribution
+
+ // After parsing: Add top-level declarations to our "unmappedDecls" list
+ FileInfo(Lint rootLint, JCCompilationUnit tree) {
+ rootRange = new LintRange(rootLint);
+ tree.defs.stream()
+ .filter(this::isTopLevelDecl)
+ .map(decl -> new Span(decl, tree.endPositions))
+ .forEach(unmappedDecls::add);
+ }
+
+ // After attribution: Discard the span from "unmappedDecls" and populate the declaration's subtree under "rootRange"
+ void afterAttr(JCTree tree, EndPosTable endPositions) {
+ for (Iterator i = unmappedDecls.iterator(); i.hasNext(); ) {
+ if (i.next().contains(tree.pos())) {
+ rootRange.populateSubtree(tree, endPositions);
+ i.remove();
+ return;
+ }
+ }
+ throw new AssertionError("top-level declaration not found");
+ }
+
+ // Find the most specific Lint configuration applying to the given position, unless the position has not been mapped yet
+ Optional lintAt(DiagnosticPosition pos) {
+ boolean mapped = unmappedDecls.stream().noneMatch(span -> span.contains(pos));
+ return mapped ? Optional.of(rootRange.bestMatch(pos).lint) : Optional.empty();
+ }
+
+ boolean isTopLevelDecl(JCTree tree) {
+ return tree.getTag() == Tag.MODULEDEF
+ || tree.getTag() == Tag.PACKAGEDEF
+ || tree.getTag() == Tag.CLASSDEF;
+ }
+ }
+
+// Span
+
+ /**
+ * A lexical range.
+ */
+ private record Span(int startPos, int endPos) {
+
+ static final Span MAXIMAL = new Span(Integer.MIN_VALUE, Integer.MAX_VALUE);
+
+ Span(JCTree tree, EndPosTable endPositions) {
+ this(TreeInfo.getStartPos(tree), TreeInfo.getEndPos(tree, endPositions));
+ }
+
+ boolean contains(DiagnosticPosition pos) {
+ int offset = pos.getLintPosition();
+ return offset == startPos || (offset > startPos && offset < endPos);
+ }
+
+ boolean contains(Span that) {
+ return this.startPos <= that.startPos && this.endPos >= that.endPos;
+ }
+ }
+
+// LintRange
+
+ /**
+ * A tree of nested lexical ranges and the {@link Lint} configurations that apply therein.
+ */
+ private record LintRange(
+ Span span, // declaration's lexical range
+ Lint lint, // the Lint configuration that applies at this declaration
+ List children // the nested declarations one level below this node
+ ) {
+
+ // Create a node representing the entire file, using the root lint configuration
+ LintRange(Lint rootLint) {
+ this(Span.MAXIMAL, rootLint, new ArrayList<>());
+ }
+
+ // Create a node representing the given declaration and its corresponding Lint configuration
+ LintRange(JCTree tree, EndPosTable endPositions, Lint lint) {
+ this(new Span(tree, endPositions), lint, new ArrayList<>());
+ }
+
+ // Find the most specific node in this tree (including me) that contains the given position, if any
+ LintRange bestMatch(DiagnosticPosition pos) {
+ return children.stream()
+ .map(child -> child.bestMatch(pos))
+ .filter(Objects::nonNull)
+ .reduce((a, b) -> a.span.contains(b.span) ? b : a)
+ .orElseGet(() -> span.contains(pos) ? this : null);
+ }
+
+ // Populate a sparse subtree corresponding to the given nested declaration.
+ // Only when the Lint configuration differs from the parent is a node added.
+ void populateSubtree(JCTree tree, EndPosTable endPositions) {
+ new TreeScanner() {
+
+ private LintRange currentNode = LintRange.this;
+
+ @Override
+ public void visitModuleDef(JCModuleDecl tree) {
+ scanDecl(tree, tree.sym, super::visitModuleDef);
+ }
+ @Override
+ public void visitPackageDef(JCPackageDecl tree) {
+ scanDecl(tree, tree.packge, super::visitPackageDef);
+ }
+ @Override
+ public void visitClassDef(JCClassDecl tree) {
+ scanDecl(tree, tree.sym, super::visitClassDef);
+ }
+ @Override
+ public void visitMethodDef(JCMethodDecl tree) {
+ scanDecl(tree, tree.sym, super::visitMethodDef);
+ }
+ @Override
+ public void visitVarDef(JCVariableDecl tree) {
+ scanDecl(tree, tree.sym, super::visitVarDef);
+ }
+
+ private void scanDecl(T tree, Symbol symbol, Consumer super T> recursor) {
+
+ // The "symbol" can be null if there were earlier errors; skip this declaration if so
+ if (symbol == null) {
+ recursor.accept(tree);
+ return;
+ }
+
+ // Update the Lint using the declaration; if there's no change, then we don't need a new node here
+ Lint newLint = currentNode.lint.augment(symbol);
+ if (newLint == currentNode.lint) { // note: lint.augment() returns the same instance if there's no change
+ recursor.accept(tree);
+ return;
+ }
+
+ // Add a new node here and proceed
+ final LintRange previousNode = currentNode;
+ currentNode = new LintRange(tree, endPositions, newLint);
+ previousNode.children.add(currentNode);
+ try {
+ recursor.accept(tree);
+ } finally {
+ currentNode = previousNode;
+ }
+ }
+ }.scan(tree);
+ }
+ }
+}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
index e11a9c6754e..1c93c37698a 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
@@ -67,9 +67,6 @@ public class Preview {
/** flag: are preview features enabled */
private final boolean enabled;
- /** flag: is the "preview" lint category enabled? */
- private final boolean verbose;
-
/** test flag: should all features be considered as preview features? */
private final boolean forcePreview;
@@ -100,7 +97,6 @@ public class Preview {
enabled = options.isSet(PREVIEW);
log = Log.instance(context);
source = Source.instance(context);
- verbose = Lint.instance(context).isEnabled(LintCategory.PREVIEW);
forcePreview = options.isSet("forcePreview");
majorVersionToSource = initMajorVersionToSourceMap();
}
@@ -184,9 +180,7 @@ public class Preview {
*/
public void warnPreview(JavaFileObject classfile, int majorVersion) {
Assert.check(isEnabled());
- if (verbose) {
- log.warning(LintWarnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name));
- }
+ log.warning(LintWarnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name));
}
/**
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
index 3da83248436..9f56bec4cca 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
@@ -89,9 +89,7 @@ public class Annotate {
private final Attr attr;
private final Check chk;
private final ConstFold cfolder;
- private final DeferredLintHandler deferredLintHandler;
private final Enter enter;
- private final Lint lint;
private final Log log;
private final Names names;
private final Resolve resolve;
@@ -110,10 +108,8 @@ public class Annotate {
attr = Attr.instance(context);
chk = Check.instance(context);
cfolder = ConstFold.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
enter = Enter.instance(context);
log = Log.instance(context);
- lint = Lint.instance(context);
make = TreeMaker.instance(context);
names = Names.instance(context);
resolve = Resolve.instance(context);
@@ -235,10 +231,8 @@ public class Annotate {
* @param annotations the list of JCAnnotations to attribute and enter
* @param localEnv the enclosing env
* @param s the Symbol on which to enter the annotations
- * @param deferDecl enclosing declaration for DeferredLintHandler, or null for no deferral
*/
- public void annotateLater(List annotations, Env localEnv,
- Symbol s, JCTree deferDecl)
+ public void annotateLater(List annotations, Env localEnv, Symbol s)
{
if (annotations.isEmpty()) {
return;
@@ -256,8 +250,6 @@ public class Annotate {
// been handled, meaning that the set of annotations pending completion is now empty.
Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- Assert.check(deferDecl != null);
- deferredLintHandler.push(deferDecl);
try {
if (s.hasAnnotations() && annotations.nonEmpty())
log.error(annotations.head.pos, Errors.AlreadyAnnotated(Kinds.kindName(s), s));
@@ -268,7 +260,6 @@ public class Annotate {
// never called for a type parameter
annotateNow(s, annotations, localEnv, false, false);
} finally {
- deferredLintHandler.pop();
log.useSource(prev);
}
});
@@ -285,16 +276,13 @@ public class Annotate {
/** Queue processing of an attribute default value. */
- public void annotateDefaultValueLater(JCExpression defaultValue, Env localEnv,
- MethodSymbol m, JCTree deferDecl)
+ public void annotateDefaultValueLater(JCExpression defaultValue, Env localEnv, MethodSymbol m)
{
normal(() -> {
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- deferredLintHandler.push(deferDecl);
try {
enterDefaultValue(defaultValue, localEnv, m);
} finally {
- deferredLintHandler.pop();
log.useSource(prev);
}
});
@@ -682,7 +670,7 @@ public class Annotate {
// Scan the annotation element value and then attribute nested annotations if present
if (tree.type != null && tree.type.tsym != null) {
- queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym, null);
+ queueScanTreeAndTypeAnnotate(tree, env, tree.type.tsym);
}
result = cfolder.coerce(result, expectedElementType);
@@ -1034,20 +1022,14 @@ public class Annotate {
/**
* Attribute the list of annotations and enter them onto s.
*/
- public void enterTypeAnnotations(List annotations, Env env,
- Symbol s, JCTree deferDecl, boolean isTypeParam)
+ public void enterTypeAnnotations(List annotations, Env env, Symbol s, boolean isTypeParam)
{
Assert.checkNonNull(s, "Symbol argument to actualEnterTypeAnnotations is nul/");
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
- if (deferDecl != null) {
- deferredLintHandler.push(deferDecl);
- }
try {
annotateNow(s, annotations, env, true, isTypeParam);
} finally {
- if (deferDecl != null)
- deferredLintHandler.pop();
log.useSource(prev);
}
}
@@ -1055,10 +1037,10 @@ public class Annotate {
/**
* Enqueue tree for scanning of type annotations, attaching to the Symbol sym.
*/
- public void queueScanTreeAndTypeAnnotate(JCTree tree, Env env, Symbol sym, JCTree deferDecl)
+ public void queueScanTreeAndTypeAnnotate(JCTree tree, Env env, Symbol sym)
{
Assert.checkNonNull(sym);
- normal(() -> tree.accept(new TypeAnnotate(env, sym, deferDecl)));
+ normal(() -> tree.accept(new TypeAnnotate(env, sym)));
}
/**
@@ -1093,32 +1075,30 @@ public class Annotate {
private class TypeAnnotate extends TreeScanner {
private final Env env;
private final Symbol sym;
- private JCTree deferDecl;
- public TypeAnnotate(Env env, Symbol sym, JCTree deferDecl) {
+ public TypeAnnotate(Env env, Symbol sym) {
this.env = env;
this.sym = sym;
- this.deferDecl = deferDecl;
}
@Override
public void visitAnnotatedType(JCAnnotatedType tree) {
- enterTypeAnnotations(tree.annotations, env, sym, deferDecl, false);
+ enterTypeAnnotations(tree.annotations, env, sym, false);
scan(tree.underlyingType);
}
@Override
public void visitTypeParameter(JCTypeParameter tree) {
- enterTypeAnnotations(tree.annotations, env, sym, deferDecl, true);
+ enterTypeAnnotations(tree.annotations, env, sym, true);
scan(tree.bounds);
}
@Override
public void visitNewArray(JCNewArray tree) {
- enterTypeAnnotations(tree.annotations, env, sym, deferDecl, false);
+ enterTypeAnnotations(tree.annotations, env, sym, false);
for (List dimAnnos : tree.dimAnnotations)
- enterTypeAnnotations(dimAnnos, env, sym, deferDecl, false);
+ enterTypeAnnotations(dimAnnos, env, sym, false);
scan(tree.elemtype);
scan(tree.elems);
}
@@ -1137,19 +1117,13 @@ public class Annotate {
@Override
public void visitVarDef(JCVariableDecl tree) {
- JCTree prevDecl = deferDecl;
- deferDecl = tree;
- try {
- if (sym != null && sym.kind == VAR) {
- // Don't visit a parameter once when the sym is the method
- // and once when the sym is the parameter.
- scan(tree.mods);
- scan(tree.vartype);
- }
- scan(tree.init);
- } finally {
- deferDecl = prevDecl;
+ if (sym != null && sym.kind == VAR) {
+ // Don't visit a parameter once when the sym is the method
+ // and once when the sym is the parameter.
+ scan(tree.mods);
+ scan(tree.vartype);
}
+ scan(tree.init);
}
@Override
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index ea3b08e0338..45ece909ad7 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -41,6 +41,7 @@ import com.sun.source.tree.TreeVisitor;
import com.sun.source.util.SimpleTreeVisitor;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
@@ -98,6 +99,7 @@ public class Attr extends JCTree.Visitor {
final Names names;
final Log log;
+ final LintMapper lintMapper;
final Symtab syms;
final Resolve rs;
final Operators operators;
@@ -116,7 +118,6 @@ public class Attr extends JCTree.Visitor {
final Preview preview;
final JCDiagnostic.Factory diags;
final TypeAnnotations typeAnnotations;
- final DeferredLintHandler deferredLintHandler;
final TypeEnvs typeEnvs;
final Dependencies dependencies;
final Annotate annotate;
@@ -137,6 +138,7 @@ public class Attr extends JCTree.Visitor {
names = Names.instance(context);
log = Log.instance(context);
+ lintMapper = LintMapper.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
operators = Operators.instance(context);
@@ -156,7 +158,6 @@ public class Attr extends JCTree.Visitor {
diags = JCDiagnostic.Factory.instance(context);
annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
argumentAttr = ArgumentAttr.instance(context);
@@ -853,7 +854,6 @@ public class Attr extends JCTree.Visitor {
Env enclosingEnv,
JCVariableDecl variable,
Type type) {
- deferredLintHandler.push(variable);
final JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
try {
doQueueScanTreeAndTypeAnnotateForVarInit(variable, enclosingEnv);
@@ -869,7 +869,6 @@ public class Attr extends JCTree.Visitor {
}
} finally {
log.useSource(prevSource);
- deferredLintHandler.pop();
}
}
@@ -998,7 +997,6 @@ public class Attr extends JCTree.Visitor {
Assert.check(!env.info.ctorPrologue);
MethodSymbol prevMethod = chk.setMethod(m);
try {
- deferredLintHandler.flush(tree, lint);
chk.checkDeprecatedAnnotation(tree.pos(), m);
@@ -1233,7 +1231,7 @@ public class Attr extends JCTree.Visitor {
}
// Attribute all type annotations in the body
- annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m, null);
+ annotate.queueScanTreeAndTypeAnnotate(tree.body, localEnv, m);
annotate.flush();
// Start of constructor prologue (if not in java.lang.Object constructor)
@@ -1297,7 +1295,6 @@ public class Attr extends JCTree.Visitor {
try {
v.getConstValue(); // ensure compile-time constant initializer is evaluated
- deferredLintHandler.flush(tree, lint);
chk.checkDeprecatedAnnotation(tree.pos(), v);
if (tree.init != null) {
@@ -1342,7 +1339,7 @@ public class Attr extends JCTree.Visitor {
env.info.scope.owner.kind != MTH && env.info.scope.owner.kind != VAR) {
tree.mods.flags |= Flags.FIELD_INIT_TYPE_ANNOTATIONS_QUEUED;
// Field initializer expression need to be entered.
- annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym, tree);
+ annotate.queueScanTreeAndTypeAnnotate(tree.init, env, tree.sym);
annotate.flush();
}
}
@@ -1439,7 +1436,7 @@ public class Attr extends JCTree.Visitor {
if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
// Attribute all type annotations in the block
- annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
+ annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, localEnv.info.scope.owner);
annotate.flush();
attribStats(tree.stats, localEnv);
@@ -1952,7 +1949,7 @@ public class Attr extends JCTree.Visitor {
public void visitSynchronized(JCSynchronized tree) {
chk.checkRefType(tree.pos(), attribExpr(tree.lock, env));
if (tree.lock.type != null && tree.lock.type.isValueBased()) {
- env.info.lint.logIfEnabled(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
+ log.warning(tree.pos(), LintWarnings.AttemptToSynchronizeOnInstanceOfValueBasedClass);
}
attribStat(tree.body, env);
result = null;
@@ -2054,7 +2051,7 @@ public class Attr extends JCTree.Visitor {
if (close.kind == MTH &&
close.overrides(syms.autoCloseableClose, resource.tsym, types, true) &&
chk.isHandled(syms.interruptedExceptionType, types.memberType(resource, close).getThrownTypes())) {
- env.info.lint.logIfEnabled(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource));
+ log.warning(pos, LintWarnings.TryResourceThrowsInterruptedExc(resource));
}
}
}
@@ -4226,9 +4223,9 @@ public class Attr extends JCTree.Visitor {
setSyntheticVariableType(tree.var, type == Type.noType ? syms.errType
: type);
}
- annotate.annotateLater(tree.var.mods.annotations, env, v, tree.var);
+ annotate.annotateLater(tree.var.mods.annotations, env, v);
if (!tree.var.isImplicitlyTyped()) {
- annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v, tree.var);
+ annotate.queueScanTreeAndTypeAnnotate(tree.var.vartype, env, v);
}
annotate.flush();
result = tree.type;
@@ -4466,7 +4463,7 @@ public class Attr extends JCTree.Visitor {
sym.kind == MTH &&
sym.name.equals(names.close) &&
sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true)) {
- env.info.lint.logIfEnabled(tree, LintWarnings.TryExplicitCloseCall);
+ log.warning(tree, LintWarnings.TryExplicitCloseCall);
}
// Disallow selecting a type from an expression
@@ -4493,9 +4490,9 @@ public class Attr extends JCTree.Visitor {
// If the qualified item is not a type and the selected item is static, report
// a warning. Make allowance for the class of an array type e.g. Object[].class)
if (!sym.owner.isAnonymous()) {
- chk.lint.logIfEnabled(tree, LintWarnings.StaticNotQualifiedByType(sym.kind.kindName(), sym.owner));
+ log.warning(tree, LintWarnings.StaticNotQualifiedByType(sym.kind.kindName(), sym.owner));
} else {
- chk.lint.logIfEnabled(tree, LintWarnings.StaticNotQualifiedByType2(sym.kind.kindName()));
+ log.warning(tree, LintWarnings.StaticNotQualifiedByType2(sym.kind.kindName()));
}
}
@@ -5297,6 +5294,9 @@ public class Attr extends JCTree.Visitor {
}
annotate.flush();
+
+ // Now that this tree is attributed, we can calculate the Lint configuration everywhere within it
+ lintMapper.calculateLints(env.toplevel.sourcefile, env.tree, env.toplevel.endPositions);
}
public void attribPackage(DiagnosticPosition pos, PackageSymbol p) {
@@ -5339,7 +5339,6 @@ public class Attr extends JCTree.Visitor {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
- deferredLintHandler.flush(env.tree, lint);
attrib.accept(env);
} finally {
log.useSource(prev);
@@ -5523,7 +5522,6 @@ public class Attr extends JCTree.Visitor {
}
}
- deferredLintHandler.flush(env.tree, env.info.lint);
env.info.returnResult = null;
// java.lang.Enum may not be subclassed by a non-enum
if (st.tsym == syms.enumSym &&
@@ -5569,11 +5567,9 @@ public class Attr extends JCTree.Visitor {
ModuleSymbol msym = tree.sym;
Lint lint = env.outer.info.lint = env.outer.info.lint.augment(msym);
Lint prevLint = chk.setLint(lint);
- chk.checkModuleName(tree);
- chk.checkDeprecatedAnnotation(tree, msym);
-
try {
- deferredLintHandler.flush(tree, lint);
+ chk.checkModuleName(tree);
+ chk.checkDeprecatedAnnotation(tree, msym);
} finally {
chk.setLint(prevLint);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index ec328f391f9..3d9eff107da 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -121,7 +121,7 @@ public class Check {
// The set of lint options currently in effect. It is initialized
// from the context, and then is set/reset as needed by Attr as it
// visits all the various parts of the trees during attribution.
- Lint lint;
+ private Lint lint;
// The method being analyzed in Attr - it is set/reset as needed by
// Attr as it visits new method declarations.
@@ -164,8 +164,6 @@ public class Check {
profile = Profile.instance(context);
preview = Preview.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
-
allowModules = Feature.MODULES.allowedInSource(source);
allowRecords = Feature.RECORDS.allowedInSource(source);
allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);
@@ -180,10 +178,6 @@ public class Check {
*/
private Map,ClassSymbol> compiled = new HashMap<>();
- /** A handler for deferred lint warnings.
- */
- private DeferredLintHandler deferredLintHandler;
-
/** Are modules allowed
*/
private final boolean allowModules;
@@ -229,24 +223,15 @@ public class Check {
* @param sym The deprecated symbol.
*/
void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
- LintWarning warningKey = null;
- if (sym.isDeprecatedForRemoval()) {
- if (!lint.isSuppressed(LintCategory.REMOVAL)) {
- if (sym.kind == MDL) {
- warningKey = LintWarnings.HasBeenDeprecatedForRemovalModule(sym);
- } else {
- warningKey = LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location());
- }
- }
- } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
- if (sym.kind == MDL) {
- warningKey = LintWarnings.HasBeenDeprecatedModule(sym);
- } else {
- warningKey = LintWarnings.HasBeenDeprecated(sym, sym.location());
- }
- }
- if (warningKey != null)
- log.warning(pos, warningKey);
+ Assert.check(!importSuppression);
+ LintWarning warningKey = sym.isDeprecatedForRemoval() ?
+ (sym.kind == MDL ?
+ LintWarnings.HasBeenDeprecatedForRemovalModule(sym) :
+ LintWarnings.HasBeenDeprecatedForRemoval(sym, sym.location())) :
+ (sym.kind == MDL ?
+ LintWarnings.HasBeenDeprecatedModule(sym) :
+ LintWarnings.HasBeenDeprecated(sym, sym.location()));
+ log.warning(pos, warningKey);
}
/** Log a preview warning.
@@ -254,25 +239,16 @@ public class Check {
* @param msg A Warning describing the problem.
*/
public void warnPreviewAPI(DiagnosticPosition pos, LintWarning warnKey) {
- if (!importSuppression && !lint.isSuppressed(LintCategory.PREVIEW))
+ if (!importSuppression)
log.warning(pos, warnKey);
}
- /** Log a preview warning.
- * @param pos Position to be used for error reporting.
- * @param msg A Warning describing the problem.
- */
- public void warnRestrictedAPI(DiagnosticPosition pos, Symbol sym) {
- lint.logIfEnabled(pos, LintWarnings.RestrictedMethod(sym.enclClass(), sym));
- }
-
/** Warn about unchecked operation.
* @param pos Position to be used for error reporting.
* @param msg A string describing the problem.
*/
public void warnUnchecked(DiagnosticPosition pos, LintWarning warnKey) {
- if (!lint.isSuppressed(LintCategory.UNCHECKED))
- log.warning(pos, warnKey);
+ log.warning(pos, warnKey);
}
/** Report a failure to complete a class.
@@ -608,9 +584,7 @@ public class Check {
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
&& !is292targetTypeCast(tree)) {
- deferredLintHandler.report(_l -> {
- lint.logIfEnabled(tree.pos(), LintWarnings.RedundantCast(tree.clazz.type));
- });
+ log.warning(tree.pos(), LintWarnings.RedundantCast(tree.clazz.type));
}
}
//where
@@ -914,7 +888,7 @@ public class Check {
}
} else if (hasTrustMeAnno && varargElemType != null &&
types.isReifiable(varargElemType)) {
- lint.logIfEnabled(tree, LintWarnings.VarargsRedundantTrustmeAnno(
+ log.warning(tree.pos(), LintWarnings.VarargsRedundantTrustmeAnno(
syms.trustMeType.tsym,
diags.fragment(Fragments.VarargsTrustmeOnReifiableVarargs(varargElemType))));
}
@@ -1173,7 +1147,7 @@ public class Check {
mask = MethodFlags;
}
if ((flags & STRICTFP) != 0) {
- warnOnExplicitStrictfp(tree);
+ log.warning(tree.pos(), LintWarnings.Strictfp);
}
// Imply STRICTFP if owner has STRICTFP set.
if (((flags|implicit) & Flags.ABSTRACT) == 0 ||
@@ -1217,7 +1191,7 @@ public class Check {
implicit |= FINAL;
}
if ((flags & STRICTFP) != 0) {
- warnOnExplicitStrictfp(tree);
+ log.warning(tree.pos(), LintWarnings.Strictfp);
}
// Imply STRICTFP if owner has STRICTFP set.
implicit |= sym.owner.flags_field & STRICTFP;
@@ -1281,16 +1255,6 @@ public class Check {
return flags & (mask | ~ExtendedStandardFlags) | implicit;
}
- private void warnOnExplicitStrictfp(JCTree tree) {
- deferredLintHandler.push(tree);
- try {
- deferredLintHandler.report(_ -> lint.logIfEnabled(tree.pos(), LintWarnings.Strictfp));
- } finally {
- deferredLintHandler.pop();
- }
- }
-
-
/** Determine if this enum should be implicitly final.
*
* If the enum has no specialized enum constants, it is final.
@@ -1503,7 +1467,7 @@ public class Check {
!TreeInfo.isDiamond(tree) &&
!withinAnonConstr(env) &&
tree.type.isRaw()) {
- lint.logIfEnabled(tree.pos(), LintWarnings.RawClassUse(tree.type, tree.type.tsym.type));
+ log.warning(tree.pos(), LintWarnings.RawClassUse(tree.type, tree.type.tsym.type));
}
}
//where
@@ -1827,7 +1791,7 @@ public class Check {
// Optional warning if varargs don't agree
if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)) {
- lint.logIfEnabled(TreeInfo.diagnosticPositionFor(m, tree),
+ log.warning(TreeInfo.diagnosticPositionFor(m, tree),
((m.flags() & Flags.VARARGS) != 0)
? LintWarnings.OverrideVarargsMissing(varargsOverrides(m, other))
: LintWarnings.OverrideVarargsExtra(varargsOverrides(m, other)));
@@ -1841,12 +1805,7 @@ public class Check {
// Warn if a deprecated method overridden by a non-deprecated one.
if (!isDeprecatedOverrideIgnorable(other, origin)) {
- Lint prevLint = setLint(lint.augment(m));
- try {
- checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other);
- } finally {
- setLint(prevLint);
- }
+ checkDeprecated(() -> TreeInfo.diagnosticPositionFor(m, tree), m, other);
}
}
// where
@@ -2915,42 +2874,33 @@ public class Check {
// Apply special flag "-XDwarnOnAccessToMembers" which turns on just this particular warning for all types of access
void checkAccessFromSerializableElement(final JCTree tree, boolean isLambda) {
- final Lint prevLint = setLint(warnOnAnyAccessToMembers ? lint.enable(LintCategory.SERIAL) : lint);
- try {
- if (warnOnAnyAccessToMembers || isLambda)
- checkAccessFromSerializableElementInner(tree, isLambda);
- } finally {
- setLint(prevLint);
- }
+ if (warnOnAnyAccessToMembers || isLambda)
+ checkAccessFromSerializableElementInner(tree, isLambda);
}
private void checkAccessFromSerializableElementInner(final JCTree tree, boolean isLambda) {
- if (lint.isEnabled(LintCategory.SERIAL)) {
- Symbol sym = TreeInfo.symbol(tree);
- if (!sym.kind.matches(KindSelector.VAL_MTH)) {
+ Symbol sym = TreeInfo.symbol(tree);
+ if (!sym.kind.matches(KindSelector.VAL_MTH)) {
+ return;
+ }
+
+ if (sym.kind == VAR) {
+ if ((sym.flags() & PARAMETER) != 0 ||
+ sym.isDirectlyOrIndirectlyLocal() ||
+ sym.name == names._this ||
+ sym.name == names._super) {
return;
}
+ }
- if (sym.kind == VAR) {
- if ((sym.flags() & PARAMETER) != 0 ||
- sym.isDirectlyOrIndirectlyLocal() ||
- sym.name == names._this ||
- sym.name == names._super) {
- return;
- }
- }
-
- if (!types.isSubtype(sym.owner.type, syms.serializableType) &&
- isEffectivelyNonPublic(sym)) {
- if (isLambda) {
- if (belongsToRestrictedPackage(sym)) {
- log.warning(tree.pos(),
- LintWarnings.AccessToMemberFromSerializableLambda(sym));
- }
- } else {
- log.warning(tree.pos(),
- LintWarnings.AccessToMemberFromSerializableElement(sym));
+ if (!types.isSubtype(sym.owner.type, syms.serializableType) && isEffectivelyNonPublic(sym)) {
+ DiagnosticFlag flag = warnOnAnyAccessToMembers ? DiagnosticFlag.DEFAULT_ENABLED : null;
+ if (isLambda) {
+ if (belongsToRestrictedPackage(sym)) {
+ log.warning(flag, tree.pos(), LintWarnings.AccessToMemberFromSerializableLambda(sym));
}
+ } else {
+ log.warning(flag, tree.pos(), LintWarnings.AccessToMemberFromSerializableElement(sym));
}
}
}
@@ -3737,8 +3687,7 @@ public class Check {
// Note: @Deprecated has no effect on local variables, parameters and package decls.
if (lint.isEnabled(LintCategory.DEPRECATION) && !s.isDeprecatableViaAnnotation()) {
if (!syms.deprecatedType.isErroneous() && s.attribute(syms.deprecatedType.tsym) != null) {
- log.warning(pos,
- LintWarnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s)));
+ log.warning(pos, LintWarnings.DeprecatedAnnotationHasNoEffect(Kinds.kindName(s)));
}
}
}
@@ -3752,15 +3701,13 @@ public class Check {
&& (s.isDeprecatedForRemoval() || s.isDeprecated() && !other.isDeprecated())
&& (s.outermostClass() != other.outermostClass() || s.outermostClass() == null)
&& s.kind != Kind.PCK) {
- deferredLintHandler.report(_l -> warnDeprecated(pos.get(), s));
+ warnDeprecated(pos.get(), s);
}
}
void checkSunAPI(final DiagnosticPosition pos, final Symbol s) {
if ((s.flags() & PROPRIETARY) != 0) {
- deferredLintHandler.report(_l -> {
- log.warning(pos, Warnings.SunProprietary(s));
- });
+ log.warning(pos, Warnings.SunProprietary(s));
}
}
@@ -3817,7 +3764,7 @@ public class Check {
void checkRestricted(DiagnosticPosition pos, Symbol s) {
if (s.kind == MTH && (s.flags() & RESTRICTED) != 0) {
- deferredLintHandler.report(_l -> warnRestrictedAPI(pos, s));
+ log.warning(pos, LintWarnings.RestrictedMethod(s.enclClass(), s));
}
}
@@ -4089,7 +4036,7 @@ public class Check {
int opc = ((OperatorSymbol)operator).opcode;
if (opc == ByteCodes.idiv || opc == ByteCodes.imod
|| opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
- deferredLintHandler.report(_ -> lint.logIfEnabled(pos, LintWarnings.DivZero));
+ log.warning(pos, LintWarnings.DivZero);
}
}
}
@@ -4102,8 +4049,7 @@ public class Check {
*/
void checkLossOfPrecision(final DiagnosticPosition pos, Type found, Type req) {
if (found.isNumeric() && req.isNumeric() && !types.isAssignable(found, req)) {
- deferredLintHandler.report(_ ->
- lint.logIfEnabled(pos, LintWarnings.PossibleLossOfPrecision(found, req)));
+ log.warning(pos, LintWarnings.PossibleLossOfPrecision(found, req));
}
}
@@ -4112,7 +4058,7 @@ public class Check {
*/
void checkEmptyIf(JCIf tree) {
if (tree.thenpart.hasTag(SKIP) && tree.elsepart == null) {
- lint.logIfEnabled(tree.thenpart.pos(), LintWarnings.EmptyIf);
+ log.warning(tree.thenpart.pos(), LintWarnings.EmptyIf);
}
}
@@ -4259,8 +4205,7 @@ public class Check {
rs.isAccessible(env, c) &&
!fileManager.isSameFile(c.sourcefile, env.toplevel.sourcefile))
{
- lint.logIfEnabled(pos,
- LintWarnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile));
+ log.warning(pos, LintWarnings.AuxiliaryClassAccessedFromOutsideOfItsSourceFile(c, c.sourcefile));
}
}
@@ -4302,8 +4247,7 @@ public class Check {
// Warning may be suppressed by
// annotations; check again for being
// enabled in the deferred context.
- deferredLintHandler.report(_ ->
- lint.logIfEnabled(pos, LintWarnings.MissingExplicitCtor(c, pkg, modle)));
+ log.warning(pos, LintWarnings.MissingExplicitCtor(c, pkg, modle));
} else {
return;
}
@@ -4339,7 +4283,7 @@ public class Check {
method.attribute(syms.trustMeType.tsym) != null &&
isTrustMeAllowedOnMethod(method) &&
!types.isReifiable(method.type.getParameterTypes().last())) {
- Check.this.lint.logIfEnabled(pos(), LintWarnings.VarargsUnsafeUseVarargsParam(method.params.last()));
+ log.warning(pos(), LintWarnings.VarargsUnsafeUseVarargsParam(method.params.last()));
}
break;
default:
@@ -4637,28 +4581,24 @@ public class Check {
void checkModuleExists(final DiagnosticPosition pos, ModuleSymbol msym) {
if (msym.kind != MDL) {
- deferredLintHandler.report(_ ->
- lint.logIfEnabled(pos, LintWarnings.ModuleNotFound(msym)));
+ log.warning(pos, LintWarnings.ModuleNotFound(msym));
}
}
void checkPackageExistsForOpens(final DiagnosticPosition pos, PackageSymbol packge) {
if (packge.members().isEmpty() &&
((packge.flags() & Flags.HAS_RESOURCE) == 0)) {
- deferredLintHandler.report(_ ->
- lint.logIfEnabled(pos, LintWarnings.PackageEmptyOrNotFound(packge)));
+ log.warning(pos, LintWarnings.PackageEmptyOrNotFound(packge));
}
}
void checkModuleRequires(final DiagnosticPosition pos, final RequiresDirective rd) {
if ((rd.module.flags() & Flags.AUTOMATIC_MODULE) != 0) {
- deferredLintHandler.report(_ -> {
- if (rd.isTransitive() && lint.isEnabled(LintCategory.REQUIRES_TRANSITIVE_AUTOMATIC)) {
- log.warning(pos, LintWarnings.RequiresTransitiveAutomatic);
- } else {
- lint.logIfEnabled(pos, LintWarnings.RequiresAutomatic);
- }
- });
+ if (rd.isTransitive()) { // see comment in Log.applyLint() for special logic that applies
+ log.warning(pos, LintWarnings.RequiresTransitiveAutomatic);
+ } else {
+ log.warning(pos, LintWarnings.RequiresAutomatic);
+ }
}
}
@@ -5693,14 +5633,14 @@ public class Check {
VarSymbol lastParam = ms.params.head;
for (VarSymbol param: ms.params) {
if ((param.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
- lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
+ log.warning(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
}
lastParam = param;
argExps = argExps.tail;
}
while (argExps != null && !argExps.isEmpty() && lastParam != null) {
if ((lastParam.flags_field & REQUIRES_IDENTITY) != 0 && argExps.head.type.isValueBased()) {
- lint.logIfEnabled(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
+ log.warning(argExps.head.pos(), LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
}
argExps = argExps.tail;
}
@@ -5727,7 +5667,7 @@ public class Check {
// we need to avoid recursion due to self referencing type vars or captures, this is why we need a set
requiresIdentityVisitor.visit(t, new HashSet<>());
if (requiresIdentityVisitor.requiresWarning) {
- lint.logIfEnabled(pos, LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
+ log.warning(pos, LintWarnings.AttemptToUseValueBasedWhereIdentityExpected);
return true;
}
}
@@ -5804,7 +5744,7 @@ public class Check {
.filter(ta -> isRequiresIdentityAnnotation(ta.type.tsym) &&
typeParamTrees.get(ta.position.parameter_index).type != null &&
typeParamTrees.get(ta.position.parameter_index).type.isValueBased())
- .forEach(ta -> lint.logIfEnabled(typeParamTrees.get(ta.position.parameter_index).pos(),
+ .forEach(ta -> log.warning(typeParamTrees.get(ta.position.parameter_index).pos(),
CompilerProperties.LintWarnings.AttemptToUseValueBasedWhereIdentityExpected));
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
index e685f139b68..3bbd007c66a 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
@@ -214,7 +214,6 @@ public class Flow {
private final Resolve rs;
private final JCDiagnostic.Factory diags;
private Env attrEnv;
- private Lint lint;
private final Infer infer;
public static Flow instance(Context context) {
@@ -337,7 +336,6 @@ public class Flow {
syms = Symtab.instance(context);
types = Types.instance(context);
chk = Check.instance(context);
- lint = Lint.instance(context);
infer = Infer.instance(context);
rs = Resolve.instance(context);
diags = JCDiagnostic.Factory.instance(context);
@@ -562,10 +560,8 @@ public class Flow {
if (tree.sym == null) return;
Liveness alivePrev = alive;
ListBuffer pendingExitsPrev = pendingExits;
- Lint lintPrev = lint;
pendingExits = new ListBuffer<>();
- lint = lint.augment(tree.sym);
try {
// process all the nested classes
@@ -596,30 +592,22 @@ public class Flow {
} finally {
pendingExits = pendingExitsPrev;
alive = alivePrev;
- lint = lintPrev;
}
}
public void visitMethodDef(JCMethodDecl tree) {
if (tree.body == null) return;
- Lint lintPrev = lint;
-
- lint = lint.augment(tree.sym);
Assert.check(pendingExits.isEmpty());
- try {
- alive = Liveness.ALIVE;
- scanStat(tree.body);
- tree.completesNormally = alive != Liveness.DEAD;
+ alive = Liveness.ALIVE;
+ scanStat(tree.body);
+ tree.completesNormally = alive != Liveness.DEAD;
- if (alive == Liveness.ALIVE && !tree.sym.type.getReturnType().hasTag(VOID))
- log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
+ if (alive == Liveness.ALIVE && !tree.sym.type.getReturnType().hasTag(VOID))
+ log.error(TreeInfo.diagEndPos(tree.body), Errors.MissingRetStmt);
- clearPendingExits(true);
- } finally {
- lint = lintPrev;
- }
+ clearPendingExits(true);
}
private void clearPendingExits(boolean inMethod) {
@@ -634,15 +622,7 @@ public class Flow {
}
public void visitVarDef(JCVariableDecl tree) {
- if (tree.init != null) {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try{
- scan(tree.init);
- } finally {
- lint = lintPrev;
- }
- }
+ scan(tree.init);
}
public void visitBlock(JCBlock tree) {
@@ -724,8 +704,7 @@ public class Flow {
// Warn about fall-through if lint switch fallthrough enabled.
if (alive == Liveness.ALIVE &&
c.stats.nonEmpty() && l.tail.nonEmpty())
- lint.logIfEnabled(l.tail.head.pos(),
- LintWarnings.PossibleFallThroughIntoCase);
+ log.warning(l.tail.head.pos(), LintWarnings.PossibleFallThroughIntoCase);
}
tree.isExhaustive = tree.hasUnconditionalPattern ||
TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases);
@@ -1232,7 +1211,7 @@ public class Flow {
scanStat(tree.finalizer);
tree.finallyCanCompleteNormally = alive != Liveness.DEAD;
if (alive == Liveness.DEAD) {
- lint.logIfEnabled(TreeInfo.diagEndPos(tree.finalizer),
+ log.warning(TreeInfo.diagEndPos(tree.finalizer),
LintWarnings.FinallyCannotComplete);
} else {
while (exits.nonEmpty()) {
@@ -1453,7 +1432,6 @@ public class Flow {
List thrownPrev = thrown;
List caughtPrev = caught;
ListBuffer pendingExitsPrev = pendingExits;
- Lint lintPrev = lint;
boolean anonymousClass = tree.name == names.empty;
pendingExits = new ListBuffer<>();
if (!anonymousClass) {
@@ -1461,7 +1439,6 @@ public class Flow {
}
classDef = tree;
thrown = List.nil();
- lint = lint.augment(tree.sym);
try {
// process all the nested classes
@@ -1510,7 +1487,6 @@ public class Flow {
pendingExits = pendingExitsPrev;
caught = caughtPrev;
classDef = classDefPrev;
- lint = lintPrev;
}
}
@@ -1519,9 +1495,6 @@ public class Flow {
List caughtPrev = caught;
List mthrown = tree.sym.type.getThrownTypes();
- Lint lintPrev = lint;
-
- lint = lint.augment(tree.sym);
Assert.check(pendingExits.isEmpty());
@@ -1554,20 +1527,11 @@ public class Flow {
}
} finally {
caught = caughtPrev;
- lint = lintPrev;
}
}
public void visitVarDef(JCVariableDecl tree) {
- if (tree.init != null) {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try{
- scan(tree.init);
- } finally {
- lint = lintPrev;
- }
- }
+ scan(tree.init);
}
public void visitBlock(JCBlock tree) {
@@ -2387,82 +2351,76 @@ public class Flow {
return;
}
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
+ JCClassDecl classDefPrev = classDef;
+ int firstadrPrev = firstadr;
+ int nextadrPrev = nextadr;
+ ListBuffer pendingExitsPrev = pendingExits;
+
+ pendingExits = new ListBuffer<>();
+ if (tree.name != names.empty) {
+ firstadr = nextadr;
+ }
+ classDef = tree;
try {
- JCClassDecl classDefPrev = classDef;
- int firstadrPrev = firstadr;
- int nextadrPrev = nextadr;
- ListBuffer pendingExitsPrev = pendingExits;
-
- pendingExits = new ListBuffer<>();
- if (tree.name != names.empty) {
- firstadr = nextadr;
+ // define all the static fields
+ for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(VARDEF)) {
+ JCVariableDecl def = (JCVariableDecl)l.head;
+ if ((def.mods.flags & STATIC) != 0) {
+ VarSymbol sym = def.sym;
+ if (trackable(sym)) {
+ newVar(def);
+ }
+ }
+ }
}
- classDef = tree;
- try {
- // define all the static fields
- for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(VARDEF)) {
- JCVariableDecl def = (JCVariableDecl)l.head;
- if ((def.mods.flags & STATIC) != 0) {
- VarSymbol sym = def.sym;
- if (trackable(sym)) {
- newVar(def);
- }
+
+ // process all the static initializers
+ forEachInitializer(tree, true, def -> {
+ scan(def);
+ clearPendingExits(false);
+ });
+
+ // verify all static final fields got initialized
+ for (int i = firstadr; i < nextadr; i++) {
+ JCVariableDecl vardecl = vardecls[i];
+ VarSymbol var = vardecl.sym;
+ if (var.owner == classDef.sym && var.isStatic()) {
+ checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
+ }
+ }
+
+ // define all the instance fields
+ for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(VARDEF)) {
+ JCVariableDecl def = (JCVariableDecl)l.head;
+ if ((def.mods.flags & STATIC) == 0) {
+ VarSymbol sym = def.sym;
+ if (trackable(sym)) {
+ newVar(def);
}
}
}
+ }
- // process all the static initializers
- forEachInitializer(tree, true, def -> {
- scan(def);
- clearPendingExits(false);
- });
-
- // verify all static final fields got initialized
- for (int i = firstadr; i < nextadr; i++) {
- JCVariableDecl vardecl = vardecls[i];
- VarSymbol var = vardecl.sym;
- if (var.owner == classDef.sym && var.isStatic()) {
- checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
- }
+ // process all the methods
+ for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(METHODDEF)) {
+ scan(l.head);
}
+ }
- // define all the instance fields
- for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(VARDEF)) {
- JCVariableDecl def = (JCVariableDecl)l.head;
- if ((def.mods.flags & STATIC) == 0) {
- VarSymbol sym = def.sym;
- if (trackable(sym)) {
- newVar(def);
- }
- }
- }
+ // process all the nested classes
+ for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(CLASSDEF)) {
+ scan(l.head);
}
-
- // process all the methods
- for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(METHODDEF)) {
- scan(l.head);
- }
- }
-
- // process all the nested classes
- for (List l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(CLASSDEF)) {
- scan(l.head);
- }
- }
- } finally {
- pendingExits = pendingExitsPrev;
- nextadr = nextadrPrev;
- firstadr = firstadrPrev;
- classDef = classDefPrev;
}
} finally {
- lint = lintPrev;
+ pendingExits = pendingExitsPrev;
+ nextadr = nextadrPrev;
+ firstadr = firstadrPrev;
+ classDef = classDefPrev;
}
}
@@ -2477,87 +2435,81 @@ public class Flow {
return;
}
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
+ final Bits initsPrev = new Bits(inits);
+ final Bits uninitsPrev = new Bits(uninits);
+ int nextadrPrev = nextadr;
+ int firstadrPrev = firstadr;
+ int returnadrPrev = returnadr;
+
+ Assert.check(pendingExits.isEmpty());
+ boolean isConstructorPrev = isConstructor;
try {
- final Bits initsPrev = new Bits(inits);
- final Bits uninitsPrev = new Bits(uninits);
- int nextadrPrev = nextadr;
- int firstadrPrev = firstadr;
- int returnadrPrev = returnadr;
+ isConstructor = TreeInfo.isConstructor(tree);
- Assert.check(pendingExits.isEmpty());
- boolean isConstructorPrev = isConstructor;
- try {
- isConstructor = TreeInfo.isConstructor(tree);
+ // We only track field initialization inside constructors
+ if (!isConstructor) {
+ firstadr = nextadr;
+ }
- // We only track field initialization inside constructors
- if (!isConstructor) {
- firstadr = nextadr;
- }
+ // Mark all method parameters as DA
+ for (List l = tree.params; l.nonEmpty(); l = l.tail) {
+ JCVariableDecl def = l.head;
+ scan(def);
+ Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
+ /* If we are executing the code from Gen, then there can be
+ * synthetic or mandated variables, ignore them.
+ */
+ initParam(def);
+ }
+ // else we are in an instance initializer block;
+ // leave caught unchanged.
+ scan(tree.body);
- // Mark all method parameters as DA
- for (List l = tree.params; l.nonEmpty(); l = l.tail) {
- JCVariableDecl def = l.head;
- scan(def);
- Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
- /* If we are executing the code from Gen, then there can be
- * synthetic or mandated variables, ignore them.
- */
- initParam(def);
- }
- // else we are in an instance initializer block;
- // leave caught unchanged.
- scan(tree.body);
-
- boolean isCompactOrGeneratedRecordConstructor = (tree.sym.flags() & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
- (tree.sym.flags() & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD);
- if (isConstructor) {
- boolean isSynthesized = (tree.sym.flags() &
- GENERATEDCONSTR) != 0;
- for (int i = firstadr; i < nextadr; i++) {
- JCVariableDecl vardecl = vardecls[i];
- VarSymbol var = vardecl.sym;
- if (var.owner == classDef.sym && !var.isStatic()) {
- // choose the diagnostic position based on whether
- // the ctor is default(synthesized) or not
- if (isSynthesized && !isCompactOrGeneratedRecordConstructor) {
- checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
- var, Errors.VarNotInitializedInDefaultConstructor(var));
- } else if (isCompactOrGeneratedRecordConstructor) {
- boolean isInstanceRecordField = var.enclClass().isRecord() &&
- (var.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0 &&
- var.owner.kind == TYP;
- if (isInstanceRecordField) {
- boolean notInitialized = !inits.isMember(var.adr);
- if (notInitialized && uninits.isMember(var.adr) && tree.completesNormally) {
- /* this way we indicate Lower that it should generate an initialization for this field
- * in the compact constructor
- */
- var.flags_field |= UNINITIALIZED_FIELD;
- } else {
- checkInit(TreeInfo.diagEndPos(tree.body), var);
- }
+ boolean isCompactOrGeneratedRecordConstructor = (tree.sym.flags() & Flags.COMPACT_RECORD_CONSTRUCTOR) != 0 ||
+ (tree.sym.flags() & (GENERATEDCONSTR | RECORD)) == (GENERATEDCONSTR | RECORD);
+ if (isConstructor) {
+ boolean isSynthesized = (tree.sym.flags() &
+ GENERATEDCONSTR) != 0;
+ for (int i = firstadr; i < nextadr; i++) {
+ JCVariableDecl vardecl = vardecls[i];
+ VarSymbol var = vardecl.sym;
+ if (var.owner == classDef.sym && !var.isStatic()) {
+ // choose the diagnostic position based on whether
+ // the ctor is default(synthesized) or not
+ if (isSynthesized && !isCompactOrGeneratedRecordConstructor) {
+ checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
+ var, Errors.VarNotInitializedInDefaultConstructor(var));
+ } else if (isCompactOrGeneratedRecordConstructor) {
+ boolean isInstanceRecordField = var.enclClass().isRecord() &&
+ (var.flags_field & (Flags.PRIVATE | Flags.FINAL | Flags.GENERATED_MEMBER | Flags.RECORD)) != 0 &&
+ var.owner.kind == TYP;
+ if (isInstanceRecordField) {
+ boolean notInitialized = !inits.isMember(var.adr);
+ if (notInitialized && uninits.isMember(var.adr) && tree.completesNormally) {
+ /* this way we indicate Lower that it should generate an initialization for this field
+ * in the compact constructor
+ */
+ var.flags_field |= UNINITIALIZED_FIELD;
} else {
- checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
+ checkInit(TreeInfo.diagEndPos(tree.body), var);
}
} else {
- checkInit(TreeInfo.diagEndPos(tree.body), var);
+ checkInit(TreeInfo.diagnosticPositionFor(var, vardecl), var);
}
+ } else {
+ checkInit(TreeInfo.diagEndPos(tree.body), var);
}
}
}
- clearPendingExits(true);
- } finally {
- inits.assign(initsPrev);
- uninits.assign(uninitsPrev);
- nextadr = nextadrPrev;
- firstadr = firstadrPrev;
- returnadr = returnadrPrev;
- isConstructor = isConstructorPrev;
}
+ clearPendingExits(true);
} finally {
- lint = lintPrev;
+ inits.assign(initsPrev);
+ uninits.assign(uninitsPrev);
+ nextadr = nextadrPrev;
+ firstadr = firstadrPrev;
+ returnadr = returnadrPrev;
+ isConstructor = isConstructorPrev;
}
}
@@ -2585,21 +2537,15 @@ public class Flow {
}
public void visitVarDef(JCVariableDecl tree) {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try{
- boolean track = trackable(tree.sym);
- if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
- newVar(tree);
+ boolean track = trackable(tree.sym);
+ if (track && (tree.sym.owner.kind == MTH || tree.sym.owner.kind == VAR)) {
+ newVar(tree);
+ }
+ if (tree.init != null) {
+ scanExpr(tree.init);
+ if (track) {
+ letInit(tree.pos(), tree.sym);
}
- if (tree.init != null) {
- scanExpr(tree.init);
- if (track) {
- letInit(tree.pos(), tree.sym);
- }
- }
- } finally {
- lint = lintPrev;
}
}
@@ -2851,8 +2797,7 @@ public class Flow {
final Bits uninitsEnd = new Bits(uninits);
int nextadrCatch = nextadr;
- if (!resourceVarDecls.isEmpty() &&
- lint.isEnabled(Lint.LintCategory.TRY)) {
+ if (!resourceVarDecls.isEmpty()) {
for (JCVariableDecl resVar : resourceVarDecls) {
if (unrefdResources.includes(resVar.sym) && !resVar.sym.isUnnamedVariable()) {
log.warning(resVar.pos(),
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
index b726cc7a61d..d63ba1677d6 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
@@ -66,7 +66,6 @@ public class MemberEnter extends JCTree.Visitor {
private final Annotate annotate;
private final Types types;
private final Names names;
- private final DeferredLintHandler deferredLintHandler;
public static MemberEnter instance(Context context) {
MemberEnter instance = context.get(memberEnterKey);
@@ -87,7 +86,6 @@ public class MemberEnter extends JCTree.Visitor {
types = Types.instance(context);
source = Source.instance(context);
names = Names.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
}
/** Construct method type from method signature.
@@ -194,16 +192,11 @@ public class MemberEnter extends JCTree.Visitor {
}
Env localEnv = methodEnv(tree, env);
- deferredLintHandler.push(tree);
- try {
- // Compute the method type
- m.type = signature(m, tree.typarams, tree.params,
- tree.restype, tree.recvparam,
- tree.thrown,
- localEnv);
- } finally {
- deferredLintHandler.pop();
- }
+ // Compute the method type
+ m.type = signature(m, tree.typarams, tree.params,
+ tree.restype, tree.recvparam,
+ tree.thrown,
+ localEnv);
if (types.isSignaturePolymorphic(m)) {
m.flags_field |= SIGNATURE_POLYMORPHIC;
@@ -227,14 +220,14 @@ public class MemberEnter extends JCTree.Visitor {
enclScope.enter(m);
}
- annotate.annotateLater(tree.mods.annotations, localEnv, m, tree);
+ annotate.annotateLater(tree.mods.annotations, localEnv, m);
// Visit the signature of the method. Note that
// TypeAnnotate doesn't descend into the body.
- annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, m, tree);
+ annotate.queueScanTreeAndTypeAnnotate(tree, localEnv, m);
if (tree.defaultValue != null) {
m.defaultValue = annotate.unfinishedDefaultValue(); // set it to temporary sentinel for now
- annotate.annotateDefaultValueLater(tree.defaultValue, localEnv, m, tree);
+ annotate.annotateDefaultValueLater(tree.defaultValue, localEnv, m);
}
}
@@ -263,18 +256,13 @@ public class MemberEnter extends JCTree.Visitor {
localEnv = env.dup(tree, env.info.dup());
localEnv.info.staticLevel++;
}
- deferredLintHandler.push(tree);
- try {
- if (TreeInfo.isEnumInit(tree)) {
- attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
- } else if (!tree.isImplicitlyTyped()) {
- attr.attribType(tree.vartype, localEnv);
- if (TreeInfo.isReceiverParam(tree))
- checkReceiver(tree, localEnv);
- }
- } finally {
- deferredLintHandler.pop();
+ if (TreeInfo.isEnumInit(tree)) {
+ attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
+ } else if (!tree.isImplicitlyTyped()) {
+ attr.attribType(tree.vartype, localEnv);
+ if (TreeInfo.isReceiverParam(tree))
+ checkReceiver(tree, localEnv);
}
if ((tree.mods.flags & VARARGS) != 0) {
@@ -315,9 +303,9 @@ public class MemberEnter extends JCTree.Visitor {
}
}
- annotate.annotateLater(tree.mods.annotations, localEnv, v, tree);
+ annotate.annotateLater(tree.mods.annotations, localEnv, v);
if (!tree.isImplicitlyTyped()) {
- annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v, tree);
+ annotate.queueScanTreeAndTypeAnnotate(tree.vartype, localEnv, v);
}
v.pos = tree.pos;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
index 4d0af014d83..0cef9cc6602 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
@@ -52,7 +52,6 @@ import javax.tools.JavaFileObject.Kind;
import javax.tools.StandardLocation;
import com.sun.source.tree.ModuleTree.ModuleKind;
-import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.Directive;
import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.ExportsFlag;
@@ -141,7 +140,6 @@ public class Modules extends JCTree.Visitor {
private final Attr attr;
private final Check chk;
private final Preview preview;
- private final DeferredLintHandler deferredLintHandler;
private final TypeEnvs typeEnvs;
private final Types types;
private final JavaFileManager fileManager;
@@ -169,8 +167,6 @@ public class Modules extends JCTree.Visitor {
private final String moduleVersionOpt;
private final boolean sourceLauncher;
- private final boolean lintOptions;
-
private Set rootModules = null;
private final Set warnedMissing = new HashSet<>();
@@ -193,7 +189,6 @@ public class Modules extends JCTree.Visitor {
attr = Attr.instance(context);
chk = Check.instance(context);
preview = Preview.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
typeEnvs = TypeEnvs.instance(context);
moduleFinder = ModuleFinder.instance(context);
types = Types.instance(context);
@@ -205,8 +200,6 @@ public class Modules extends JCTree.Visitor {
allowAccessIntoSystem = options.isUnset(Option.RELEASE);
- lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
-
multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
ClassWriter classWriter = ClassWriter.instance(context);
classWriter.multiModuleMode = multiModuleMode;
@@ -746,7 +739,6 @@ public class Modules extends JCTree.Visitor {
ModuleVisitor v = new ModuleVisitor();
JavaFileObject prev = log.useSource(tree.sourcefile);
JCModuleDecl moduleDecl = tree.getModuleDecl();
- deferredLintHandler.push(moduleDecl);
try {
moduleDecl.accept(v);
@@ -754,7 +746,6 @@ public class Modules extends JCTree.Visitor {
checkCyclicDependencies(moduleDecl);
} finally {
log.useSource(prev);
- deferredLintHandler.pop();
msym.flags_field &= ~UNATTRIBUTED;
}
}
@@ -991,13 +982,11 @@ public class Modules extends JCTree.Visitor {
UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
JCModuleDecl decl = env.toplevel.getModuleDecl();
- deferredLintHandler.push(decl);
try {
decl.accept(v);
} finally {
log.useSource(prev);
- deferredLintHandler.pop();
}
};
}
@@ -1263,12 +1252,9 @@ public class Modules extends JCTree.Visitor {
}
observable = computeTransitiveClosure(limitMods, rootModules, null);
observable.addAll(rootModules);
- if (lintOptions) {
- for (ModuleSymbol msym : limitMods) {
- if (!observable.contains(msym)) {
- log.warning(
- LintWarnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym));
- }
+ for (ModuleSymbol msym : limitMods) {
+ if (!observable.contains(msym)) {
+ log.warning(LintWarnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym));
}
}
}
@@ -1721,10 +1707,7 @@ public class Modules extends JCTree.Visitor {
}
if (!unknownModules.contains(msym)) {
- if (lintOptions) {
- log.warning(
- LintWarnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym));
- }
+ log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym));
unknownModules.add(msym);
}
return false;
@@ -1760,9 +1743,7 @@ public class Modules extends JCTree.Visitor {
ModuleSymbol msym = syms.enterModule(names.fromString(sourceName));
if (!allModules.contains(msym)) {
- if (lintOptions) {
- log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, msym));
- }
+ log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, msym));
continue;
}
@@ -1780,9 +1761,7 @@ public class Modules extends JCTree.Visitor {
continue;
targetModule = syms.enterModule(names.fromString(targetName));
if (!allModules.contains(targetModule)) {
- if (lintOptions) {
- log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule));
- }
+ log.warning(LintWarnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule));
continue;
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java
index 9119278660f..6fb1feed08d 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ThisEscapeAnalyzer.java
@@ -45,6 +45,7 @@ import java.util.stream.Stream;
import com.sun.tools.javac.code.Directive;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
@@ -57,6 +58,7 @@ import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Log;
@@ -67,6 +69,7 @@ import static com.sun.tools.javac.code.Kinds.Kind.*;
import static com.sun.tools.javac.code.Lint.LintCategory.THIS_ESCAPE;
import static com.sun.tools.javac.code.TypeTag.*;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
+import static com.sun.tools.javac.util.Position.NOPOS;
/**
* Looks for possible 'this' escapes and generates corresponding warnings.
@@ -156,7 +159,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
private final Types types;
private final Resolve rs;
private final Log log;
- private Lint lint;
+ private final LintMapper lintMapper;
// These fields are scoped to the entire compilation unit
@@ -168,10 +171,6 @@ public class ThisEscapeAnalyzer extends TreeScanner {
*/
private final Map methodMap = new LinkedHashMap<>();
- /** Contains symbols of fields and constructors that have warnings suppressed.
- */
- private final Set suppressed = new HashSet<>();
-
/** Contains classes whose outer instance (if any) is non-public.
*/
private final Set nonPublicOuters = new HashSet<>();
@@ -231,7 +230,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
syms = Symtab.instance(context);
types = Types.instance(context);
rs = Resolve.instance(context);
- lint = Lint.instance(context);
+ lintMapper = LintMapper.instance(context);
}
//
@@ -262,8 +261,8 @@ public class ThisEscapeAnalyzer extends TreeScanner {
Assert.check(checkInvariants(false, false));
Assert.check(methodMap.isEmpty()); // we are not prepared to be used more than once
- // Short circuit if warnings are totally disabled
- if (!lint.isEnabled(THIS_ESCAPE))
+ // Short circuit if this calculation is unnecessary
+ if (!lintMapper.lintAt(env.toplevel.sourcefile, env.tree.pos()).get().isEnabled(THIS_ESCAPE))
return;
// Determine which packages are exported by the containing module, if any.
@@ -278,11 +277,9 @@ public class ThisEscapeAnalyzer extends TreeScanner {
// Build a mapping from symbols of methods to their declarations.
// Classify all ctors and methods as analyzable and/or invokable.
- // Track which constructors and fields have warnings suppressed.
// Record classes whose outer instance (if any) is non-public.
new TreeScanner() {
- private Lint lint = ThisEscapeAnalyzer.this.lint;
private JCClassDecl currentClass;
private boolean nonPublicOuter;
@@ -290,8 +287,6 @@ public class ThisEscapeAnalyzer extends TreeScanner {
public void visitClassDef(JCClassDecl tree) {
JCClassDecl currentClassPrev = currentClass;
boolean nonPublicOuterPrev = nonPublicOuter;
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
try {
currentClass = tree;
@@ -306,57 +301,29 @@ public class ThisEscapeAnalyzer extends TreeScanner {
} finally {
currentClass = currentClassPrev;
nonPublicOuter = nonPublicOuterPrev;
- lint = lintPrev;
- }
- }
-
- @Override
- public void visitVarDef(JCVariableDecl tree) {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try {
-
- // Track warning suppression of fields
- if (tree.sym.owner.kind == TYP && !lint.isEnabled(THIS_ESCAPE))
- suppressed.add(tree.sym);
-
- // Recurse
- super.visitVarDef(tree);
- } finally {
- lint = lintPrev;
}
}
@Override
public void visitMethodDef(JCMethodDecl tree) {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try {
- // Track warning suppression of constructors
- if (TreeInfo.isConstructor(tree) && !lint.isEnabled(THIS_ESCAPE))
- suppressed.add(tree.sym);
+ // Gather some useful info
+ boolean constructor = TreeInfo.isConstructor(tree);
+ boolean extendableClass = currentClassIsExternallyExtendable();
+ boolean nonPrivate = (tree.sym.flags() & (Flags.PUBLIC | Flags.PROTECTED)) != 0;
+ boolean finalish = (tree.mods.flags & (Flags.STATIC | Flags.PRIVATE | Flags.FINAL)) != 0;
- // Gather some useful info
- boolean constructor = TreeInfo.isConstructor(tree);
- boolean extendableClass = currentClassIsExternallyExtendable();
- boolean nonPrivate = (tree.sym.flags() & (Flags.PUBLIC | Flags.PROTECTED)) != 0;
- boolean finalish = (tree.mods.flags & (Flags.STATIC | Flags.PRIVATE | Flags.FINAL)) != 0;
+ // Determine if this is a constructor we should analyze
+ boolean analyzable = extendableClass && constructor && nonPrivate;
- // Determine if this is a constructor we should analyze
- boolean analyzable = extendableClass && constructor && nonPrivate;
+ // Determine if it's safe to "invoke" the method in an analysis (i.e., it can't be overridden)
+ boolean invokable = !extendableClass || constructor || finalish;
- // Determine if it's safe to "invoke" the method in an analysis (i.e., it can't be overridden)
- boolean invokable = !extendableClass || constructor || finalish;
+ // Add this method or constructor to our map
+ methodMap.put(tree.sym, new MethodInfo(currentClass, tree, constructor, analyzable, invokable));
- // Add this method or constructor to our map
- methodMap.put(tree.sym, new MethodInfo(currentClass, tree, constructor, analyzable, invokable));
-
- // Recurse
- super.visitMethodDef(tree);
- } finally {
- lint = lintPrev;
- }
+ // Recurse
+ super.visitMethodDef(tree);
}
// Determines if the current class could be extended in some other package/module
@@ -401,7 +368,7 @@ public class ThisEscapeAnalyzer extends TreeScanner {
for (Warning warning : warningList) {
LintWarning key = LintWarnings.PossibleThisEscape;
for (StackFrame frame : warning.stack) {
- log.warning(frame.site.pos(), key);
+ log.warning(frame.warningPos(), key);
key = LintWarnings.PossibleThisEscapeLocation;
}
}
@@ -1746,9 +1713,16 @@ public class ThisEscapeAnalyzer extends TreeScanner {
this.suppressible = initializer != null || (method.constructor && method.declaringClass == targetClass);
}
+ DiagnosticPosition warningPos() {
+ return site.pos().withLintPosition(NOPOS); // disable normal Lint suppression
+ }
+
+ Lint lint() {
+ return lintMapper.lintAt(topLevelEnv.toplevel.sourcefile, site.pos()).get();
+ }
+
boolean isSuppressed() {
- return suppressible &&
- suppressed.contains(initializer instanceof JCVariableDecl v ? v.sym : method.declaration.sym);
+ return suppressible && !lint().isEnabled(THIS_ESCAPE);
}
int comparePos(StackFrame that) {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
index eb4ab96dfd2..8648b929a04 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
@@ -34,7 +34,6 @@ import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Directive.ExportsDirective;
import com.sun.tools.javac.code.Directive.RequiresDirective;
-import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Scope.ImportFilter;
import com.sun.tools.javac.code.Scope.NamedImportScope;
import com.sun.tools.javac.code.Scope.StarImportScope;
@@ -108,8 +107,6 @@ public class TypeEnter implements Completer {
private final Annotate annotate;
private final TypeAnnotations typeAnnotations;
private final Types types;
- private final DeferredLintHandler deferredLintHandler;
- private final Lint lint;
private final TypeEnvs typeEnvs;
private final Dependencies dependencies;
@@ -135,8 +132,6 @@ public class TypeEnter implements Completer {
annotate = Annotate.instance(context);
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context);
- deferredLintHandler = DeferredLintHandler.instance(context);
- lint = Lint.instance(context);
typeEnvs = TypeEnvs.instance(context);
dependencies = Dependencies.instance(context);
Source source = Source.instance(context);
@@ -274,7 +269,6 @@ public class TypeEnter implements Completer {
queue.add(env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
- deferredLintHandler.push(tree);
try {
dependencies.push(env.enclClass.sym, phaseName);
runPhase(env);
@@ -282,7 +276,6 @@ public class TypeEnter implements Completer {
chk.completionError(tree.pos(), ex);
} finally {
dependencies.pop();
- deferredLintHandler.pop();
log.useSource(prev);
}
}
@@ -351,8 +344,6 @@ public class TypeEnter implements Completer {
ImportFilter prevStaticImportFilter = staticImportFilter;
ImportFilter prevTypeImportFilter = typeImportFilter;
- deferredLintHandler.pushImmediate(lint);
- Lint prevLint = chk.setLint(lint);
Env prevEnv = this.env;
try {
this.env = env;
@@ -376,20 +367,13 @@ public class TypeEnter implements Completer {
handleImports(tree.getImports());
if (decl != null) {
- deferredLintHandler.push(decl);
- try {
- //check @Deprecated:
- markDeprecated(decl.sym, decl.mods.annotations, env);
- } finally {
- deferredLintHandler.pop();
- }
+ //check for @Deprecated annotations
+ markDeprecated(decl.sym, decl.mods.annotations, env);
// process module annotations
- annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle, decl);
+ annotate.annotateLater(decl.mods.annotations, env, env.toplevel.modle);
}
} finally {
this.env = prevEnv;
- chk.setLint(prevLint);
- deferredLintHandler.pop();
this.staticImportFilter = prevStaticImportFilter;
this.typeImportFilter = prevTypeImportFilter;
}
@@ -422,7 +406,7 @@ public class TypeEnter implements Completer {
}
}
// process package annotations
- annotate.annotateLater(tree.annotations, env, env.toplevel.packge, tree);
+ annotate.annotateLater(tree.annotations, env, env.toplevel.packge);
}
private void doImport(JCImport tree, boolean fromModuleImport) {
@@ -914,9 +898,9 @@ public class TypeEnter implements Completer {
Env baseEnv = baseEnv(tree, env);
if (tree.extending != null)
- annotate.queueScanTreeAndTypeAnnotate(tree.extending, baseEnv, sym, tree);
+ annotate.queueScanTreeAndTypeAnnotate(tree.extending, baseEnv, sym);
for (JCExpression impl : tree.implementing)
- annotate.queueScanTreeAndTypeAnnotate(impl, baseEnv, sym, tree);
+ annotate.queueScanTreeAndTypeAnnotate(impl, baseEnv, sym);
annotate.flush();
attribSuperTypes(env, baseEnv);
@@ -931,11 +915,11 @@ public class TypeEnter implements Completer {
chk.checkNotRepeated(iface.pos(), types.erasure(it), interfaceSet);
}
- annotate.annotateLater(tree.mods.annotations, baseEnv, sym, tree);
+ annotate.annotateLater(tree.mods.annotations, baseEnv, sym);
attr.attribTypeVariables(tree.typarams, baseEnv, false);
for (JCTypeParameter tp : tree.typarams)
- annotate.queueScanTreeAndTypeAnnotate(tp, baseEnv, sym, tree);
+ annotate.queueScanTreeAndTypeAnnotate(tp, baseEnv, sym);
// check that no package exists with same fully qualified name,
// but admit classes in the unnamed package which have the same
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
index 73f86239713..5964c16c151 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
@@ -92,7 +92,7 @@ public abstract class BaseFileManager implements JavaFileManager {
options = Options.instance(context);
// Initialize locations
- locations.update(log, lint, FSInfo.instance(context));
+ locations.update(log, FSInfo.instance(context));
// Apply options
options.whenReady(this::applyOptions);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
index ff02de705fb..c4573b9a364 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java
@@ -77,12 +77,11 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardJavaFileManager.PathFactory;
import javax.tools.StandardLocation;
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
import jdk.internal.jmod.JmodFile;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
import com.sun.tools.javac.util.DefinedBy;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.ListBuffer;
@@ -123,11 +122,6 @@ public class Locations {
*/
private FSInfo fsInfo;
- /**
- * The root {@link Lint} instance.
- */
- private Lint lint;
-
private ModuleNameReader moduleNameReader;
private PathFactory pathFactory = Paths::get;
@@ -168,9 +162,8 @@ public class Locations {
}
}
- void update(Log log, Lint lint, FSInfo fsInfo) {
+ void update(Log log, FSInfo fsInfo) {
this.log = log;
- this.lint = lint;
this.fsInfo = fsInfo;
}
@@ -221,7 +214,7 @@ public class Locations {
try {
entries.add(getPath(s));
} catch (IllegalArgumentException e) {
- lint.logIfEnabled(LintWarnings.InvalidPath(s));
+ log.warning(LintWarnings.InvalidPath(s));
}
}
}
@@ -316,7 +309,7 @@ public class Locations {
private void addDirectory(Path dir, boolean warn) {
if (!Files.isDirectory(dir)) {
if (warn) {
- lint.logIfEnabled(LintWarnings.DirPathElementNotFound(dir));
+ log.warning(LintWarnings.DirPathElementNotFound(dir));
}
return;
}
@@ -361,7 +354,7 @@ public class Locations {
if (!fsInfo.exists(file)) {
/* No such file or directory exists */
if (warn) {
- lint.logIfEnabled(LintWarnings.PathElementNotFound(file));
+ log.warning(LintWarnings.PathElementNotFound(file));
}
super.add(file);
return;
@@ -383,12 +376,12 @@ public class Locations {
try {
FileSystems.newFileSystem(file, (ClassLoader)null).close();
if (warn) {
- lint.logIfEnabled(LintWarnings.UnexpectedArchiveFile(file));
+ log.warning(LintWarnings.UnexpectedArchiveFile(file));
}
} catch (IOException | ProviderNotFoundException e) {
// FIXME: include e.getLocalizedMessage in warning
if (warn) {
- lint.logIfEnabled(LintWarnings.InvalidArchiveFile(file));
+ log.warning(LintWarnings.InvalidArchiveFile(file));
}
return;
}
@@ -1651,7 +1644,7 @@ public class Locations {
void add(Map> map, Path prefix, Path suffix) {
if (!Files.isDirectory(prefix)) {
- lint.logIfEnabled(Files.exists(prefix) ?
+ log.warning(Files.exists(prefix) ?
LintWarnings.DirPathElementNotDirectory(prefix) :
LintWarnings.DirPathElementNotFound(prefix));
return;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
index cf751ff6b30..6f1ad28586d 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
@@ -51,7 +51,6 @@ import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.Annotate.AnnotationTypeCompleter;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Directive.*;
-import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Symtab;
@@ -139,9 +138,6 @@ public class ClassReader {
/** The symbol table. */
Symtab syms;
- /** The root Lint config. */
- Lint lint;
-
Types types;
/** The name table. */
@@ -303,8 +299,6 @@ public class ClassReader {
typevars = WriteableScope.create(syms.noSymbol);
- lint = Lint.instance(context);
-
initAttributeReaders();
}
@@ -854,8 +848,7 @@ public class ClassReader {
if (!warnedAttrs.contains(name)) {
JavaFileObject prev = log.useSource(currentClassFile);
try {
- lint.logIfEnabled(
- LintWarnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
+ log.warning(LintWarnings.FutureAttr(name, version.major, version.minor, majorVersion, minorVersion));
} finally {
log.useSource(prev);
}
@@ -1609,7 +1602,7 @@ public class ClassReader {
} else if (parameterAnnotations.length != numParameters) {
//the RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations
//provide annotations for a different number of parameters, ignore:
- lint.logIfEnabled(LintWarnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
+ log.warning(LintWarnings.RuntimeVisibleInvisibleParamAnnotationsMismatch(currentClassFile));
for (int pnum = 0; pnum < numParameters; pnum++) {
readAnnotations();
}
@@ -2075,9 +2068,9 @@ public class ClassReader {
JavaFileObject prevSource = log.useSource(requestingOwner.classfile);
try {
if (failure == null) {
- lint.logIfEnabled(LintWarnings.AnnotationMethodNotFound(container, name));
+ log.warning(LintWarnings.AnnotationMethodNotFound(container, name));
} else {
- lint.logIfEnabled(LintWarnings.AnnotationMethodNotFoundReason(container,
+ log.warning(LintWarnings.AnnotationMethodNotFoundReason(container,
name,
failure.getDetailValue()));//diagnostic, if present
}
@@ -2954,7 +2947,7 @@ public class ClassReader {
private void dropParameterAnnotations() {
parameterAnnotations = null;
- lint.logIfEnabled(LintWarnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
+ log.warning(LintWarnings.RuntimeInvisibleParameterAnnotations(currentClassFile));
}
/**
* Creates the parameter at the position {@code mpIndex} in the parameter list of the owning method.
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
index 7aa1cc473b5..58beee78af2 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
@@ -52,7 +52,6 @@ import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.doclint.DocLint;
-import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.JavacFileManager;
@@ -503,12 +502,9 @@ public class Arguments {
}
} else {
// single-module or legacy mode
- boolean lintPaths = !options.isLintDisabled(LintCategory.PATH);
- if (lintPaths) {
- Path outDirParent = outDir.getParent();
- if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
- log.warning(LintWarnings.OutdirIsInExplodedModule(outDir));
- }
+ Path outDirParent = outDir.getParent();
+ if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
+ log.warning(LintWarnings.OutdirIsInExplodedModule(outDir));
}
}
}
@@ -576,15 +572,14 @@ public class Arguments {
reportDiag(Errors.SourcepathModulesourcepathConflict);
}
- boolean lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
- if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
+ if (source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
if (fm instanceof BaseFileManager baseFileManager) {
if (source.compareTo(Source.JDK8) <= 0) {
- if (baseFileManager.isDefaultBootClassPath())
+ if (baseFileManager.isDefaultBootClassPath()) {
log.warning(LintWarnings.SourceNoBootclasspath(source.name, releaseNote(source, targetString)));
- } else {
- if (baseFileManager.isDefaultSystemModulesPath())
- log.warning(LintWarnings.SourceNoSystemModulesPath(source.name, releaseNote(source, targetString)));
+ }
+ } else if (baseFileManager.isDefaultSystemModulesPath()) {
+ log.warning(LintWarnings.SourceNoSystemModulesPath(source.name, releaseNote(source, targetString)));
}
}
}
@@ -593,14 +588,14 @@ public class Arguments {
if (source.compareTo(Source.MIN) < 0) {
log.error(Errors.OptionRemovedSource(source.name, Source.MIN.name));
- } else if (source == Source.MIN && lintOptions) {
+ } else if (source == Source.MIN) {
log.warning(LintWarnings.OptionObsoleteSource(source.name));
obsoleteOptionFound = true;
}
if (target.compareTo(Target.MIN) < 0) {
log.error(Errors.OptionRemovedTarget(target, Target.MIN));
- } else if (target == Target.MIN && lintOptions) {
+ } else if (target == Target.MIN) {
log.warning(LintWarnings.OptionObsoleteTarget(target));
obsoleteOptionFound = true;
}
@@ -634,7 +629,7 @@ public class Arguments {
log.error(Errors.ProcessorpathNoProcessormodulepath);
}
- if (obsoleteOptionFound && lintOptions) {
+ if (obsoleteOptionFound) {
log.warning(LintWarnings.OptionObsoleteSuppression);
}
@@ -645,7 +640,7 @@ public class Arguments {
validateLimitModules(sv);
validateDefaultModuleForCreatedFiles(sv);
- if (lintOptions && options.isSet(Option.ADD_OPENS)) {
+ if (options.isSet(Option.ADD_OPENS)) {
log.warning(LintWarnings.AddopensIgnored);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
index 83106ff2278..ee11304dce9 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java
@@ -258,6 +258,10 @@ public class JavaCompiler {
*/
protected JNIWriter jniWriter;
+ /** The Lint mapper.
+ */
+ protected LintMapper lintMapper;
+
/** The module for the symbol table entry phases.
*/
protected Enter enter;
@@ -384,6 +388,7 @@ public class JavaCompiler {
names = Names.instance(context);
log = Log.instance(context);
+ lintMapper = LintMapper.instance(context);
diagFactory = JCDiagnostic.Factory.instance(context);
finder = ClassFinder.instance(context);
reader = ClassReader.instance(context);
@@ -575,6 +580,7 @@ public class JavaCompiler {
/** The number of errors reported so far.
*/
public int errorCount() {
+ log.reportOutstandingWarnings();
if (werror && log.nerrors == 0 && log.nwarnings > 0) {
log.error(Errors.WarningsAndWerror);
}
@@ -625,6 +631,7 @@ public class JavaCompiler {
private JCCompilationUnit parse(JavaFileObject filename, CharSequence content, boolean silent) {
long msec = now();
JCCompilationUnit tree = make.TopLevel(List.nil());
+ lintMapper.startParsingFile(filename);
if (content != null) {
if (verbose) {
log.printVerbose("parsing.started", filename);
@@ -644,6 +651,7 @@ public class JavaCompiler {
}
tree.sourcefile = filename;
+ lintMapper.finishParsingFile(tree);
if (content != null && !taskListener.isEmpty() && !silent) {
TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree);
@@ -1843,6 +1851,7 @@ public class JavaCompiler {
else
log.warning(Warnings.ProcUseProcOrImplicit);
}
+ log.reportOutstandingWarnings();
log.reportOutstandingNotes();
if (log.compressedOutput) {
log.note(Notes.CompressedDiags);
@@ -1916,6 +1925,7 @@ public class JavaCompiler {
attr = null;
chk = null;
gen = null;
+ lintMapper = null;
flow = null;
transTypes = null;
lower = null;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
index f3d0837398c..f40cb0fb6b7 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java
@@ -25,8 +25,6 @@
package com.sun.tools.javac.parser;
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Source.Feature;
@@ -83,7 +81,7 @@ public class JavaTokenizer extends UnicodeReader {
/**
* The log to be used for error reporting. Copied from scanner factory.
*/
- private final Log log;
+ protected final Log log;
/**
* The token factory. Copied from scanner factory.
@@ -135,13 +133,6 @@ public class JavaTokenizer extends UnicodeReader {
*/
protected boolean hasEscapeSequences;
- /**
- * The set of lint options currently in effect. It is initialized
- * from the context, and then is set/reset as needed by Attr as it
- * visits all the various parts of the trees during attribution.
- */
- protected final Lint lint;
-
/**
* Construct a Java token scanner from the input character buffer.
*
@@ -168,7 +159,6 @@ public class JavaTokenizer extends UnicodeReader {
this.source = fac.source;
this.preview = fac.preview;
this.enableLineDocComments = fac.enableLineDocComments;
- this.lint = fac.lint;
this.sb = new StringBuilder(256);
}
@@ -205,17 +195,6 @@ public class JavaTokenizer extends UnicodeReader {
errPos = pos;
}
- /**
- * Report a warning at the given position using the provided arguments.
- *
- * @param pos position in input buffer.
- * @param key error key to report.
- */
- protected void lexWarning(int pos, JCDiagnostic.LintWarning key) {
- DiagnosticPosition dp = new SimpleDiagnosticPosition(pos) ;
- log.warning(dp, key);
- }
-
/**
* Add a character to the literal buffer.
*
@@ -1060,17 +1039,12 @@ public class JavaTokenizer extends UnicodeReader {
// If a text block.
if (isTextBlock) {
// Verify that the incidental indentation is consistent.
- if (lint.isEnabled(LintCategory.TEXT_BLOCKS)) {
- Set checks =
- TextBlockSupport.checkWhitespace(string);
- if (checks.contains(TextBlockSupport.WhitespaceChecks.INCONSISTENT)) {
- lexWarning(pos,
- LintWarnings.InconsistentWhiteSpaceIndentation);
- }
- if (checks.contains(TextBlockSupport.WhitespaceChecks.TRAILING)) {
- lexWarning(pos,
- LintWarnings.TrailingWhiteSpaceWillBeRemoved);
- }
+ Set checks = TextBlockSupport.checkWhitespace(string);
+ if (checks.contains(TextBlockSupport.WhitespaceChecks.INCONSISTENT)) {
+ log.warning(pos, LintWarnings.InconsistentWhiteSpaceIndentation);
+ }
+ if (checks.contains(TextBlockSupport.WhitespaceChecks.TRAILING)) {
+ log.warning(pos, LintWarnings.TrailingWhiteSpaceWillBeRemoved);
}
// Remove incidental indentation.
try {
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
index b63374d9c6d..4a990701315 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
@@ -116,8 +116,6 @@ public class JavacParser implements Parser {
/** A map associating "other nearby documentation comments"
* with the preferred documentation comment for a declaration. */
protected Map> danglingComments = new HashMap<>();
- /** Handler for deferred diagnostics. */
- protected final DeferredLintHandler deferredLintHandler;
// Because of javac's limited lookahead, some contexts are ambiguous in
// the presence of type annotations even though they are not ambiguous
@@ -190,7 +188,6 @@ public class JavacParser implements Parser {
this.names = fac.names;
this.source = fac.source;
this.preview = fac.preview;
- this.deferredLintHandler = fac.deferredLintHandler;
this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
this.keepDocComments = keepDocComments;
this.parseModuleInfo = parseModuleInfo;
@@ -216,7 +213,6 @@ public class JavacParser implements Parser {
this.names = parser.names;
this.source = parser.source;
this.preview = parser.preview;
- this.deferredLintHandler = parser.deferredLintHandler;
this.allowStringFolding = parser.allowStringFolding;
this.keepDocComments = parser.keepDocComments;
this.parseModuleInfo = false;
@@ -591,8 +587,7 @@ public class JavacParser implements Parser {
* 4. When the tree node for the declaration is finally
* available, and the primary comment, if any,
* is "attached", (in {@link #attach}) any related
- * dangling comments are also attached to the tree node
- * by registering them using the {@link #deferredLintHandler}.
+ * dangling comments are reported to the log as warnings.
* 5. (Later) Warnings may be generated for the dangling
* comments, subject to the {@code -Xlint} and
* {@code @SuppressWarnings}.
@@ -653,32 +648,22 @@ public class JavacParser implements Parser {
void reportDanglingComments(JCTree tree, Comment dc) {
var list = danglingComments.remove(dc);
if (list != null) {
- deferredLintHandler.push(tree);
- try {
- list.forEach(this::reportDanglingDocComment);
- } finally {
- deferredLintHandler.pop();
- }
+ list.forEach(c -> reportDanglingDocComment(tree, c));
}
}
/**
- * Reports an individual dangling comment using the {@link #deferredLintHandler}.
+ * Reports an individual dangling comment as a warning to the log.
* The comment may or not may generate an actual diagnostic, depending on
* the settings for {@code -Xlint} and/or {@code @SuppressWarnings}.
*
* @param c the comment
*/
- void reportDanglingDocComment(Comment c) {
+ void reportDanglingDocComment(JCTree tree, Comment c) {
var pos = c.getPos();
- if (pos != null) {
- deferredLintHandler.report(lint -> {
- if (lint.isEnabled(Lint.LintCategory.DANGLING_DOC_COMMENTS) &&
- !shebang(c, pos)) {
- log.warning(
- pos, LintWarnings.DanglingDocComment);
- }
- });
+ if (pos != null && !shebang(c, pos)) {
+ pos = pos.withLintPosition(tree.getStartPosition());
+ S.lintWarning(pos, LintWarnings.DanglingDocComment);
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Lexer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Lexer.java
index bff4e027db7..1d1e08194f7 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Lexer.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Lexer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, 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
@@ -28,6 +28,8 @@ package com.sun.tools.javac.parser;
import java.util.Queue;
import com.sun.tools.javac.parser.Tokens.*;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.Position.LineMap;
/**
@@ -103,4 +105,12 @@ public interface Lexer {
* token.
*/
Queue getDocComments();
+
+ /**
+ * Report a warning that is subject to possible suppression by {@code @SuppressWarnings}.
+ *
+ * @param pos the lexical position at which the warning occurs
+ * @param key the warning to report
+ */
+ void lintWarning(DiagnosticPosition pos, LintWarning key);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java
index c873c6f31b7..f9e187315ba 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ParserFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2025, 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
@@ -28,7 +28,6 @@ package com.sun.tools.javac.parser;
import java.util.Locale;
import com.sun.tools.javac.api.JavacTrees;
-import com.sun.tools.javac.code.DeferredLintHandler;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
@@ -70,7 +69,6 @@ public class ParserFactory {
final Options options;
final ScannerFactory scannerFactory;
final Locale locale;
- final DeferredLintHandler deferredLintHandler;
private final JavacTrees trees;
@@ -88,7 +86,6 @@ public class ParserFactory {
this.options = Options.instance(context);
this.scannerFactory = ScannerFactory.instance(context);
this.locale = context.get(Locale.class);
- this.deferredLintHandler = DeferredLintHandler.instance(context);
this.trees = JavacTrees.instance(context);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Scanner.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Scanner.java
index a24e73a4141..7fcb87eac7a 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Scanner.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Scanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2025, 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
@@ -31,6 +31,8 @@ import java.util.List;
import java.util.ArrayList;
import java.util.Queue;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.Position.LineMap;
import static com.sun.tools.javac.parser.Tokens.*;
@@ -150,6 +152,11 @@ public class Scanner implements Lexer {
return docComments;
}
+ @Override
+ public void lintWarning(DiagnosticPosition pos, LintWarning key) {
+ tokenizer.log.warning(pos, key);
+ }
+
public int errPos() {
return tokenizer.errPos();
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ScannerFactory.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ScannerFactory.java
index 188fe838b18..66f2b66fabf 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ScannerFactory.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/ScannerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2025, 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
@@ -27,7 +27,6 @@ package com.sun.tools.javac.parser;
import java.nio.CharBuffer;
-import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Preview;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
@@ -62,7 +61,6 @@ public class ScannerFactory {
final Source source;
final Preview preview;
final Tokens tokens;
- final Lint lint;
final boolean enableLineDocComments;
/** Create a new scanner factory. */
@@ -74,7 +72,6 @@ public class ScannerFactory {
this.source = Source.instance(context);
this.preview = Preview.instance(context);
this.tokens = Tokens.instance(context);
- this.lint = Lint.instance(context);
var options = Options.instance(context);
this.enableLineDocComments = !options.isSet(Option.DISABLE_LINE_DOC_COMMENTS);
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java
index ec3a373ab4e..2a819152eed 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/VirtualParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, 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
@@ -30,6 +30,7 @@ import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCErroneous;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.Error;
+import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Position.LineMap;
@@ -167,10 +168,9 @@ public class VirtualParser extends JavacParser {
return S.getLineMap();
}
- public void commit() {
- for (int i = 0 ; i < offset ; i++) {
- S.nextToken(); // advance underlying lexer until position matches
- }
+ @Override
+ public void lintWarning(DiagnosticPosition pos, LintWarning key) {
+ // ignore
}
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java
index 012ac628ecd..dc25de30b36 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java
@@ -51,7 +51,6 @@ import javax.tools.JavaFileManager.Location;
import static javax.tools.StandardLocation.SOURCE_OUTPUT;
import static javax.tools.StandardLocation.CLASS_OUTPUT;
-import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
import com.sun.tools.javac.code.Symtab;
@@ -62,7 +61,6 @@ import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
-import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.main.Option;
@@ -338,7 +336,6 @@ public class JavacFiler implements Filer, Closeable {
JavaFileManager fileManager;
JavacElements elementUtils;
Log log;
- Lint lint;
Modules modules;
Names names;
Symtab syms;
@@ -421,8 +418,6 @@ public class JavacFiler implements Filer, Closeable {
aggregateGeneratedClassNames = new LinkedHashSet<>();
initialClassNames = new LinkedHashSet<>();
- lint = Lint.instance(context);
-
Options options = Options.instance(context);
defaultTargetModule = options.get(Option.DEFAULT_MODULE_FOR_CREATED_FILES);
@@ -486,14 +481,12 @@ public class JavacFiler implements Filer, Closeable {
private JavaFileObject createSourceOrClassFile(ModuleSymbol mod, boolean isSourceFile, String name, Element... originatingElements) throws IOException {
Assert.checkNonNull(mod);
- if (lint.isEnabled(PROCESSING)) {
- int periodIndex = name.lastIndexOf(".");
- if (periodIndex != -1) {
- String base = name.substring(periodIndex);
- String extn = (isSourceFile ? ".java" : ".class");
- if (base.equals(extn))
- log.warning(LintWarnings.ProcSuspiciousClassName(name, extn));
- }
+ int periodIndex = name.lastIndexOf(".");
+ if (periodIndex != -1) {
+ String base = name.substring(periodIndex);
+ String extn = (isSourceFile ? ".java" : ".class");
+ if (base.equals(extn))
+ log.warning(LintWarnings.ProcSuspiciousClassName(name, extn));
}
checkNameAndExistence(mod, name, isSourceFile);
Location loc = (isSourceFile ? SOURCE_OUTPUT : CLASS_OUTPUT);
@@ -707,7 +700,7 @@ public class JavacFiler implements Filer, Closeable {
private void checkName(String name, boolean allowUnnamedPackageInfo) throws FilerException {
if (!SourceVersion.isName(name) && !isPackageInfo(name, allowUnnamedPackageInfo)) {
- lint.logIfEnabled(LintWarnings.ProcIllegalFileName(name));
+ log.warning(LintWarnings.ProcIllegalFileName(name));
throw new FilerException("Illegal name " + name);
}
}
@@ -735,11 +728,11 @@ public class JavacFiler implements Filer, Closeable {
initialClassNames.contains(typename) ||
containedInInitialInputs(typename);
if (alreadySeen) {
- lint.logIfEnabled(LintWarnings.ProcTypeRecreate(typename));
+ log.warning(LintWarnings.ProcTypeRecreate(typename));
throw new FilerException("Attempt to recreate a file for type " + typename);
}
if (existing != null) {
- lint.logIfEnabled(LintWarnings.ProcTypeAlreadyExists(typename));
+ log.warning(LintWarnings.ProcTypeAlreadyExists(typename));
}
if (!mod.isUnnamed() && !typename.contains(".")) {
throw new FilerException("Attempt to create a type in unnamed package of a named module: " + typename);
@@ -768,7 +761,7 @@ public class JavacFiler implements Filer, Closeable {
*/
private void checkFileReopening(FileObject fileObject, boolean forWriting) throws FilerException {
if (isInFileObjectHistory(fileObject, forWriting)) {
- lint.logIfEnabled(LintWarnings.ProcFileReopening(fileObject.getName()));
+ log.warning(LintWarnings.ProcFileReopening(fileObject.getName()));
throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
}
if (forWriting)
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
index 7bc538a1d1e..b28f19bd3af 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
@@ -123,7 +123,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private final Modules modules;
private final Types types;
private final Annotate annotate;
- private final Lint lint;
/**
* Holds relevant state history of which processors have been
@@ -206,7 +205,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
printProcessorInfo = options.isSet(Option.XPRINTPROCESSORINFO);
printRounds = options.isSet(Option.XPRINTROUNDS);
verbose = options.isSet(Option.VERBOSE);
- lint = Lint.instance(context);
compiler = JavaCompiler.instance(context);
if (options.isSet(Option.PROC, "only") || options.isSet(Option.XPRINT)) {
compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
@@ -626,7 +624,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
private Set supportedOptionNames;
ProcessorState(Processor p, Log log, Source source, DeferredCompletionFailureHandler dcfh,
- boolean allowModules, ProcessingEnvironment env, Lint lint) {
+ boolean allowModules, ProcessingEnvironment env) {
processor = p;
contributed = false;
@@ -647,10 +645,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
boolean patternAdded = supportedAnnotationStrings.add(annotationPattern);
supportedAnnotationPatterns.
- add(importStringToPattern(allowModules, annotationPattern,
- processor, log, lint));
+ add(importStringToPattern(allowModules, annotationPattern, processor, log));
if (!patternAdded) {
- lint.logIfEnabled(LintWarnings.ProcDuplicateSupportedAnnotation(annotationPattern,
+ log.warning(LintWarnings.ProcDuplicateSupportedAnnotation(annotationPattern,
p.getClass().getName()));
}
}
@@ -663,7 +660,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
// and "foo.bar.*".
if (supportedAnnotationPatterns.contains(MatchingUtils.validImportStringToPattern("*")) &&
supportedAnnotationPatterns.size() > 1) {
- lint.logIfEnabled(LintWarnings.ProcRedundantTypesWithWildcard(p.getClass().getName()));
+ log.warning(LintWarnings.ProcRedundantTypesWithWildcard(p.getClass().getName()));
}
supportedOptionNames = new LinkedHashSet<>();
@@ -671,8 +668,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (checkOptionName(optionName, log)) {
boolean optionAdded = supportedOptionNames.add(optionName);
if (!optionAdded) {
- lint.logIfEnabled(LintWarnings.ProcDuplicateOptionName(optionName,
- p.getClass().getName()));
+ log.warning(LintWarnings.ProcDuplicateOptionName(optionName, p.getClass().getName()));
}
}
}
@@ -759,8 +755,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
log, source, dcfh,
Feature.MODULES.allowedInSource(source),
- JavacProcessingEnvironment.this,
- lint);
+ JavacProcessingEnvironment.this);
psi.procStateList.add(ps);
return ps;
} else
@@ -888,7 +883,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
unmatchedAnnotations.remove("");
- if (lint.isEnabled(PROCESSING) && unmatchedAnnotations.size() > 0) {
+ if (unmatchedAnnotations.size() > 0) {
// Remove annotations processed by javac
unmatchedAnnotations.keySet().removeAll(platformAnnotations);
if (unmatchedAnnotations.size() > 0) {
@@ -1649,7 +1644,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
* regex matching that string. If the string is not a valid
* import-style string, return a regex that won't match anything.
*/
- private static Pattern importStringToPattern(boolean allowModules, String s, Processor p, Log log, Lint lint) {
+ private static Pattern importStringToPattern(boolean allowModules, String s, Processor p, Log log) {
String module;
String pkg;
int slash = s.indexOf('/');
@@ -1662,7 +1657,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
} else {
String moduleName = s.substring(0, slash);
if (!SourceVersion.isName(moduleName)) {
- return warnAndNoMatches(s, p, log, lint);
+ return warnAndNoMatches(s, p, log);
}
module = Pattern.quote(moduleName + "/");
// And warn if module is specified if modules aren't supported, conditional on -Xlint:proc?
@@ -1671,12 +1666,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (MatchingUtils.isValidImportString(pkg)) {
return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
} else {
- return warnAndNoMatches(s, p, log, lint);
+ return warnAndNoMatches(s, p, log);
}
}
- private static Pattern warnAndNoMatches(String s, Processor p, Log log, Lint lint) {
- lint.logIfEnabled(LintWarnings.ProcMalformedSupportedString(s, p.getClass().getName()));
+ private static Pattern warnAndNoMatches(String s, Processor p, Log log) {
+ log.warning(LintWarnings.ProcMalformedSupportedString(s, p.getClass().getName()));
return noMatches; // won't match any valid identifier
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
index 7dde6cc963f..a226b2f5960 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
@@ -1600,6 +1600,7 @@ compiler.err.multi-module.outdir.cannot.be.exploded.module=\
# 0: path
# lint: path
+# flags: default-enabled
compiler.warn.outdir.is.in.exploded.module=\
the output directory is within an exploded module: {0}
@@ -1924,19 +1925,19 @@ compiler.warn.incubating.modules=\
# 0: symbol, 1: symbol
# lint: deprecation
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated=\
{0} in {1} has been deprecated
# 0: symbol, 1: symbol
# lint: removal
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.for.removal=\
{0} in {1} has been deprecated and marked for removal
# 0: symbol
# lint: preview
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.is.preview=\
{0} is a preview API and may be removed in a future release.
@@ -1947,7 +1948,7 @@ compiler.err.is.preview=\
# 0: symbol
# lint: preview
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.is.preview.reflective=\
{0} is a reflective preview API and may be removed in a future release.
@@ -1959,13 +1960,13 @@ compiler.warn.restricted.method=\
# 0: symbol
# lint: deprecation
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.module=\
module {0} has been deprecated
# 0: symbol
# lint: removal
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.has.been.deprecated.for.removal.module=\
module {0} has been deprecated and marked for removal
@@ -2194,11 +2195,13 @@ compiler.warn.static.not.qualified.by.type2=\
# 0: string, 1: fragment
# lint: options
+# flags: default-enabled
compiler.warn.source.no.bootclasspath=\
bootstrap class path is not set in conjunction with -source {0}\n{1}
# 0: string, 1: fragment
# lint: options
+# flags: default-enabled
compiler.warn.source.no.system.modules.path=\
location of system modules is not set in conjunction with -source {0}\n{1}
@@ -2224,11 +2227,13 @@ compiler.misc.source.no.system.modules.path.with.target=\
# 0: string
# lint: options
+# flags: default-enabled
compiler.warn.option.obsolete.source=\
source value {0} is obsolete and will be removed in a future release
# 0: target
# lint: options
+# flags: default-enabled
compiler.warn.option.obsolete.target=\
target value {0} is obsolete and will be removed in a future release
@@ -2241,6 +2246,7 @@ compiler.err.option.removed.target=\
Target option {0} is no longer supported. Use {1} or later.
# lint: options
+# flags: default-enabled
compiler.warn.option.obsolete.suppression=\
To suppress warnings about obsolete options, use -Xlint:-options.
@@ -2365,13 +2371,13 @@ compiler.warn.unchecked.assign=\
# 0: symbol, 1: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.assign.to.var=\
unchecked assignment to variable {0} as member of raw type {1}
# 0: symbol, 1: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.call.mbr.of.raw.type=\
unchecked call to {0} as a member of the raw type {1}
@@ -2381,7 +2387,7 @@ compiler.warn.unchecked.cast.to.type=\
# 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.meth.invocation.applied=\
unchecked method invocation: {0} {1} in {4} {5} is applied to given types\n\
required: {2}\n\
@@ -2389,13 +2395,13 @@ compiler.warn.unchecked.meth.invocation.applied=\
# 0: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.generic.array.creation=\
unchecked generic array creation for varargs parameter of type {0}
# 0: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.unchecked.varargs.non.reifiable.type=\
Possible heap pollution from parameterized vararg type {0}
@@ -2794,7 +2800,7 @@ compiler.misc.prob.found.req=\
# 0: message segment, 1: type, 2: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.prob.found.req=\
{0}\n\
required: {2}\n\
@@ -3191,14 +3197,14 @@ compiler.err.override.incompatible.ret=\
# 0: message segment, 1: type, 2: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.override.unchecked.ret=\
{0}\n\
return type requires unchecked conversion from {1} to {2}
# 0: message segment, 1: type
# lint: unchecked
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.override.unchecked.thrown=\
{0}\n\
overridden method does not throw {1}
@@ -3302,13 +3308,13 @@ compiler.err.preview.feature.disabled.classfile=\
# 0: message segment (feature)
# lint: preview
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.preview.feature.use=\
{0} is a preview feature and may be removed in a future release.
# 0: message segment (feature)
# lint: preview
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.preview.feature.use.plural=\
{0} are a preview feature and may be removed in a future release.
@@ -3879,6 +3885,7 @@ compiler.err.bad.name.for.option=\
# 0: option name, 1: symbol
# lint: options
+# flags: default-enabled
compiler.warn.module.for.option.not.found=\
module name in {0} option not found: {1}
@@ -3895,6 +3902,7 @@ compiler.err.add.reads.with.release=\
adding read edges for system module {0} is not allowed with --release
# lint: options
+# flags: default-enabled
compiler.warn.addopens.ignored=\
--add-opens has no effect at compile time
@@ -4272,7 +4280,7 @@ compiler.err.incorrect.number.of.nested.patterns=\
# 0: kind name, 1: symbol
# lint: preview
-# flags: aggregate, mandatory
+# flags: aggregate, mandatory, default-enabled
compiler.warn.declared.using.preview=\
{0} {1} is declared using a preview feature, which may be removed in a future release.
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
index 06a1d9fc7a3..c9f529eae55 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JCDiagnostic.java
@@ -368,6 +368,36 @@ public class JCDiagnostic implements Diagnostic {
* the end position of the tree node. Otherwise, just returns the
* same as getPreferredPosition(). */
int getEndPosition(EndPosTable endPosTable);
+ /** Get the position that determines which Lint configuration applies. */
+ default int getLintPosition() {
+ return getStartPosition();
+ }
+ /** Create a new instance from this instance and the given lint position. */
+ default DiagnosticPosition withLintPosition(int lintPos) {
+ DiagnosticPosition orig = this;
+ return new DiagnosticPosition() {
+ @Override
+ public JCTree getTree() {
+ return orig.getTree();
+ }
+ @Override
+ public int getStartPosition() {
+ return orig.getStartPosition();
+ }
+ @Override
+ public int getPreferredPosition() {
+ return orig.getPreferredPosition();
+ }
+ @Override
+ public int getEndPosition(EndPosTable endPosTable) {
+ return orig.getEndPosition(endPosTable);
+ }
+ @Override
+ public int getLintPosition() {
+ return lintPos;
+ }
+ };
+ }
}
/**
@@ -405,6 +435,10 @@ public class JCDiagnostic implements Diagnostic {
RECOVERABLE,
NON_DEFERRABLE,
COMPRESSED,
+ /** Flag for lint diagnostics that should be emitted even when their category
+ * is not explicitly enabled, as long as it is not explicitly suppressed.
+ */
+ DEFAULT_ENABLED,
/** Flags mandatory warnings that should pass through a mandatory warning aggregator.
*/
AGGREGATE,
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java
index 576344a3d2a..95458f339a1 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java
@@ -32,29 +32,45 @@ import java.util.Comparator;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.api.DiagnosticFormatter;
+import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
+import com.sun.tools.javac.code.LintMapper;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.comp.AttrContext;
+import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.tree.EndPosTable;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.*;
+import com.sun.tools.javac.tree.TreeInfo;
+import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticInfo;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
+import com.sun.tools.javac.util.JCDiagnostic.LintWarning;
import static com.sun.tools.javac.main.Option.*;
import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
+import static com.sun.tools.javac.code.Lint.LintCategory.*;
+import static com.sun.tools.javac.resources.CompilerProperties.LintWarnings.RequiresAutomatic;
+import static com.sun.tools.javac.resources.CompilerProperties.LintWarnings.RequiresTransitiveAutomatic;
+import static com.sun.tools.javac.tree.JCTree.Tag.*;
/** A class for error logs. Reports errors and warnings, and
* keeps track of error numbers and positions.
@@ -103,6 +119,11 @@ public class Log extends AbstractLog {
*/
protected final DiagnosticHandler prev;
+ /**
+ * Diagnostics waiting for an applicable {@link Lint} instance.
+ */
+ protected Map> lintWaitersMap = new LinkedHashMap<>();
+
/**
* Install this diagnostic handler as the current one,
* recording the previous one.
@@ -113,9 +134,92 @@ public class Log extends AbstractLog {
}
/**
- * Handle a diagnostic.
+ * Step 1: Handle a diagnostic for which the applicable Lint instance (if any) may not be known yet.
*/
- public abstract void report(JCDiagnostic diag);
+ public final void report(JCDiagnostic diag) {
+ Lint lint = null;
+ LintCategory category = diag.getLintCategory();
+ if (category != null) { // this is a lint warning; find the applicable Lint
+ DiagnosticPosition pos = diag.getDiagnosticPosition();
+ if (pos != null && category.annotationSuppression) { // we should apply the Lint from the warning's position
+ if ((lint = lintFor(diag)) == null) {
+ addLintWaiter(currentSourceFile(), diag); // ...but we don't know it yet, so defer
+ return;
+ }
+ } else // we should apply the root Lint
+ lint = rootLint();
+ }
+ reportWithLint(diag, lint);
+ }
+
+ /**
+ * Step 2: Handle a diagnostic for which the applicable Lint instance (if any) is known and provided.
+ */
+ public final void reportWithLint(JCDiagnostic diag, Lint lint) {
+
+ // Apply hackery for REQUIRES_TRANSITIVE_AUTOMATIC (see also Check.checkModuleRequires())
+ if (diag.getCode().equals(RequiresTransitiveAutomatic.key()) && !lint.isEnabled(REQUIRES_TRANSITIVE_AUTOMATIC)) {
+ reportWithLint(
+ diags.warning(null, diag.getDiagnosticSource(), diag.getDiagnosticPosition(), RequiresAutomatic), lint);
+ return;
+ }
+
+ // Apply the lint configuration (if any) and discard the warning if it gets filtered out
+ if (lint != null) {
+ LintCategory category = diag.getLintCategory();
+ boolean emit = !diag.isFlagSet(DEFAULT_ENABLED) ? // is the warning not enabled by default?
+ lint.isEnabled(category) : // then emit if the category is enabled
+ category.annotationSuppression ? // else emit if the category is not suppressed, where
+ !lint.isSuppressed(category) : // ...suppression happens via @SuppressWarnings
+ !options.isLintDisabled(category); // ...suppression happens via -Xlint:-category
+ if (!emit)
+ return;
+ }
+
+ // Proceed
+ reportReady(diag);
+ }
+
+ /**
+ * Step 3: Handle a diagnostic to which the applicable Lint instance (if any) has been applied.
+ */
+ protected abstract void reportReady(JCDiagnostic diag);
+
+ protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diagnostic) {
+ lintWaitersMap.computeIfAbsent(sourceFile, s -> new LinkedList<>()).add(diagnostic);
+ }
+
+ /**
+ * Flush any lint waiters whose {@link Lint} configurations are now known.
+ */
+ public void flushLintWaiters() {
+ lintWaitersMap.entrySet().removeIf(entry -> {
+
+ // Is the source file no longer recognized? If so, discard warnings (e.g., this can happen with JShell)
+ JavaFileObject sourceFile = entry.getKey();
+ if (!lintMapper.isKnown(sourceFile))
+ return true;
+
+ // Flush those diagnostics for which we now know the applicable Lint
+ List diagnosticList = entry.getValue();
+ JavaFileObject prevSourceFile = useSource(sourceFile);
+ try {
+ diagnosticList.removeIf(diag -> {
+ Lint lint = lintFor(diag);
+ if (lint != null) {
+ reportWithLint(diag, lint);
+ return true;
+ }
+ return false;
+ });
+ } finally {
+ useSource(prevSourceFile);
+ }
+
+ // Discard list if empty
+ return diagnosticList.isEmpty();
+ });
+ }
}
/**
@@ -124,7 +228,10 @@ public class Log extends AbstractLog {
public class DiscardDiagnosticHandler extends DiagnosticHandler {
@Override
- public void report(JCDiagnostic diag) { }
+ protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diagnostic) { }
+
+ @Override
+ protected void reportReady(JCDiagnostic diag) { }
}
/**
@@ -157,11 +264,20 @@ public class Log extends AbstractLog {
}
@Override
- public void report(JCDiagnostic diag) {
+ protected void reportReady(JCDiagnostic diag) {
if (deferrable(diag)) {
deferred.add(diag);
} else {
- prev.report(diag);
+ prev.reportReady(diag);
+ }
+ }
+
+ @Override
+ protected void addLintWaiter(JavaFileObject sourceFile, JCDiagnostic diag) {
+ if (deferrable(diag)) {
+ super.addLintWaiter(sourceFile, diag);
+ } else {
+ prev.addLintWaiter(sourceFile, diag);
}
}
@@ -182,6 +298,13 @@ public class Log extends AbstractLog {
.filter(accepter)
.forEach(prev::report);
deferred = null; // prevent accidental ongoing use
+
+ // Flush matching Lint waiters to the previous handler
+ lintWaitersMap.forEach(
+ (sourceFile, diagnostics) -> diagnostics.stream()
+ .filter(accepter)
+ .forEach(diagnostic -> prev.addLintWaiter(sourceFile, diagnostic)));
+ lintWaitersMap = null; // prevent accidental ongoing use
}
/** Report all deferred diagnostics in the specified order. */
@@ -247,6 +370,16 @@ public class Log extends AbstractLog {
*/
private final Context context;
+ /**
+ * The {@link Options} singleton.
+ */
+ private final Options options;
+
+ /**
+ * The lint positions table.
+ */
+ private final LintMapper lintMapper;
+
/**
* The root {@link Lint} singleton.
*/
@@ -350,6 +483,8 @@ public class Log extends AbstractLog {
super(JCDiagnostic.Factory.instance(context));
context.put(logKey, this);
this.context = context;
+ this.options = Options.instance(context);
+ this.lintMapper = LintMapper.instance(context);
this.writers = writers;
@SuppressWarnings("unchecked") // FIXME
@@ -369,7 +504,6 @@ public class Log extends AbstractLog {
this.diagFormatter = new BasicDiagnosticFormatter(messages);
// Once Options is ready, complete the initialization
- final Options options = Options.instance(context);
options.whenReady(this::initOptions);
}
// where
@@ -689,6 +823,21 @@ public class Log extends AbstractLog {
diagnosticHandler.report(diagnostic);
}
+// Deferred Lint Calculation
+
+ /**
+ * Report unreported lint warnings for which the applicable {@link Lint} configuration is now known.
+ */
+ public void reportOutstandingWarnings() {
+ diagnosticHandler.flushLintWaiters();
+ }
+
+ // Get the Lint config for the given warning (if known)
+ private Lint lintFor(JCDiagnostic diag) {
+ Assert.check(diag.getLintCategory() != null);
+ return lintMapper.lintAt(diag.getSource(), diag.getDiagnosticPosition()).orElse(null);
+ }
+
// Obtain root Lint singleton lazily to avoid init loops
private Lint rootLint() {
if (rootLint == null)
@@ -756,7 +905,7 @@ public class Log extends AbstractLog {
private class DefaultDiagnosticHandler extends DiagnosticHandler {
@Override
- public void report(JCDiagnostic diagnostic) {
+ protected void reportReady(JCDiagnostic diagnostic) {
if (expectDiagKeys != null)
expectDiagKeys.remove(diagnostic.getCode());
@@ -783,13 +932,13 @@ public class Log extends AbstractLog {
// Apply the appropriate mandatory warning aggregator, if needed
if (diagnostic.isFlagSet(AGGREGATE)) {
LintCategory category = diagnostic.getLintCategory();
- boolean verbose = rootLint().isEnabled(category);
+ boolean verbose = lintFor(diagnostic).isEnabled(category);
if (!aggregatorFor(category).aggregate(diagnostic, verbose))
return;
}
// Strict warnings are always emitted
- if (diagnostic.isFlagSet(DiagnosticFlag.STRICT)) {
+ if (diagnostic.isFlagSet(STRICT)) {
writeDiagnostic(diagnostic);
nwarnings++;
return;
diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
index 365f6d1e68a..4e4751b264e 100644
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java
@@ -50,7 +50,7 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
*/
@Override
public JdkConsole console(boolean isTTY, Charset inCharset, Charset outCharset) {
- return new LazyDelegatingJdkConsoleImpl(inCharset, outCharset);
+ return isTTY ? new LazyDelegatingJdkConsoleImpl(inCharset, outCharset) : null;
}
private static class LazyDelegatingJdkConsoleImpl implements JdkConsole {
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template
index 5a36ee06819..16ae5a4d221 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/search.js.template
@@ -423,7 +423,8 @@ $.widget("custom.catcomplete", $.ui.autocomplete, {
var label = getResultLabel(item);
var resultDesc = getResultDescription(item);
return $("")
- .append($("")
+ .append($("")
+ .attr("href", item.indexItem ? pathtoroot + getURL(item.indexItem, item.category) : null)
.append($("").addClass("search-result-label").html(label))
.append($("").addClass("search-result-desc").html(resultDesc)))
.appendTo(ul);
@@ -515,7 +516,7 @@ $(function() {
this.menu.previousFilter = "_";
this.menu.filterTimer = this.menu._delay(function() {
delete this.previousFilter;
- }, 1000);
+ }, 500);
return doSearch(request, response);
},
response: function(event, ui) {
@@ -531,6 +532,11 @@ $(function() {
collision: "flip"
},
select: function(event, ui) {
+ for (var e = event.originalEvent; e != null; e = e.originalEvent) {
+ if (e.type === "click") {
+ return;
+ }
+ }
if (ui.item.indexItem) {
var url = getURL(ui.item.indexItem, ui.item.category);
window.location.href = pathtoroot + url;
diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
index 587121ad582..778ee5f03b3 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css
@@ -1235,11 +1235,11 @@ li.ui-static-link a, li.ui-static-link a:visited {
grid-template-columns: auto auto;
}
.ui-autocomplete > li,
-.ui-autocomplete > li > div {
+.ui-autocomplete > li > a {
grid-column: 1 / 3;
}
.ui-autocomplete > li.result-item,
-.ui-autocomplete > li.result-item > div {
+.ui-autocomplete > li.result-item > a {
display: grid;
grid-template-columns: subgrid;
}
@@ -1250,6 +1250,7 @@ li.ui-static-link a, li.ui-static-link a:visited {
}
.ui-autocomplete .search-result-label {
padding: 1px 4px;
+ color: var(--block-text-color);
overflow: hidden;
text-overflow: ellipsis;
}
@@ -1263,6 +1264,7 @@ li.ui-static-link a, li.ui-static-link a:visited {
.ui-autocomplete .result-highlight {
font-weight:bold;
}
+.ui-menu .ui-state-active .search-result-label,
.ui-menu .ui-state-active .search-result-desc {
color: var(--selected-text-color);
}
@@ -1843,9 +1845,9 @@ table.striped > tbody > tr > th {
grid-template-columns: none;
}
.ui-autocomplete > li,
- .ui-autocomplete > li > div,
+ .ui-autocomplete > li > a,
.ui-autocomplete > li.result-item,
- .ui-autocomplete > li.result-item > div {
+ .ui-autocomplete > li.result-item > a {
grid-column: unset;
display: block;
grid-template-columns: none;
diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java b/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
index bccdf4cc8bf..67b8e391bf3 100644
--- a/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
+++ b/src/jdk.jdi/share/classes/com/sun/jdi/ThreadReference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2025, 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
@@ -402,8 +402,8 @@ public interface ThreadReference extends ObjectReference {
* @throws java.lang.IllegalArgumentException if frame
* is not on this thread's call stack.
*
- * @throws OpaqueFrameException if this thread is a suspended virtual thread and the
- * target VM was unable to pop the frames.
+ * @throws OpaqueFrameException if the target VM is unable to pop this frame
+ * (e.g. a virtual thread is suspended, but not at an event).
*
* @throws NativeMethodException if one of the frames that would be
* popped is that of a native method or if the frame previous to
@@ -484,8 +484,8 @@ public interface ThreadReference extends ObjectReference {
* @throws IncompatibleThreadStateException if this
* thread is not suspended.
*
- * @throws OpaqueFrameException if this thread is a suspended virtual thread and the
- * target VM is unable to force the method to return.
+ * @throws OpaqueFrameException if the target VM is unable to force the method to return
+ * (e.g. a virtual thread is suspended, but not at an event).
*
* @throws NativeMethodException if the frame to be returned from
* is that of a native method.
diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/StackFrameImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/StackFrameImpl.java
index e242bd7313b..a36e5695f69 100644
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/StackFrameImpl.java
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/StackFrameImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2025, 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
@@ -395,29 +395,24 @@ public class StackFrameImpl extends MirrorImpl
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.OPAQUE_FRAME:
- if (thread.isVirtual()) {
- // We first need to find out if the current frame is native, or if the
- // previous frame is native, in which case we throw NativeMethodException
- for (int i = 0; i < 2; i++) {
- StackFrameImpl sf;
- try {
- sf = (StackFrameImpl)thread.frame(i);
- } catch (IndexOutOfBoundsException e) {
- // This should never happen, but we need to check for it.
- break;
- }
- sf.validateStackFrame();
- MethodImpl meth = (MethodImpl)sf.location().method();
- if (meth.isNative()) {
- throw new NativeMethodException();
- }
+ // We first need to find out if the current frame is native, or if the
+ // previous frame is native, in which case we throw NativeMethodException
+ for (int i = 0; i < 2; i++) {
+ StackFrame sf;
+ try {
+ sf = thread.frame(i);
+ } catch (IndexOutOfBoundsException e) {
+ // This should never happen, but we need to check for it.
+ break;
+ }
+ Method meth = sf.location().method();
+ if (meth.isNative()) {
+ throw new NativeMethodException();
}
- // No native frames involved. Must have been due to thread
- // not being mounted.
- throw new OpaqueFrameException();
- } else {
- throw new NativeMethodException();
}
+ // No native frames involved. Must have been due to virtual thread
+ // not being mounted or some other reason such as failure to deopt.
+ throw new OpaqueFrameException();
case JDWP.Error.THREAD_NOT_SUSPENDED:
throw new IncompatibleThreadStateException(
"Thread not current or suspended");
diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
index 0f99fe99871..e5dce0718f4 100644
--- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
+++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ThreadReferenceImpl.java
@@ -597,10 +597,10 @@ public class ThreadReferenceImpl extends ObjectReferenceImpl
} catch (JDWPException exc) {
switch (exc.errorCode()) {
case JDWP.Error.OPAQUE_FRAME:
- if (isVirtual() && !meth.isNative()) {
- throw new OpaqueFrameException();
- } else {
+ if (meth.isNative()) {
throw new NativeMethodException();
+ } else {
+ throw new OpaqueFrameException();
}
case JDWP.Error.THREAD_NOT_SUSPENDED:
throw new IncompatibleThreadStateException(
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java
index fc1dd97d9ab..226bb9e8134 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacApplicationBuilder.java
@@ -26,7 +26,10 @@ package jdk.jpackage.internal;
import java.io.IOException;
import java.io.UncheckedIOException;
+import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.List;
+import java.util.Set;
import java.util.Objects;
import java.util.Optional;
import jdk.jpackage.internal.model.Application;
@@ -95,6 +98,7 @@ final class MacApplicationBuilder {
}
validateAppVersion(app);
+ validateAppContentDirs(app);
final var mixin = new MacApplicationMixin.Stub(
validatedIcon(),
@@ -140,6 +144,18 @@ final class MacApplicationBuilder {
}
}
+ private static void validateAppContentDirs(Application app) {
+ for (var contentDir : app.contentDirs()) {
+ if (!Files.isDirectory(contentDir)) {
+ Log.info(I18N.format("warning.app.content.is.not.dir",
+ contentDir));
+ } else if (!CONTENTS_SUB_DIRS.contains(contentDir.getFileName().toString())) {
+ Log.info(I18N.format("warning.non.standard.contents.sub.dir",
+ contentDir));
+ }
+ }
+ }
+
private MacApplicationBuilder createCopyForExternalInfoPlistFile() throws ConfigException {
try {
final var plistFile = AppImageInfoPListFile.loadFromInfoPList(externalInfoPlistFile);
@@ -250,4 +266,8 @@ final class MacApplicationBuilder {
private static final Defaults DEFAULTS = new Defaults("utilities");
private static final int MAX_BUNDLE_NAME_LENGTH = 16;
+
+ // List of standard subdirectories of the "Contents" directory
+ private static final Set CONTENTS_SUB_DIRS = Set.of("MacOS",
+ "Resources", "Frameworks", "PlugIns", "SharedSupport");
}
diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
index 7fada9e4305..c48513c7a51 100644
--- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
+++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources.properties
@@ -85,3 +85,5 @@ message.codesign.failed.reason.app.content="codesign" failed and additional appl
message.codesign.failed.reason.xcode.tools=Possible reason for "codesign" failure is missing Xcode with command line developer tools. Install Xcode with command line developer tools to see if it resolves the problem.
warning.unsigned.app.image=Warning: Using unsigned app-image to build signed {0}.
warning.per.user.app.image.signed=Warning: Support for per-user configuration of the installed application will not be supported due to missing "{0}" in predefined signed application image.
+warning.non.standard.contents.sub.dir=Warning: The file name of the directory "{0}" specified for the --app-content option is not a standard subdirectory name in the "Contents" directory of the application bundle. The result application bundle may fail code signing and/or notarization.
+warning.app.content.is.not.dir=Warning: The value "{0}" of the --app-content option is not a directory. The result application bundle may fail code signing and/or notarization.
\ No newline at end of file
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java
index 1dd2d823f27..7790ebb3ebb 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/CLIHelp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, 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
@@ -55,6 +55,7 @@ public class CLIHelp {
String pInstallDir;
String pAppImageDescription;
String pSignSampleUsage;
+ String pAppContentNote;
switch (platform) {
case MACOS:
types = "{\"app-image\", \"dmg\", \"pkg\"}";
@@ -66,6 +67,8 @@ public class CLIHelp {
= I18N.getString("MSG_Help_mac_app_image");
pSignSampleUsage
= I18N.getString("MSG_Help_mac_sign_sample_usage");
+ pAppContentNote
+ = I18N.getString("MSG_Help_mac_app_content_note");
break;
case LINUX:
types = "{\"app-image\", \"rpm\", \"deb\"}";
@@ -76,6 +79,7 @@ public class CLIHelp {
pAppImageDescription
= I18N.getString("MSG_Help_default_app_image");
pSignSampleUsage = "";
+ pAppContentNote = "";
break;
case WINDOWS:
types = "{\"app-image\", \"exe\", \"msi\"}";
@@ -86,6 +90,7 @@ public class CLIHelp {
pAppImageDescription
= I18N.getString("MSG_Help_default_app_image");
pSignSampleUsage = "";
+ pAppContentNote = "";
break;
default:
types = "{\"app-image\", \"exe\", \"msi\", \"rpm\", \"deb\", \"pkg\", \"dmg\"}";
@@ -99,12 +104,13 @@ public class CLIHelp {
pAppImageDescription
= I18N.getString("MSG_Help_default_app_image");
pSignSampleUsage = "";
+ pAppContentNote = "";
break;
}
Log.info(MessageFormat.format(I18N.getString("MSG_Help"),
File.pathSeparator, types, pLaunchOptions,
pInstallOptions, pInstallDir, pAppImageDescription,
- pSignSampleUsage));
+ pSignSampleUsage, pAppContentNote));
}
}
}
diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties
index 0f0d9fd5a17..df87a63cb8e 100644
--- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties
+++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 2025, 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
@@ -133,7 +133,7 @@ Generic Options:\n\
\ A comma separated list of paths to files and/or directories\n\
\ to add to the application payload.\n\
\ This option can be used more than once.\n\
-\n\
+{7}\n\
\Options for creating the application launcher(s):\n\
\ --add-launcher =\n\
\ Name of launcher, and a path to a Properties file that contains\n\
@@ -334,3 +334,10 @@ MSG_Help_mac_sign_sample_usage=\
\ --mac-sign [...]\n\
\ Note: the only additional options that are permitted in this mode are:\n\
\ the set of additional mac signing options and --verbose\n\
+
+MSG_Help_mac_app_content_note=\
+\ Note: The value should be a directory with the "Resources"\n\
+\ subdirectory (or any other directory that is valid in the "Contents"\n\
+\ directory of the application bundle). Otherwise, jpackage may produce\n\
+\ invalid application bundle which may fail code signing and/or\n\
+\ notarization.\n\
diff --git a/src/jdk.jpackage/share/man/jpackage.md b/src/jdk.jpackage/share/man/jpackage.md
index e49b04e204e..f78bec9808c 100644
--- a/src/jdk.jpackage/share/man/jpackage.md
+++ b/src/jdk.jpackage/share/man/jpackage.md
@@ -190,6 +190,12 @@ The `jpackage` tool will take as input a Java application and a Java run-time im
This option can be used more than once.
+ macOS note: The value should be a directory with the "Resources"
+ subdirectory (or any other directory that is valid in the
+ "Contents" directory of the application bundle). Otherwise,
+ jpackage may produce invalid application bundle which may fail
+ code signing and/or notarization.
+
### Options for creating the application launcher(s):
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
index 4ee629476db..cb4861651e3 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
+++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java
@@ -66,6 +66,7 @@ import com.sun.tools.javac.parser.Tokens.Token;
import com.sun.tools.javac.parser.Tokens.TokenKind;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
import jdk.internal.shellsupport.doc.JavadocHelper;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
@@ -139,6 +140,7 @@ import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Types;
+import javax.tools.DiagnosticListener;
import javax.tools.JavaFileManager.Location;
import javax.tools.StandardLocation;
@@ -654,7 +656,10 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis {
Trees trees = task.trees();
SourcePositions sp = trees.getSourcePositions();
List tokens = new ArrayList<>();
- Scanner scanner = ScannerFactory.instance(new Context()).newScanner(wrappedCode, false);
+ Context ctx = new Context();
+ ctx.put(DiagnosticListener.class, (DiagnosticListener) d -> {});
+ Scanner scanner = ScannerFactory.instance(ctx).newScanner(wrappedCode, false);
+ Log.instance(ctx).useSource(cut.getSourceFile());
scanner.nextToken();
BiConsumer addKeywordForSpan = (spanStart, spanEnd) -> {
int start = codeWrap.wrapIndexToSnippetIndex(spanStart);
diff --git a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/TOOLING.jsh b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/TOOLING.jsh
index b97b6341cfa..16436514383 100644
--- a/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/TOOLING.jsh
+++ b/src/jdk.jshell/share/classes/jdk/jshell/tool/resources/TOOLING.jsh
@@ -8,9 +8,9 @@ void jmod(String... args) { run("jmod", args); }
void jpackage(String... args) { run("jpackage", args); }
void javap(Class> type) throws Exception {
+ if (type.isPrimitive() || type.isHidden() || type.isArray()) throw new IllegalArgumentException("Type has no class file: " + type);
try {
- var name = type.getCanonicalName();
- if (name == null) throw new IllegalArgumentException("Type not supported: " + type);
+ var name = type.getName();
if (type == Class.forName(name, false, ClassLoader.getSystemClassLoader())) {
run("javap", "-c", "-v", "-s", name);
return;
diff --git a/test/hotspot/gtest/nmt/test_nmt_malloclimit.cpp b/test/hotspot/gtest/nmt/test_nmt_malloclimit.cpp
index 83d4bd6235b..da357285148 100644
--- a/test/hotspot/gtest/nmt/test_nmt_malloclimit.cpp
+++ b/test/hotspot/gtest/nmt/test_nmt_malloclimit.cpp
@@ -42,8 +42,8 @@ static bool compare_limits(const malloclimit* a, const malloclimit* b) {
static bool compare_sets(const MallocLimitSet* a, const MallocLimitSet* b) {
if (compare_limits(a->global_limit(), b->global_limit())) {
for (int i = 0; i < mt_number_of_tags; i++) {
- if (!compare_limits(a->category_limit(NMTUtil::index_to_tag(i)),
- b->category_limit(NMTUtil::index_to_tag(i)))) {
+ if (!compare_limits(a->mem_tag_limit(NMTUtil::index_to_tag(i)),
+ b->mem_tag_limit(NMTUtil::index_to_tag(i)))) {
return false;
}
}
@@ -92,7 +92,7 @@ TEST(NMT, MallocLimitPerCategory) {
test("metaspace:1m,compiler:2m:oom,thread:3m:oom,threadstack:4m:oom,class:5m,classshared:6m", expected);
}
-TEST(NMT, MallocLimitCategoryEnumNames) {
+TEST(NMT, MallocLimitMemTagEnumNames) {
MallocLimitSet expected;
stringStream option;
for (int i = 0; i < mt_number_of_tags; i++) {
diff --git a/test/hotspot/gtest/nmt/test_nmt_totals.cpp b/test/hotspot/gtest/nmt/test_nmt_totals.cpp
index 61c591fa0bb..690751ede54 100644
--- a/test/hotspot/gtest/nmt/test_nmt_totals.cpp
+++ b/test/hotspot/gtest/nmt/test_nmt_totals.cpp
@@ -88,8 +88,8 @@ TEST_VM(NMTNumbers, totals) {
void* p[NUM_ALLOCS];
for (int i = 0; i < NUM_ALLOCS; i ++) {
// spread over categories
- int category = i % (mt_number_of_tags - 1);
- p[i] = NEW_C_HEAP_ARRAY(char, ALLOC_SIZE, (MemTag)category);
+ int mtag = i % (mt_number_of_tags - 1);
+ p[i] = NEW_C_HEAP_ARRAY(char, ALLOC_SIZE, (MemTag)mtag);
}
const totals_t t2 = get_totals();
diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java
new file mode 100644
index 00000000000..a8f75b9c8f4
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8360561
+ * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range)
+ * Comparing such values in such range with != should always be true.
+ * @run main/othervm -Xcomp
+ * -XX:CompileCommand=compileonly,compiler.igvn.CmpDisjointButNonOrderedRanges::*
+ * compiler.igvn.CmpDisjointButNonOrderedRanges
+ * @run main compiler.igvn.CmpDisjointButNonOrderedRanges
+ */
+package compiler.igvn;
+
+public class CmpDisjointButNonOrderedRanges {
+ static boolean bFld;
+
+ public static void main(String[] strArr) {
+ test();
+ }
+
+ static void test() {
+ int x = 7;
+ int y = 4;
+ for (int i = 3; i < 12; i++) {
+ // x = 7 \/ x = -195 => x \in [-195, 7] as a signed value
+ // but [7, bitwise_cast_uint(-195)] as unsigned
+ // So 0 is not possible.
+ if (x != 0) {
+ A.foo();
+ // Because A is not loaded, A.foo() traps and this point is not reachable.
+ }
+ // x is tighten to be in the meet (so Hotspot's join) of [0, 0] and [7, bitwise_cast_uint(-195)]
+ // that is bottom (Hotspot's top). Data is dead, control needs to be dead as well.
+ for (int j = 1; j < 8; j++) {
+ x = -195;
+ if (bFld) {
+ y += 2;
+ }
+ }
+ }
+ }
+
+ static void foo() {
+ }
+}
+
+
+class A {
+ static void foo() {
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java
new file mode 100644
index 00000000000..205a7f7d380
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRanges2.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8360561
+ * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range)
+ * Comparing such values in such range with != should always be true.
+ * @run main/othervm -Xbatch
+ * -XX:CompileCommand=compileonly,compiler.igvn.CmpDisjointButNonOrderedRanges2::*
+ * -XX:-TieredCompilation
+ * -XX:+UnlockExperimentalVMOptions
+ * -XX:PerMethodTrapLimit=0
+ * compiler.igvn.CmpDisjointButNonOrderedRanges2
+ * @run main compiler.igvn.CmpDisjointButNonOrderedRanges2
+ */
+package compiler.igvn;
+
+public class CmpDisjointButNonOrderedRanges2 {
+ int array[];
+
+ void test() {
+ int val = 2;
+ for (int i = 0; i < 10; i++) {
+ // val = 2 \/ val = -12 => val \in [-12, 2] as a signed value
+ // but [2, bitwise_cast_uint(-12)] as unsigned
+ // So 0 is not possible.
+ if (val != 0) {
+ return;
+ }
+ // val is tighten to be in the meet (so Hotspot's join) of [0, 0] and [2, bitwise_cast_uint(-12)]
+ // that is bottom (Hotspot's top). Data is dead, control needs to be dead as well.
+ for (int j = 0; j < 10; j++) {
+ array[1] = val;
+ val = -12;
+ }
+ }
+ }
+
+ static public void main(String[] args) {
+ var c = new CmpDisjointButNonOrderedRanges2();
+ for (int i = 0; i < 1000; ++i) {
+ c.test();
+ for (int j = 0; j < 100; ++j) {
+ }
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java
new file mode 100644
index 00000000000..c5ef1640721
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/igvn/CmpDisjointButNonOrderedRangesLong.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8360561
+ * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range)
+ * Comparing such values in such range with != should always be true.
+ * @library /test/lib /
+ * @run main compiler.igvn.CmpDisjointButNonOrderedRangesLong
+ */
+package compiler.igvn;
+
+import compiler.lib.ir_framework.*;
+
+public class CmpDisjointButNonOrderedRangesLong {
+ static boolean bFld;
+ static double dFld1;
+ static double dFld2;
+
+ public static void main(String[] strArr) {
+ TestFramework.run();
+ }
+
+ @Test
+ @IR(failOn = {IRNode.PHI})
+ @Warmup(0)
+ static int test() {
+ long x = 7;
+ if (bFld) {
+ x = -195;
+ }
+
+ dFld1 = dFld2 % 2.5;
+
+ if (x == 0) {
+ return 0;
+ }
+ return 1;
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
index 22f2887a266..14897f7ab87 100644
--- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java
+++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java
@@ -36,6 +36,7 @@
package compiler.startup;
+import jdk.test.lib.Platform;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
import jdk.test.lib.Utils;
@@ -60,8 +61,11 @@ public class StartupOutput {
throw new Exception("VM crashed with exit code " + exitCode);
}
+ // On s390x, generated code is ~6x larger in fastdebug and ~1.4x in release builds vs. other archs,
+ // hence we require slightly more minimum space.
+ int minInitialSize = 800 + (Platform.isS390x() ? 800 : 0);
for (int i = 0; i < 200; i++) {
- int initialCodeCacheSizeInKb = 800 + rand.nextInt(400);
+ int initialCodeCacheSizeInKb = minInitialSize + rand.nextInt(400);
int reservedCodeCacheSizeInKb = initialCodeCacheSizeInKb + rand.nextInt(200);
pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:InitialCodeCacheSize=" + initialCodeCacheSizeInKb + "K", "-XX:ReservedCodeCacheSize=" + reservedCodeCacheSizeInKb + "k", "-version");
out = new OutputAnalyzer(pb.start());
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java
index 6267c6bdf33..3c3db7d0397 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfSyntheticClasses.java
@@ -120,9 +120,9 @@ public class LotsOfSyntheticClasses {
OutputAnalyzer output = TestCommon.createArchive(
APP_JAR.toString(),
listAppClasses(),
- MAIN_CLASS_NAME,
// Verification for lots of classes slows down the test.
"-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:+UnlockDiagnosticVMOptions",
"-XX:-VerifyDependencies",
"-XX:-VerifyBeforeExit"
);
@@ -134,6 +134,7 @@ public class LotsOfSyntheticClasses {
TestCommon.run(
// Verification for lots of classes slows down the test.
"-XX:+IgnoreUnrecognizedVMOptions",
+ "-XX:+UnlockDiagnosticVMOptions",
"-XX:-VerifyDependencies",
"-XX:-VerifyBeforeExit",
"-cp", APP_JAR.toString(),
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java
index 4f2822a5970..5d1e3831d86 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/TestCommon.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025, 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
@@ -427,8 +427,6 @@ public class TestCommon extends CDSTestUtils {
cmd.add(opts.appJar);
}
- CDSTestUtils.addVerifyArchivedFields(cmd);
-
for (String s : opts.suffix) cmd.add(s);
if (RUN_WITH_JFR) {
diff --git a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java
index 7460a160ee6..1a304a44944 100644
--- a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java
+++ b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java
@@ -51,8 +51,10 @@ public class TestIncludesAreSorted {
"share/code",
"share/compiler",
"share/interpreter",
+ "share/jfr",
"share/jvmci",
"share/libadt",
+ "share/logging",
"share/metaprogramming",
"share/oops",
"share/opto",
diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java
index ac8867f3985..a33aacd924e 100644
--- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java
+++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestBadFormat.java
@@ -1124,8 +1124,8 @@ class BadIRAnnotationsAfterTestVM {
@Test
@FailCount(8)
- @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0"})
- @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_MAX, "> 0"}) // valid
+ @IR(counts = {IRNode.LOAD_VECTOR_I, "> 0"}, applyIf = {"MaxVectorSize", "> 0"}) // valid, but only if MaxVectorSize > 0, otherwise, a violation is reported
+ @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_MAX, "> 0"}, applyIf = {"MaxVectorSize", "> 0"}) // valid, but only if MaxVectorSize > 0, otherwise, a violation is reported
@IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_ANY, "> 0"}) // valid
@IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "", "> 0"})
@IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "xxx", "> 0"})
diff --git a/test/jdk/java/io/Console/DefaultCharsetTest.java b/test/jdk/java/io/Console/DefaultCharsetTest.java
index 0fca8a3cc3f..981d92ce282 100644
--- a/test/jdk/java/io/Console/DefaultCharsetTest.java
+++ b/test/jdk/java/io/Console/DefaultCharsetTest.java
@@ -21,33 +21,66 @@
* questions.
*/
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+import static jdk.test.lib.Utils.*;
/**
* @test
- * @bug 8341975 8351435
+ * @bug 8341975 8351435 8361613
* @summary Tests the default charset. It should honor `stdout.encoding`
* which should be the same as System.out.charset()
- * @modules jdk.internal.le
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=UTF-8 DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=ISO-8859-1 DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=US-ASCII DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=foo DefaultCharsetTest
- * @run junit/othervm -Djdk.console=jdk.internal.le DefaultCharsetTest
+ * @requires (os.family == "linux") | (os.family == "mac")
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.JDKToolFinder
+ * jdk.test.lib.process.ProcessTools
+ * @run junit DefaultCharsetTest
*/
public class DefaultCharsetTest {
- @Test
- public void testDefaultCharset() {
+ @BeforeAll
+ static void checkExpectAvailability() {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
+ }
+ @ParameterizedTest
+ @ValueSource(strings = {"UTF-8", "ISO-8859-1", "US-ASCII", "foo", ""})
+ void testDefaultCharset(String stdoutEncoding) throws Exception {
+ // invoking "expect" command
+ OutputAnalyzer oa = ProcessTools.executeProcess(
+ "expect",
+ "-n",
+ TEST_SRC + "/defaultCharset.exp",
+ TEST_CLASSES,
+ TEST_JDK + "/bin/java",
+ "-Dstdout.encoding=" + stdoutEncoding,
+ getClass().getName());
+ oa.reportDiagnosticSummary();
+ oa.shouldHaveExitValue(0);
+ }
+
+ public static void main(String... args) {
var stdoutEncoding = System.getProperty("stdout.encoding");
var sysoutCharset = System.out.charset();
var consoleCharset = System.console().charset();
- System.out.println("""
- stdout.encoding = %s
- System.out.charset() = %s
- System.console().charset() = %s
- """.formatted(stdoutEncoding, sysoutCharset.name(), consoleCharset.name()));
- assertEquals(consoleCharset, sysoutCharset,
- "Charsets for System.out and Console differ for stdout.encoding: %s".formatted(stdoutEncoding));
+ System.out.printf("""
+ stdout.encoding = %s
+ System.out.charset() = %s
+ System.console().charset() = %s
+ """, stdoutEncoding, sysoutCharset.name(), consoleCharset.name());
+ if (!consoleCharset.equals(sysoutCharset)) {
+ System.err.printf("Charsets for System.out and Console differ for stdout.encoding: %s%n", stdoutEncoding);
+ System.exit(-1);
+ }
}
}
diff --git a/test/jdk/java/io/Console/LocaleTest.java b/test/jdk/java/io/Console/LocaleTest.java
index 1cab84a9af7..e9a281749b1 100644
--- a/test/jdk/java/io/Console/LocaleTest.java
+++ b/test/jdk/java/io/Console/LocaleTest.java
@@ -21,28 +21,40 @@
* questions.
*/
-import java.io.File;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.function.Predicate;
+import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.Test;
+
+import static jdk.test.lib.Utils.*;
/**
* @test
- * @bug 8330276 8351435
+ * @bug 8330276 8351435 8361613
* @summary Tests Console methods that have Locale as an argument
+ * @requires (os.family == "linux") | (os.family == "mac")
* @library /test/lib
- * @modules jdk.internal.le jdk.localedata
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.JDKToolFinder
+ * jdk.test.lib.process.ProcessTools
+ * @modules jdk.localedata
+ * @run junit LocaleTest
*/
public class LocaleTest {
- private static Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
- private static String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
+ private static final Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
+ private static final String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
// We want to limit the expected strings within US-ASCII charset, as
// the native encoding is determined as such, which is used by
// the `Process` class under jtreg environment.
- private static List EXPECTED = List.of(
+ private static final List EXPECTED = List.of(
String.format(Locale.UK, FORMAT, TODAY),
String.format(Locale.FRANCE, FORMAT, TODAY),
String.format(Locale.GERMANY, FORMAT, TODAY),
@@ -53,56 +65,61 @@ public class LocaleTest {
String.format((Locale)null, FORMAT, TODAY)
);
- public static void main(String... args) throws Throwable {
- if (args.length == 0) {
- // no arg will launch the child process that actually perform tests
- var pb = ProcessTools.createTestJavaProcessBuilder(
- "-Djdk.console=jdk.internal.le",
- "LocaleTest", "dummy");
- var input = new File(System.getProperty("test.src", "."), "input.txt");
- pb.redirectInput(input);
- var oa = ProcessTools.executeProcess(pb);
- if (oa.getExitValue() == -1) {
- System.out.println("System.console() returns null. Ignoring the test.");
- } else {
- var output = oa.asLines();
- var resultText =
- """
- Actual output: %s
- Expected output: %s
- """.formatted(output, EXPECTED);
- if (!output.equals(EXPECTED)) {
- throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
- } else {
- oa.shouldHaveExitValue(0);
- System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
- }
- }
- } else {
- var con = System.console();
- if (con != null) {
- // tests these additional methods that take a Locale
- con.format(Locale.UK, FORMAT, TODAY);
- con.printf("\n");
- con.printf(Locale.FRANCE, FORMAT, TODAY);
- con.printf("\n");
- con.readLine(Locale.GERMANY, FORMAT, TODAY);
- con.printf("\n");
- con.readPassword(Locale.of("es"), FORMAT, TODAY);
- con.printf("\n");
+ @Test
+ void testLocale() throws Exception {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
- // tests null locale
- con.format((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.printf((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.readLine((Locale)null, FORMAT, TODAY);
- con.printf("\n");
- con.readPassword((Locale)null, FORMAT, TODAY);
- } else {
- // Exit with -1
- System.exit(-1);
- }
+ // invoking "expect" command
+ OutputAnalyzer oa = ProcessTools.executeProcess(
+ "expect",
+ "-n",
+ TEST_SRC + "/locale.exp",
+ TEST_CLASSES,
+ TEST_JDK + "/bin/java",
+ getClass().getName());
+
+ var stdout =
+ oa.stdoutAsLines().stream().filter(Predicate.not(String::isEmpty)).toList();
+ var resultText =
+ """
+ Actual output: %s
+ Expected output: %s
+ """.formatted(stdout, EXPECTED);
+ if (!stdout.equals(EXPECTED)) {
+ throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
+ } else {
+ oa.shouldHaveExitValue(0);
+ System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
+ }
+ }
+
+ public static void main(String... args) throws Throwable {
+ var con = System.console();
+ if (con != null) {
+ // tests these additional methods that take a Locale
+ con.format(Locale.UK, FORMAT, TODAY);
+ con.printf("\n");
+ con.printf(Locale.FRANCE, FORMAT, TODAY);
+ con.printf("\n");
+ con.readLine(Locale.GERMANY, FORMAT, TODAY);
+ con.printf("\n");
+ con.readPassword(Locale.of("es"), FORMAT, TODAY);
+ con.printf("\n");
+
+ // tests null locale
+ con.format((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.printf((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.readLine((Locale)null, FORMAT, TODAY);
+ con.printf("\n");
+ con.readPassword((Locale)null, FORMAT, TODAY);
+ } else {
+ // Exit with -1
+ System.exit(-1);
}
}
}
diff --git a/test/jdk/java/io/Console/ModuleSelectionTest.java b/test/jdk/java/io/Console/ModuleSelectionTest.java
index d9885699ebf..332acf83fbd 100644
--- a/test/jdk/java/io/Console/ModuleSelectionTest.java
+++ b/test/jdk/java/io/Console/ModuleSelectionTest.java
@@ -23,21 +23,71 @@
/**
* @test
- * @bug 8295803 8299689 8351435
+ * @bug 8295803 8299689 8351435 8361613
* @summary Tests System.console() returns correct Console (or null) from the expected
* module.
- * @modules java.base/java.io:+open
- * @run main/othervm ModuleSelectionTest java.base
- * @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le
- * @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base
- * @run main/othervm --limit-modules java.base ModuleSelectionTest java.base
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * jdk.test.lib.process.ProcessTools
+ * @run junit ModuleSelectionTest
*/
import java.io.Console;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static jdk.test.lib.Utils.*;
public class ModuleSelectionTest {
+ private static Stream options() {
+ return Stream.of(
+ Arguments.of("-Djdk.console=foo", "java.base"),
+ Arguments.of("-Djdk.console=java.base", "java.base"),
+ Arguments.of("-Djdk.console=jdk.internal.le", "jdk.internal.le"),
+ Arguments.of("--limit-modules java.base", "java.base")
+ );
+ }
+
+ @ParameterizedTest
+ @MethodSource("options")
+ void testNonTTY(String opts) throws Exception {
+ opts = opts +
+ " --add-opens java.base/java.io=ALL-UNNAMED ModuleSelectionTest null";
+ OutputAnalyzer output = ProcessTools.executeTestJava(opts.split(" "));
+ output.reportDiagnosticSummary();
+ output.shouldHaveExitValue(0);
+ }
+
+ @ParameterizedTest
+ @MethodSource("options")
+ void testTTY(String opts, String expected) throws Exception {
+ // check "expect" command availability
+ var expect = Paths.get("/usr/bin/expect");
+ Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
+ "'" + expect + "' not found. Test ignored.");
+
+ opts = "expect -n " + TEST_SRC + "/moduleSelection.exp " +
+ TEST_CLASSES + " " +
+ expected + " " +
+ TEST_JDK + "/bin/java" +
+ " --add-opens java.base/java.io=ALL-UNNAMED "
+ + opts;
+ // invoking "expect" command
+ OutputAnalyzer output = ProcessTools.executeProcess(opts.split(" "));
+ output.reportDiagnosticSummary();
+ output.shouldHaveExitValue(0);
+ }
+
public static void main(String... args) throws Throwable {
var con = System.console();
var pc = Class.forName("java.io.ProxyingConsole");
@@ -49,10 +99,7 @@ public class ModuleSelectionTest {
.findGetter(pc, "delegate", jdkc)
.invoke(con) : null;
- var expected = switch (args[0]) {
- case "java.base" -> istty ? "java.base" : "null";
- default -> args[0];
- };
+ var expected = args[0];
var actual = con == null ? "null" : impl.getClass().getModule().getName();
if (!actual.equals(expected)) {
@@ -62,7 +109,7 @@ public class ModuleSelectionTest {
Actual: %s
""".formatted(expected, actual));
} else {
- System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty);
+ System.out.printf("%s is the expected implementation. (tty: %s)\n", actual, istty);
}
}
}
diff --git a/test/jdk/java/io/Console/defaultCharset.exp b/test/jdk/java/io/Console/defaultCharset.exp
new file mode 100644
index 00000000000..5b1418db28c
--- /dev/null
+++ b/test/jdk/java/io/Console/defaultCharset.exp
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2025, 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.
+#
+
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set java [lrange $argv 1 1]
+set stdoutProp [lrange $argv 2 2]
+set clsname [lrange $argv 3 3]
+eval spawn $java -classpath $classpath $stdoutProp $clsname
+expect eof
+set result [wait]
+exit [lindex $result 3]
diff --git a/test/jdk/java/io/Console/locale.exp b/test/jdk/java/io/Console/locale.exp
new file mode 100644
index 00000000000..a88ea43feac
--- /dev/null
+++ b/test/jdk/java/io/Console/locale.exp
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2025, 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.
+#
+
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set java [lrange $argv 1 1]
+set clsname [lrange $argv 2 2]
+eval spawn -noecho $java -classpath $classpath $clsname
+
+# sends CR 4 times (readLine x 2, readPassword x 2)
+send "\r"
+send "\r"
+send "\r"
+send "\r"
+expect eof
+set result [wait]
+exit [lindex $result 3]
diff --git a/test/jdk/java/io/Console/moduleSelection.exp b/test/jdk/java/io/Console/moduleSelection.exp
new file mode 100644
index 00000000000..2b44afe72e4
--- /dev/null
+++ b/test/jdk/java/io/Console/moduleSelection.exp
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2025, 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.
+#
+
+# simply invoking java under expect command
+set classpath [lrange $argv 0 0]
+set expected [lrange $argv 1 1]
+set java [lrange $argv 2 2]
+set opts [lrange $argv 3 end]
+eval spawn $java $opts -classpath $classpath ModuleSelectionTest $expected
+expect eof
diff --git a/test/jdk/java/lang/IO/IO.java b/test/jdk/java/lang/IO/IO.java
index dbb83db5f80..2b13657b58e 100644
--- a/test/jdk/java/lang/IO/IO.java
+++ b/test/jdk/java/lang/IO/IO.java
@@ -50,10 +50,9 @@ import static org.junit.jupiter.api.Assertions.*;
/*
* @test
- * @bug 8305457 8342936 8351435 8344706
+ * @bug 8305457 8342936 8351435 8344706 8361613
* @summary java.lang.IO tests
* @library /test/lib
- * @modules jdk.internal.le
* @run junit IO
*/
@ExtendWith(IO.TimingExtension.class)
@@ -78,22 +77,6 @@ public class IO {
} catch (Exception _) { }
}
- /*
- * Unlike printTest, which tests a _default_ console that is normally
- * jdk.internal.org.jline.JdkConsoleProviderImpl, this test tests
- * jdk.internal.io.JdkConsoleImpl. Those console implementations operate
- * in different conditions and, thus, are tested separately.
- *
- * To test jdk.internal.io.JdkConsoleImpl one needs to ensure that both
- * conditions are met:
- *
- * - a non-existent console provider is requested
- * - isatty is true
- *
- * To achieve isatty, the test currently uses the EXPECT(1) Unix command,
- * which does not work for Windows. Later, a library like pty4j or JPty
- * might be used instead of EXPECT, to cover both Unix and Windows.
- */
@ParameterizedTest
@ValueSource(strings = {"println", "print"})
public void outputTestInteractive(String mode) throws Exception {
@@ -102,8 +85,6 @@ public class IO {
expect.toString(),
Path.of(testSrc, "output.exp").toAbsolutePath().toString(),
System.getProperty("test.jdk") + "/bin/java",
- "--enable-preview",
- "-Djdk.console=gibberish",
Path.of(testSrc, "Output.java").toAbsolutePath().toString(),
mode);
assertEquals(0, output.getExitValue());
@@ -130,7 +111,7 @@ public class IO {
*/
@ParameterizedTest
@MethodSource("args")
- public void inputTestInteractive(String console, String prompt) throws Exception {
+ public void inputTestInteractive(String prompt) throws Exception {
var testSrc = System.getProperty("test.src", ".");
var command = new ArrayList();
command.add(expect.toString());
@@ -138,9 +119,6 @@ public class IO {
: "input";
command.add(Path.of(testSrc, expectInputName + ".exp").toAbsolutePath().toString());
command.add(System.getProperty("test.jdk") + "/bin/java");
- command.add("--enable-preview");
- if (console != null)
- command.add("-Djdk.console=" + console);
command.add(Path.of(testSrc, "Input.java").toAbsolutePath().toString());
command.add(prompt == null ? "0" : PROMPT_NONE.equals(prompt) ? "2" : "1");
command.add(String.valueOf(prompt));
@@ -152,33 +130,11 @@ public class IO {
private static final String PROMPT_NONE = "prompt-none";
public static Stream args() {
- // cross product: consoles x prompts
- return Stream.of("jdk.internal.le", "gibberish").flatMap(console -> Stream.of(null, "?", "%s", PROMPT_NONE)
- .map(prompt -> new String[]{console, prompt}).map(Arguments::of));
+ // prompts
+ return Stream.of(null, "?", "%s", PROMPT_NONE).map(Arguments::of);
}
}
- @ParameterizedTest
- @ValueSource(strings = {"println", "print"})
- public void printTest(String mode) throws Exception {
- var file = Path.of(System.getProperty("test.src", "."), "Output.java")
- .toAbsolutePath().toString();
- var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file, mode);
- OutputAnalyzer output = ProcessTools.executeProcess(pb);
- assertEquals(0, output.getExitValue());
- assertTrue(output.getStderr().isEmpty());
- output.reportDiagnosticSummary();
- String out = output.getStdout();
- // The first half of the output is produced by Console, the second
- // half is produced by IO: those halves must match.
- // Executing Console and IO in the same VM (as opposed to
- // consecutive VM runs, which are cleaner) to be able to compare string
- // representation of objects.
- assertFalse(out.isBlank());
- assertEquals(out.substring(0, out.length() / 2),
- out.substring(out.length() / 2));
- }
-
@Test //JDK-8342936
public void printlnNoParamsTest() throws Exception {
var file = Path.of("PrintlnNoParams.java");
@@ -193,7 +149,7 @@ public class IO {
}
""");
}
- var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file.toString());
+ var pb = ProcessTools.createTestJavaProcessBuilder(file.toString());
OutputAnalyzer output = ProcessTools.executeProcess(pb);
assertEquals(0, output.getExitValue());
assertTrue(output.getStderr().isEmpty());
diff --git a/test/jdk/java/lang/Thread/virtual/JfrEvents.java b/test/jdk/java/lang/Thread/virtual/JfrEvents.java
index 0b0c2ccc7a0..0c967811481 100644
--- a/test/jdk/java/lang/Thread/virtual/JfrEvents.java
+++ b/test/jdk/java/lang/Thread/virtual/JfrEvents.java
@@ -42,6 +42,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import java.util.stream.Stream;
import jdk.jfr.EventType;
@@ -77,12 +78,13 @@ class JfrEvents {
// execute 100 tasks, each in their own virtual thread
recording.start();
- ThreadFactory factory = Thread.ofVirtual().factory();
- try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
- for (int i = 0; i < 100; i++) {
- executor.submit(() -> { });
+ try {
+ List threads = IntStream.range(0, 100)
+ .mapToObj(_ -> Thread.startVirtualThread(() -> { }))
+ .toList();
+ for (Thread t : threads) {
+ t.join();
}
- Thread.sleep(1000); // give time for thread end events to be recorded
} finally {
recording.stop();
}
diff --git a/test/jdk/java/net/httpclient/ManyRequests.java b/test/jdk/java/net/httpclient/ManyRequests.java
index 5d698d60ee5..493c2c3a504 100644
--- a/test/jdk/java/net/httpclient/ManyRequests.java
+++ b/test/jdk/java/net/httpclient/ManyRequests.java
@@ -24,6 +24,7 @@
/*
* @test
* @bug 8087112 8180044 8256459
+ * @key intermittent
* @modules java.net.http
* java.logging
* jdk.httpserver
diff --git a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java
index 7ff02cdfea4..1cdd090d1be 100644
--- a/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java
+++ b/test/jdk/java/nio/channels/vthread/BlockingChannelOps.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, 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
@@ -21,7 +21,7 @@
* questions.
*/
-/**
+/*
* @test id=default
* @bug 8284161
* @summary Test virtual threads doing blocking I/O on NIO channels
@@ -29,7 +29,7 @@
* @run junit BlockingChannelOps
*/
-/**
+/*
* @test id=poller-modes
* @requires (os.family == "linux") | (os.family == "mac")
* @library /test/lib
@@ -37,7 +37,7 @@
* @run junit/othervm -Djdk.pollerMode=2 BlockingChannelOps
*/
-/**
+/*
* @test id=no-vmcontinuations
* @requires vm.continuations
* @library /test/lib
@@ -62,6 +62,7 @@ import java.nio.channels.ReadableByteChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.WritableByteChannel;
+import java.util.concurrent.locks.LockSupport;
import jdk.test.lib.thread.VThreadRunner;
import org.junit.jupiter.api.Test;
@@ -161,6 +162,22 @@ class BlockingChannelOps {
});
}
+ /**
+ * SocketChannel shutdownInput while virtual thread blocked in read.
+ */
+ @Test
+ void testSocketChannelReadAsyncShutdownInput() throws Exception {
+ VThreadRunner.run(() -> {
+ try (var connection = new Connection()) {
+ SocketChannel sc = connection.channel1();
+ runAfterParkedAsync(sc::shutdownInput);
+ int n = sc.read(ByteBuffer.allocate(100));
+ assertEquals(-1, n);
+ assertTrue(sc.isOpen());
+ }
+ });
+ }
+
/**
* Virtual thread interrupted while blocked in SocketChannel read.
*/
@@ -190,13 +207,15 @@ class BlockingChannelOps {
@Test
void testSocketChannelWriteAsyncClose() throws Exception {
VThreadRunner.run(() -> {
- boolean retry = true;
- while (retry) {
+ boolean done = false;
+ while (!done) {
try (var connection = new Connection()) {
SocketChannel sc = connection.channel1();
// close sc when current thread blocks in write
- runAfterParkedAsync(sc::close);
+ runAfterParkedAsync(sc::close, true);
+
+ // write until channel is closed
try {
ByteBuffer bb = ByteBuffer.allocate(100*1024);
for (;;) {
@@ -206,30 +225,59 @@ class BlockingChannelOps {
}
} catch (AsynchronousCloseException expected) {
// closed when blocked in write
- retry = false;
+ done = true;
} catch (ClosedChannelException e) {
- // closed when not blocked in write, need to retry test
+ // closed but not blocked in write, need to retry test
+ System.err.format("%s, need to retry!%n", e);
}
}
}
});
}
+
+ /**
+ * SocketChannel shutdownOutput while virtual thread blocked in write.
+ */
+ @Test
+ void testSocketChannelWriteAsyncShutdownOutput() throws Exception {
+ VThreadRunner.run(() -> {
+ try (var connection = new Connection()) {
+ SocketChannel sc = connection.channel1();
+
+ // shutdown output when current thread blocks in write
+ runAfterParkedAsync(sc::shutdownOutput);
+ try {
+ ByteBuffer bb = ByteBuffer.allocate(100*1024);
+ for (;;) {
+ int n = sc.write(bb);
+ assertTrue(n > 0);
+ bb.clear();
+ }
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ assertTrue(sc.isOpen());
+ }
+ });
+ }
+
/**
* Virtual thread interrupted while blocked in SocketChannel write.
*/
@Test
void testSocketChannelWriteInterrupt() throws Exception {
VThreadRunner.run(() -> {
- boolean retry = true;
- while (retry) {
+ boolean done = false;
+ while (!done) {
try (var connection = new Connection()) {
SocketChannel sc = connection.channel1();
// interrupt current thread when it blocks in write
Thread thisThread = Thread.currentThread();
- runAfterParkedAsync(thisThread::interrupt);
+ runAfterParkedAsync(thisThread::interrupt, true);
+ // write until channel is closed
try {
ByteBuffer bb = ByteBuffer.allocate(100*1024);
for (;;) {
@@ -240,9 +288,10 @@ class BlockingChannelOps {
} catch (ClosedByInterruptException e) {
// closed when blocked in write
assertTrue(Thread.interrupted());
- retry = false;
+ done = true;
} catch (ClosedChannelException e) {
- // closed when not blocked in write, need to retry test
+ // closed but not blocked in write, need to retry test
+ System.err.format("%s, need to retry!%n", e);
}
}
}
@@ -734,14 +783,16 @@ class BlockingChannelOps {
@Test
void testPipeWriteAsyncClose() throws Exception {
VThreadRunner.run(() -> {
- boolean retry = true;
- while (retry) {
+ boolean done = false;
+ while (!done) {
Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink();
Pipe.SourceChannel source = p.source()) {
// close sink when current thread blocks in write
- runAfterParkedAsync(sink::close);
+ runAfterParkedAsync(sink::close, true);
+
+ // write until channel is closed
try {
ByteBuffer bb = ByteBuffer.allocate(100*1024);
for (;;) {
@@ -751,9 +802,10 @@ class BlockingChannelOps {
}
} catch (AsynchronousCloseException e) {
// closed when blocked in write
- retry = false;
+ done = true;
} catch (ClosedChannelException e) {
- // closed when not blocked in write, need to retry test
+ // closed but not blocked in write, need to retry test
+ System.err.format("%s, need to retry!%n", e);
}
}
}
@@ -766,16 +818,17 @@ class BlockingChannelOps {
@Test
void testPipeWriteInterrupt() throws Exception {
VThreadRunner.run(() -> {
- boolean retry = true;
- while (retry) {
+ boolean done = false;
+ while (!done) {
Pipe p = Pipe.open();
try (Pipe.SinkChannel sink = p.sink();
Pipe.SourceChannel source = p.source()) {
// interrupt current thread when it blocks in write
Thread thisThread = Thread.currentThread();
- runAfterParkedAsync(thisThread::interrupt);
+ runAfterParkedAsync(thisThread::interrupt, true);
+ // write until channel is closed
try {
ByteBuffer bb = ByteBuffer.allocate(100*1024);
for (;;) {
@@ -786,9 +839,10 @@ class BlockingChannelOps {
} catch (ClosedByInterruptException expected) {
// closed when blocked in write
assertTrue(Thread.interrupted());
- retry = false;
+ done = true;
} catch (ClosedChannelException e) {
- // closed when not blocked in write, need to retry test
+ // closed but not blocked in write, need to retry test
+ System.err.format("%s, need to retry!%n", e);
}
}
}
@@ -848,26 +902,50 @@ class BlockingChannelOps {
}
/**
- * Runs the given task asynchronously after the current virtual thread has parked.
+ * Runs the given task asynchronously after the current virtual thread parks.
+ * @param writing if the thread will block in write
* @return the thread started to run the task
*/
- static Thread runAfterParkedAsync(ThrowingRunnable task) {
+ private static Thread runAfterParkedAsync(ThrowingRunnable task, boolean writing) {
Thread target = Thread.currentThread();
if (!target.isVirtual())
throw new WrongThreadException();
return Thread.ofPlatform().daemon().start(() -> {
try {
- Thread.State state = target.getState();
- while (state != Thread.State.WAITING
- && state != Thread.State.TIMED_WAITING) {
+ // wait for target thread to park
+ while (!isWaiting(target)) {
Thread.sleep(20);
- state = target.getState();
}
- Thread.sleep(20); // give a bit more time to release carrier
+
+ // if the target thread is parked in write then we nudge it a few times
+ // to avoid wakeup with some bytes written
+ if (writing) {
+ for (int i = 0; i < 3; i++) {
+ LockSupport.unpark(target);
+ while (!isWaiting(target)) {
+ Thread.sleep(20);
+ }
+ }
+ }
+
task.run();
+
} catch (Exception e) {
e.printStackTrace();
}
});
}
+
+ private static Thread runAfterParkedAsync(ThrowingRunnable task) {
+ return runAfterParkedAsync(task, false);
+ }
+
+ /**
+ * Return true if the given Thread is parked.
+ */
+ private static boolean isWaiting(Thread target) {
+ Thread.State state = target.getState();
+ assertNotEquals(Thread.State.TERMINATED, state);
+ return (state == Thread.State.WAITING || state == Thread.State.TIMED_WAITING);
+ }
}
diff --git a/test/jdk/java/nio/file/Files/IsSameFile.java b/test/jdk/java/nio/file/Files/IsSameFile.java
new file mode 100644
index 00000000000..00bac0fb5a7
--- /dev/null
+++ b/test/jdk/java/nio/file/Files/IsSameFile.java
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8154364
+ * @summary Test of Files.isSameFile
+ * @requires (os.family != "windows")
+ * @library .. /test/lib
+ * @build IsSameFile jdk.test.lib.util.FileUtils
+ * @run junit IsSameFile
+ */
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.nio.file.Files;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystemException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import jdk.test.lib.util.FileUtils;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@TestInstance(Lifecycle.PER_CLASS)
+public class IsSameFile {
+ private Path home;
+ private Path a;
+ private Path aa;
+ private Path b;
+ private Path c;
+ private List allFiles;
+
+ @BeforeAll
+ public void init() throws IOException {
+ home = Files.createTempDirectory("TestIsSameFile");
+
+ allFiles = new ArrayList();
+ allFiles.add(a = home.resolve("a"));
+ allFiles.add(aa = home.resolve("a"));
+ allFiles.add(b = home.resolve("b"));
+ allFiles.add(c = home.resolve("c"));
+ }
+
+ public void deleteFiles() throws IOException {
+ for (Path p : allFiles)
+ Files.deleteIfExists(p);
+ }
+
+ @AfterAll
+ public void deleteHome() throws IOException {
+ TestUtil.removeAll(home);
+ }
+
+ public void test(boolean expect, Path x, Path y) throws IOException {
+ assertTrue(Files.isSameFile(x, y) == expect);
+ }
+
+ private Stream stringCompareSource() throws IOException {
+ deleteFiles();
+ List list = new ArrayList();
+ Path x = Path.of("x/y/z");
+ list.add(Arguments.of(true, x, x));
+ list.add(Arguments.of(false, Path.of("w/x/y/z"), x));
+ Path y = Path.of("v/w/x/../y/z");
+ list.add(Arguments.of(false, y, Path.of("v/w/y/z")));
+ list.add(Arguments.of(false, y, Path.of("v/w/x/y/../z")));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("stringCompareSource")
+ public void stringCompare(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ private Stream noneExistSource() throws IOException {
+ deleteFiles();
+ List list = new ArrayList();
+ list.add(Arguments.of(true, a, a));
+ list.add(Arguments.of(true, a, aa));
+ list.add(Arguments.of(false, a, b));
+ list.add(Arguments.of(true, b, b));
+ return list.stream();
+ }
+
+ @Test
+ public void obj2Null() {
+ Path x = Path.of("x/y");
+ assertThrows(NullPointerException.class, () -> Files.isSameFile(x, null));
+ }
+
+ private static void zipStringToFile(String entry, String content,
+ Path path)
+ throws IOException
+ {
+ FileOutputStream fos = new FileOutputStream(path.toString());
+ ZipOutputStream zos = new ZipOutputStream(fos);
+
+ ZipEntry zipEntry = new ZipEntry(entry);
+ zos.putNextEntry(zipEntry);
+ zos.write(content.getBytes());
+
+ zos.close();
+ fos.close();
+ }
+
+ private Stream obj2ZipSource() throws IOException {
+ deleteFiles();
+ Files.createFile(a);
+ zipStringToFile("quote.txt", "To be determined", b);
+ FileSystem zipfs = FileSystems.newFileSystem(b);
+ List list = new ArrayList();
+ list.add(Arguments.of(false, a, zipfs.getPath(b.toString())));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("obj2ZipSource")
+ public void obj2Zip(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ @ParameterizedTest
+ @MethodSource("noneExistSource")
+ public void noneExist(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ private Stream aExistsSource() throws IOException {
+ deleteFiles();
+ Files.createFile(a);
+ List list = new ArrayList();
+ list.add(Arguments.of(true, a, a));
+ list.add(Arguments.of(true, a, aa));
+ list.add(Arguments.of(false, a, b));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("aExistsSource")
+ public void aExists(boolean expect, Path x, Path y) throws IOException {
+ test(expect, x, y);
+ }
+
+ private Stream abExistSource() throws IOException {
+ deleteFiles();
+ Files.createFile(a);
+ Files.createFile(b);
+ List list = new ArrayList();
+ list.add(Arguments.of(false, a, b));
+ list.add(Arguments.of(true, b, b));
+ list.add(Arguments.of(false, a, c));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("abExistSource")
+ public void abExist(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ private Stream abcExistSource() throws IOException {
+ deleteFiles();
+ Files.createFile(a);
+ Files.createFile(b);
+ Files.createSymbolicLink(c, a);
+ List list = new ArrayList();
+ list.add(Arguments.of(true, a, c));
+ list.add(Arguments.of(false, a, b));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("abcExistSource")
+ public void abcExist(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ private Stream bcExistSource() throws IOException {
+ deleteFiles();
+ Files.createFile(b);
+ Files.createSymbolicLink(c, a);
+ List list = new ArrayList();
+ list.add(Arguments.of(true, a, a));
+ list.add(Arguments.of(true, a, aa));
+ list.add(Arguments.of(false, a, b));
+ list.add(Arguments.of(true, b, b));
+ list.add(Arguments.of(false, a, c));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("bcExistSource")
+ public void bcExist(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 => L2 => target
+ // L3 => L4 => target
+ //
+ private Stream equalFollowingSource() throws IOException {
+ deleteFiles();
+ Path target = home.resolve("target");
+ Files.createFile(target);
+ allFiles.add(target);
+
+ Path L2 = Path.of("link2");
+ Files.createSymbolicLink(L2, target);
+ allFiles.add(L2);
+
+ Path L1 = Path.of("link1");
+ Files.createSymbolicLink(L1, L2);
+ allFiles.add(L1);
+
+ Path L4 = Path.of("link4");
+ Files.createSymbolicLink(L4, target);
+ allFiles.add(L4);
+
+ Path L3 = Path.of("link3");
+ Files.createSymbolicLink(L3, L4);
+ allFiles.add(L3);
+
+ List list = new ArrayList();
+ list.add(Arguments.of(true, L1, L3));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("equalFollowingSource")
+ public void equalFollowing(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 => L2 => target
+ // L3 => L4 => cible
+ //
+ private Stream unequalFollowingSource() throws IOException {
+ deleteFiles();
+ Path target = home.resolve("target");
+ Files.createFile(target);
+ allFiles.add(target);
+
+ Path L2 = Path.of("link2");
+ Files.createSymbolicLink(L2, target);
+ allFiles.add(L2);
+
+ Path L1 = Path.of("link1");
+ Files.createSymbolicLink(L1, L2);
+ allFiles.add(L1);
+
+ Path cible = home.resolve("cible");
+ Files.createFile(cible);
+ allFiles.add(cible);
+
+ Path L4 = Path.of("link4");
+ Files.createSymbolicLink(L4, cible);
+ allFiles.add(L4);
+
+ Path L3 = Path.of("link3");
+ Files.createSymbolicLink(L3, L4);
+ allFiles.add(L3);
+
+ List list = new ArrayList();
+ list.add(Arguments.of(false, L1, L3));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("unequalFollowingSource")
+ public void unequalFollowing(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 => L2 =>
+ // L3 => L4 =>
+ //
+ private Stream unequalNotFollowingSource() throws IOException {
+ deleteFiles();
+
+ Path doesNotExist = Path.of("doesNotExist");
+
+ Path L2 = Path.of("link2");
+ Files.createSymbolicLink(L2, doesNotExist);
+ allFiles.add(L2);
+
+ Path L1 = Path.of("link1");
+ Files.createSymbolicLink(L1, L2);
+ allFiles.add(L1);
+
+ Path L4 = Path.of("link4");
+ Files.createSymbolicLink(L4, doesNotExist);
+ allFiles.add(L4);
+
+ Path L3 = Path.of("link3");
+ Files.createSymbolicLink(L3, L4);
+ allFiles.add(L3);
+
+ List list = new ArrayList();
+ list.add(Arguments.of(false, L1, L3));
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("unequalNotFollowingSource")
+ public void unequalNotFollowing(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 => L2 => L3 => L4 => target
+ //
+ // isSameFile(LX,LY) should be true for all X, Y
+ //
+ private Stream multiLinkSource() throws IOException {
+ deleteFiles();
+ Path target = home.resolve("target");
+ Files.createFile(target);
+ allFiles.add(target);
+ Path[] links = new Path[4];
+ links[3] = Files.createSymbolicLink(Path.of("link4"), target);
+ allFiles.add(links[3]);
+ for (int i = 3; i > 0; i--) {
+ links[i-1] = Files.createSymbolicLink(Path.of("link"+i), links[i]);
+ allFiles.add(links[i-1]);
+ }
+
+ List list = new ArrayList();
+ for (int i = 0; i < 4; i++) {
+ list.add(Arguments.of(true, links[i], target));
+ for (int j = i+1; j < 4; j++)
+ list.add(Arguments.of(true, links[i], links[j]));
+ }
+
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("multiLinkSource")
+ public void multiLink(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 => L2 => L3 => L4 =>
+ //
+ // isSameFile(LX,LY) should be true for all X, Y
+ //
+ private Stream multiLinkNoTargetSource() throws IOException {
+ deleteFiles();
+ Path target = home.resolve("target");
+ Files.createFile(target);
+ allFiles.add(target);
+ Path[] links = new Path[4];
+ links[3] = Files.createSymbolicLink(Path.of("link4"), target);
+ allFiles.add(links[3]);
+ Files.delete(target);
+ allFiles.remove(target);
+ for (int i = 3; i > 0; i--) {
+ links[i-1] = Files.createSymbolicLink(Path.of("link"+i), links[i]);
+ allFiles.add(links[i-1]);
+ }
+
+ List list = new ArrayList();
+ for (int i = 0; i < 4; i++) {
+ list.add(Arguments.of(false, links[i], target));
+ for (int j = i+1; j < 4; j++)
+ list.add(Arguments.of(true, links[i], links[j]));
+ }
+
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("multiLinkNoTargetSource")
+ public void multiLinkNoTarget(boolean expect, Path x, Path y)
+ throws IOException {
+ test(expect, x, y);
+ }
+
+ //
+ // L1 -> L2 -> L3 -> L1...
+ //
+ // This is a loop and should throw FileSystemException.
+ //
+ private Stream linkLoopSource() throws IOException {
+ deleteFiles();
+
+ Path link1 = home.resolve("L1");
+ Path link2 = home.resolve("L2");
+ Path link3 = home.resolve("L3");
+ allFiles.add(Files.createSymbolicLink(link1, link2));
+ allFiles.add(Files.createSymbolicLink(link2, link3));
+ allFiles.add(Files.createSymbolicLink(link3, link1));
+
+ List list = new ArrayList();
+ list.add(Arguments.of(true, link1, link2));
+ list.add(Arguments.of(true, link2, link3));
+ list.add(Arguments.of(true, link3, link1));
+
+ return list.stream();
+ }
+
+ @ParameterizedTest
+ @MethodSource("linkLoopSource")
+ public void linkLoop(boolean expect, Path x, Path y) throws IOException {
+ assertThrows(FileSystemException.class, () -> Files.isSameFile(x, y));
+ }
+}
diff --git a/test/jdk/java/nio/file/Files/Misc.java b/test/jdk/java/nio/file/Files/Misc.java
index 024b518141b..9ec8d7c252e 100644
--- a/test/jdk/java/nio/file/Files/Misc.java
+++ b/test/jdk/java/nio/file/Files/Misc.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2025, 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
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333 8005566 8215467 8255576 8286160
+ * @bug 4313887 6838333 8005566 8154364 8215467 8255576 8286160
* @summary Unit test for miscellaneous methods in java.nio.file.Files
* @library .. /test/lib
* @build jdk.test.lib.Platform
@@ -113,34 +113,18 @@ public class Misc {
assertTrue(isSameFile(thisFile, thisFile));
/**
- * Test: Neither files exist
+ * Test: Neither file exists
*/
- try {
- isSameFile(thisFile, thatFile);
- throw new RuntimeException("IOException not thrown");
- } catch (IOException x) {
- }
- try {
- isSameFile(thatFile, thisFile);
- throw new RuntimeException("IOException not thrown");
- } catch (IOException x) {
- }
+ assertTrue(!isSameFile(thisFile, thatFile));
+ assertTrue(!isSameFile(thatFile, thisFile));
createFile(thisFile);
try {
/**
* Test: One file exists
*/
- try {
- isSameFile(thisFile, thatFile);
- throw new RuntimeException("IOException not thrown");
- } catch (IOException x) {
- }
- try {
- isSameFile(thatFile, thisFile);
- throw new RuntimeException("IOException not thrown");
- } catch (IOException x) {
- }
+ assertTrue(!isSameFile(thisFile, thatFile));
+ assertTrue(!isSameFile(thatFile, thisFile));
/**
* Test: Both file exists
diff --git a/test/jdk/javax/imageio/FlushTest.java b/test/jdk/javax/imageio/FlushTest.java
new file mode 100644
index 00000000000..e342880e65f
--- /dev/null
+++ b/test/jdk/javax/imageio/FlushTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8364768
+ * @summary Tests that the standard plugins flush the stream after writing a complete image.
+ */
+
+import static java.awt.Color.WHITE;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.FileCacheImageOutputStream;
+
+public class FlushTest {
+
+ static final int SZ = 1000;
+ static BufferedImage bi;
+ static final String[] FORMATS = { "jpg", "png", "gif", "tiff", "bmp", "wbmp" } ;
+ static boolean failed = false;
+
+ public static void main(String[] args) throws IOException {
+
+ bi = new BufferedImage(SZ, SZ, BufferedImage.TYPE_BYTE_BINARY);
+ Graphics2D g2d = bi.createGraphics();
+ g2d.setPaint(WHITE);
+ g2d.fillRect(0, 0, SZ, SZ);
+
+ for (String f : FORMATS) {
+ testWrite(f);
+ }
+ if (failed) {
+ throw new RuntimeException("Stream sizes differ.");
+ }
+ }
+
+ static void testWrite(String fmt) throws IOException {
+ ImageWriter iw = ImageIO.getImageWritersBySuffix(fmt).next();
+ System.out.println(iw);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ FileCacheImageOutputStream fcs = new FileCacheImageOutputStream(baos, null);
+ iw.setOutput(fcs);
+ iw.write(bi);
+ int sz0 = baos.size();
+ fcs.close();
+ int sz1 = baos.size();
+ System.out.println("fmt=" + fmt + " sizes=" + sz0 + ", " + sz1);
+ if (sz0 != sz1) {
+ failed = true;
+ }
+ }
+}
diff --git a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java
index 81f5e0d0802..7c3732925be 100644
--- a/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java
+++ b/test/jdk/javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2025, 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
@@ -21,6 +21,7 @@
* questions.
*/
+import java.io.File;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Point;
@@ -28,6 +29,7 @@ import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
+import javax.imageio.ImageIO;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
@@ -51,6 +53,7 @@ public class JInternalFrameDraggingTest {
private static JInternalFrame internalFrame;
private static int FRAME_SIZE = 500;
private static Color BACKGROUND_COLOR = Color.ORANGE;
+ private static final int tolerance = 10;
public static void main(String[] args) throws Exception {
try {
@@ -69,14 +72,24 @@ public class JInternalFrameDraggingTest {
BufferedImage img = robot.createScreenCapture(rect);
int testRGB = BACKGROUND_COLOR.getRGB();
+ Color testColor = new Color(testRGB);
for (int i = 1; i < size; i++) {
int rgbCW = img.getRGB(i, size / 2);
int rgbCH = img.getRGB(size / 2, i);
- if (rgbCW != testRGB || rgbCH != testRGB) {
+ Color rgbCWColor = new Color(rgbCW);
+ Color rgbCHColor = new Color(rgbCH);
+
+ if (Math.abs(rgbCWColor.getRed() - testColor.getRed()) > tolerance
+ || Math.abs(rgbCWColor.getGreen() - testColor.getGreen()) > tolerance
+ || Math.abs(rgbCWColor.getBlue() - testColor.getBlue()) > tolerance
+ || Math.abs(rgbCHColor.getRed() - testColor.getRed()) > tolerance
+ || Math.abs(rgbCHColor.getGreen() - testColor.getGreen()) > tolerance
+ || Math.abs(rgbCHColor.getBlue() - testColor.getBlue()) > tolerance) {
System.out.println("i " + i + " rgbCW " +
Integer.toHexString(rgbCW) +
" testRGB " + Integer.toHexString(testRGB) +
" rgbCH " + Integer.toHexString(rgbCH));
+ ImageIO.write(img, "png", new File("JInternalFrameDraggingTest.png"));
throw new RuntimeException("Background color is wrong!");
}
}
diff --git a/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java
index 71590040685..445da167c5f 100644
--- a/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java
+++ b/test/jdk/jdk/internal/jline/JLineConsoleProviderTest.java
@@ -23,16 +23,19 @@
/**
* @test
- * @bug 8331535 8351435 8347050
+ * @bug 8331535 8351435 8347050 8361613
* @summary Verify the jdk.internal.le's console provider works properly.
- * @modules jdk.internal.le
+ * @modules java.base/jdk.internal.io
+ * jdk.internal.le/jdk.internal.org.jline
* @library /test/lib
- * @run main/othervm -Djdk.console=jdk.internal.le JLineConsoleProviderTest
+ * @run main JLineConsoleProviderTest
*/
import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
import java.util.Objects;
+import jdk.internal.org.jline.JdkConsoleProviderImpl;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
@@ -66,8 +69,13 @@ public class JLineConsoleProviderTest {
String input,
String expectedOut) throws Exception {
ProcessBuilder builder =
- ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName(),
- testName);
+ ProcessTools.createTestJavaProcessBuilder(
+ "--add-exports",
+ "java.base/jdk.internal.io=ALL-UNNAMED",
+ "--add-exports",
+ "jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED",
+ ConsoleTest.class.getName(),
+ testName);
OutputAnalyzer output = ProcessTools.executeProcess(builder, input);
output.waitFor();
@@ -98,16 +106,18 @@ public class JLineConsoleProviderTest {
public static class ConsoleTest {
public static void main(String... args) {
+ // directly instantiate JLine JdkConsole, simulating isTTY=true
+ var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8);
switch (args[0]) {
case "testCorrectOutputReadLine" ->
- System.console().readLine("%%s");
+ impl.readLine(null, "%%s");
case "testCorrectOutputReadPassword" ->
- System.console().readPassword("%%s");
+ impl.readPassword(null, "%%s");
case "readAndPrint" ->
- System.out.println("'" + System.console().readLine() + "'");
+ System.out.println("'" + impl.readLine() + "'");
case "readAndPrint2" -> {
- System.out.println("1: '" +System.console().readLine() + "'");
- System.out.println("2: '" + System.console().readLine() + "'");
+ System.out.println("1: '" + impl.readLine() + "'");
+ System.out.println("2: '" + impl.readLine() + "'");
}
default -> throw new UnsupportedOperationException(args[0]);
}
diff --git a/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java b/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java
index acf0c848b43..a7533796b7c 100644
--- a/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java
+++ b/test/jdk/jdk/internal/jline/LazyJdkConsoleProvider.java
@@ -23,15 +23,19 @@
/**
* @test
- * @bug 8333086 8344706
+ * @bug 8333086 8344706 8361613
* @summary Verify the JLine backend is not initialized for simple printing.
- * @enablePreview
- * @modules jdk.internal.le/jdk.internal.org.jline.reader
+ * @modules java.base/jdk.internal.io
+ * jdk.internal.le/jdk.internal.org.jline
+ * jdk.internal.le/jdk.internal.org.jline.reader
* jdk.internal.le/jdk.internal.org.jline.terminal
* @library /test/lib
* @run main LazyJdkConsoleProvider
*/
+import java.nio.charset.StandardCharsets;
+
+import jdk.internal.org.jline.JdkConsoleProviderImpl;
import jdk.internal.org.jline.reader.LineReader;
import jdk.internal.org.jline.terminal.Terminal;
@@ -41,19 +45,18 @@ import jdk.test.lib.process.ProcessTools;
public class LazyJdkConsoleProvider {
public static void main(String... args) throws Throwable {
+ // directly instantiate JLine JdkConsole, simulating isTTY=true
switch (args.length > 0 ? args[0] : "default") {
case "write" -> {
- System.console().printf("Hello!\n");
- System.console().printf("Hello!");
- System.console().format("\nHello!\n");
- System.console().flush();
- IO.println("Hello!");
- IO.print("Hello!");
- }
- case "read" -> System.console().readLine("Hello!");
- case "IO-read" -> {
- IO.readln("Hello!");
+ var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8);
+ impl.println("Hello!\n");
+ impl.println("Hello!");
+ impl.format(null, "\nHello!\n");
+ impl.flush();
}
+ case "read" -> new JdkConsoleProviderImpl()
+ .console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8)
+ .readLine(null, "Hello!");
case "default" -> {
new LazyJdkConsoleProvider().runTest();
}
@@ -64,14 +67,15 @@ public class LazyJdkConsoleProvider {
record TestCase(String testKey, String expected, String notExpected) {}
TestCase[] testCases = new TestCase[] {
new TestCase("write", null, Terminal.class.getName()),
- new TestCase("read", LineReader.class.getName(), null),
- new TestCase("IO-read", null, Terminal.class.getName())
+ new TestCase("read", LineReader.class.getName(), null)
};
for (TestCase tc : testCases) {
ProcessBuilder builder =
- ProcessTools.createTestJavaProcessBuilder("--enable-preview",
- "-verbose:class",
- "-Djdk.console=jdk.internal.le",
+ ProcessTools.createTestJavaProcessBuilder("-verbose:class",
+ "--add-exports",
+ "java.base/jdk.internal.io=ALL-UNNAMED",
+ "--add-exports",
+ "jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED",
LazyJdkConsoleProvider.class.getName(),
tc.testKey());
OutputAnalyzer output = ProcessTools.executeProcess(builder, "");
diff --git a/test/jdk/jdk/internal/jline/RedirectedStdOut.java b/test/jdk/jdk/internal/jline/RedirectedStdOut.java
deleted file mode 100644
index 71419f96c73..00000000000
--- a/test/jdk/jdk/internal/jline/RedirectedStdOut.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @bug 8330998 8351435
- * @summary Verify that even if the stdout is redirected java.io.Console will
- * use it for writing.
- * @modules jdk.internal.le
- * @library /test/lib
- * @run main RedirectedStdOut runRedirectAllTest
- * @run main/othervm --enable-native-access=ALL-UNNAMED RedirectedStdOut runRedirectOutOnly
- */
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.lang.foreign.Arena;
-import java.lang.foreign.FunctionDescriptor;
-import java.lang.foreign.Linker;
-import java.lang.foreign.MemorySegment;
-import java.lang.foreign.SymbolLookup;
-import java.lang.foreign.ValueLayout;
-import java.lang.invoke.MethodHandle;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.Optional;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class RedirectedStdOut {
- private static final String OUTPUT = "Hello!";
-
- public static void main(String... args) throws Throwable {
- RedirectedStdOut.class.getDeclaredMethod(args[0])
- .invoke(new RedirectedStdOut());
- }
-
- //verify the case where neither stdin/out/err is attached to a terminal,
- //this test is weaker, but more reliable:
- void runRedirectAllTest() throws Exception {
- ProcessBuilder builder =
- ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName());
- OutputAnalyzer output = ProcessTools.executeProcess(builder);
-
- output.waitFor();
-
- if (output.getExitValue() != 0) {
- throw new AssertionError("Unexpected return value: " + output.getExitValue() +
- ", actualOut: " + output.getStdout() +
- ", actualErr: " + output.getStderr());
- }
-
- String expectedOut = OUTPUT;
- String actualOut = output.getStdout();
-
- if (!Objects.equals(expectedOut, actualOut)) {
- throw new AssertionError("Unexpected stdout content. " +
- "Expected: '" + expectedOut + "'" +
- ", got: '" + actualOut + "'");
- }
-
- String expectedErr = "";
- String actualErr = output.getStderr();
-
- if (!Objects.equals(expectedErr, actualErr)) {
- throw new AssertionError("Unexpected stderr content. " +
- "Expected: '" + expectedErr + "'" +
- ", got: '" + actualErr + "'");
- }
- }
-
- //verify the case where stdin is attached to a terminal,
- //this test allocates pty, and it might be skipped, if the appropriate
- //native functions cannot be found
- //it also leaves the VM in a broken state (with a pty attached), and so
- //should run in a separate VM instance
- void runRedirectOutOnly() throws Throwable {
- Path stdout = Path.of(".", "stdout.txt").toAbsolutePath();
-
- Files.deleteIfExists(stdout);
-
- Linker linker = Linker.nativeLinker();
- SymbolLookup stdlib = linker.defaultLookup();
- MemorySegment parent = Arena.global().allocate(ValueLayout.ADDRESS);
- MemorySegment child = Arena.global().allocate(ValueLayout.ADDRESS);
- Optional openptyAddress = stdlib.find("openpty");
-
- if (openptyAddress.isEmpty()) {
- System.out.println("Cannot lookup openpty.");
- //does not have forkpty, ignore
- return ;
- }
-
- Optional loginttyAddress = stdlib.find("login_tty");
-
- if (loginttyAddress.isEmpty()) {
- System.out.println("Cannot lookup login_tty.");
- //does not have forkpty, ignore
- return ;
- }
-
- FunctionDescriptor openttyDescriptor =
- FunctionDescriptor.of(ValueLayout.JAVA_INT,
- ValueLayout.ADDRESS,
- ValueLayout.ADDRESS,
- ValueLayout.ADDRESS,
- ValueLayout.ADDRESS,
- ValueLayout.ADDRESS);
- MethodHandle forkpty = linker.downcallHandle(openptyAddress.get(),
- openttyDescriptor);
- int res = (int) forkpty.invoke(parent,
- child,
- MemorySegment.NULL,
- MemorySegment.NULL,
- MemorySegment.NULL);
-
- if (res != 0) {
- throw new AssertionError();
- }
-
- //set the current VM's in/out to the terminal:
- FunctionDescriptor loginttyDescriptor =
- FunctionDescriptor.of(ValueLayout.JAVA_INT,
- ValueLayout.JAVA_INT);
- MethodHandle logintty = linker.downcallHandle(loginttyAddress.get(),
- loginttyDescriptor);
- logintty.invoke(child.get(ValueLayout.JAVA_INT, 0));
-
- //createTestJavaProcessBuilder logs to (current process') System.out, but
- //that may not work since the redirect. Setting System.out to a scratch value:
- System.setOut(new PrintStream(new ByteArrayOutputStream()));
-
- ProcessBuilder builder =
- ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName());
-
- builder.inheritIO();
- builder.redirectOutput(stdout.toFile());
-
- OutputAnalyzer output = ProcessTools.executeProcess(builder);
-
- output.waitFor();
-
- String expectedOut = OUTPUT;
- String actualOut = Files.readString(stdout);
-
- if (!Objects.equals(expectedOut, actualOut)) {
- throw new AssertionError("Unexpected stdout content. " +
- "Expected: '" + expectedOut + "'" +
- ", got: '" + actualOut + "'");
- }
- }
-
- public static class ConsoleTest {
- public static void main(String... args) {
- System.console().printf(OUTPUT);
- System.exit(0);
- }
- }
-}
diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
index 3a423fd71ca..49f565e27e9 100644
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
@@ -46,6 +46,7 @@ import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
+import java.util.OptionalInt;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -811,11 +812,19 @@ public class JPackageCommand extends CommandArguments {
return exec;
}
+ public Executor.Result executeIgnoreExitCode() {
+ return execute(OptionalInt.empty());
+ }
+
public Executor.Result execute() {
return execute(0);
}
public Executor.Result execute(int expectedExitCode) {
+ return execute(OptionalInt.of(expectedExitCode));
+ }
+
+ private Executor.Result execute(OptionalInt expectedExitCode) {
verifyMutable();
executePrerequisiteActions();
@@ -852,7 +861,8 @@ public class JPackageCommand extends CommandArguments {
}
}
- if (expectedExitCode == 0 && !isImagePackageType()) {
+ if (expectedExitCode.isPresent() && expectedExitCode.orElseThrow() == 0
+ && !isImagePackageType()) {
ConfigFilesStasher.INSTANCE.accept(this);
}
@@ -860,11 +870,17 @@ public class JPackageCommand extends CommandArguments {
final var directoriesAssert = new ReadOnlyPathsAssert(copy);
- Executor.Result result = copy.createExecutor().execute(expectedExitCode);
+ Executor.Result result;
+ if (expectedExitCode.isEmpty()) {
+ result = copy.createExecutor().executeWithoutExitCodeCheck();
+ } else {
+ result = copy.createExecutor().execute(expectedExitCode.orElseThrow());
+ }
directoriesAssert.updateAndAssert();
- if (expectedExitCode == 0 && isImagePackageType()) {
+ if (expectedExitCode.isPresent() && expectedExitCode.orElseThrow() == 0
+ && isImagePackageType()) {
ConfigFilesStasher.INSTANCE.accept(this);
}
@@ -872,7 +888,7 @@ public class JPackageCommand extends CommandArguments {
outputValidator.accept(result.getOutput().iterator());
}
- if (result.exitCode() == 0) {
+ if (result.exitCode() == 0 && expectedExitCode.isPresent()) {
verifyActions.run();
}
diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java
index 15b61763562..edb7e2918da 100644
--- a/test/jdk/tools/jpackage/share/AppContentTest.java
+++ b/test/jdk/tools/jpackage/share/AppContentTest.java
@@ -33,12 +33,12 @@ import jdk.jpackage.test.TKit;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameter;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import jdk.jpackage.internal.util.FileUtils;
import jdk.jpackage.internal.util.function.ThrowingFunction;
import jdk.jpackage.test.JPackageCommand;
+import jdk.jpackage.test.JPackageStringBundle;
/**
@@ -116,6 +116,20 @@ public class AppContentTest {
.run();
}
+ @Test(ifOS = MACOS)
+ @Parameter({TEST_DIR, "warning.non.standard.contents.sub.dir"})
+ @Parameter({TEST_DUKE, "warning.app.content.is.not.dir"})
+ public void testWarnings(String testPath, String warningId) throws Exception {
+ final var appContentValue = TKit.TEST_SRC_ROOT.resolve(testPath);
+ final var expectedWarning = JPackageStringBundle.MAIN.cannedFormattedString(
+ warningId, appContentValue);
+
+ JPackageCommand.helloAppImage()
+ .addArguments("--app-content", appContentValue)
+ .validateOutput(expectedWarning)
+ .executeIgnoreExitCode();
+ }
+
private static Path getAppContentRoot(JPackageCommand cmd) {
Path contentDir = cmd.appLayout().contentDirectory();
if (copyInResources) {
diff --git a/test/langtools/jdk/jshell/SnippetHighlightTest.java b/test/langtools/jdk/jshell/SnippetHighlightTest.java
index 9c59a3d8016..902d4347f74 100644
--- a/test/langtools/jdk/jshell/SnippetHighlightTest.java
+++ b/test/langtools/jdk/jshell/SnippetHighlightTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8274148 8301580
+ * @bug 8274148 8301580 8359497
* @summary Check snippet highlighting
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -114,6 +114,12 @@ public class SnippetHighlightTest extends KullaTesting {
"Highlight[start=32, end=38, attributes=[KEYWORD]]");
}
+ public void testNoCrashOnLexicalErrors() { //JDK-8359497
+ assertHighlights("""
+ "
+ """);
+ }
+
private void assertHighlights(String code, String... expected) {
List completions = computeHighlights(code);
assertEquals(completions, Arrays.asList(expected), "Input: " + code + ", " + completions.toString());
diff --git a/test/langtools/jdk/jshell/ToolingTest.java b/test/langtools/jdk/jshell/ToolingTest.java
index b36fdc03c19..f0d0e3f68eb 100644
--- a/test/langtools/jdk/jshell/ToolingTest.java
+++ b/test/langtools/jdk/jshell/ToolingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, 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
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8306560
+ * @bug 8306560 8365878
* @summary Tests for snippets and methods defined in TOOLING.jsh
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -79,4 +79,31 @@ public class ToolingTest extends ReplToolTesting {
)
);
}
+
+ @Test
+ public void testDisassembleBuiltinInnerClass() {
+ test(
+ a -> assertCommand(a, "/open TOOLING",
+ ""),
+ a -> assertCommandUserOutputContains(a, "javap(Base64.Decoder.class)",
+ "Classfile jrt:/java.base/java/util/Base64$Decoder.class",
+ "class java.util.Base64$Decoder",
+ "SourceFile: \"Base64.java\"")
+ );
+ }
+
+ @Test
+ public void testDisassembleAnonymousClass() {
+ test(
+ a -> assertCommand(a, "Object o() {return new ArrayList<>(){ };}", // must be in a method or it won't be anonymous
+ "| created method o()"),
+ a -> assertCommand(a, "/open TOOLING",
+ ""),
+ a -> assertCommandUserOutputContains(a, "javap(o().getClass())",
+ "Classfile ", // Classfile /.../TOOLING-16063368030094702464.class
+ " extends java.util.ArrayList", // class REPL.$JShell$22$1 extends java.util.ArrayList
+ "SourceFile: \"$JShell$" // SourceFile: "$JShell$22.java"
+ )
+ );
+ }
}
diff --git a/test/langtools/tools/javac/6304921/TestLog.java b/test/langtools/tools/javac/6304921/TestLog.java
index 41695554a88..8f00a14b9e2 100644
--- a/test/langtools/tools/javac/6304921/TestLog.java
+++ b/test/langtools/tools/javac/6304921/TestLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2025, 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
@@ -41,7 +41,7 @@ import javax.tools.SimpleJavaFileObject;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser;
import com.sun.tools.javac.parser.ParserFactory;
-import com.sun.tools.javac.resources.CompilerProperties.LintWarnings;
+import com.sun.tools.javac.resources.CompilerProperties.Warnings;
import com.sun.tools.javac.tree.EndPosTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
@@ -130,10 +130,11 @@ public class TestLog
log.error(tree.pos(), Errors.NotStmt);
log.error(nil, Errors.NotStmt);
- log.warning(LintWarnings.DivZero);
- log.warning(tree.pos, LintWarnings.DivZero);
- log.warning(tree.pos(), LintWarnings.DivZero);
- log.warning(nil, LintWarnings.DivZero);
+ // some warnings that will be emitted during parsing
+ log.warning(Warnings.ExtraneousSemicolon);
+ log.warning(tree.pos, Warnings.ExtraneousSemicolon);
+ log.warning(tree.pos(), Warnings.ExtraneousSemicolon);
+ log.warning(nil, Warnings.ExtraneousSemicolon);
}
private Log log;
diff --git a/test/langtools/tools/javac/ImportModule.java b/test/langtools/tools/javac/ImportModule.java
index f088dbef658..d26b73c0289 100644
--- a/test/langtools/tools/javac/ImportModule.java
+++ b/test/langtools/tools/javac/ImportModule.java
@@ -730,8 +730,8 @@ public class ImportModule extends TestRunner {
.getOutputLines(Task.OutputKind.DIRECT);
List expectedErrors = List.of(
- "module-info.java:3:18: compiler.warn.module.not.found: M1",
"module-info.java:6:9: compiler.err.cant.resolve: kindname.class, A, , ",
+ "module-info.java:3:18: compiler.warn.module.not.found: M1",
"1 error",
"1 warning"
);
diff --git a/test/langtools/tools/javac/OverrideChecks/6400189/T6400189a.out b/test/langtools/tools/javac/OverrideChecks/6400189/T6400189a.out
index 2a12111fe40..23dcddc1e93 100644
--- a/test/langtools/tools/javac/OverrideChecks/6400189/T6400189a.out
+++ b/test/langtools/tools/javac/OverrideChecks/6400189/T6400189a.out
@@ -1,4 +1,4 @@
-T6400189a.java:14:35: compiler.warn.unchecked.call.mbr.of.raw.type: getAnnotation(java.lang.Class), java.lang.reflect.Constructor
T6400189a.java:14:35: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.annotation.Annotation, java.lang.annotation.Documented)
+T6400189a.java:14:35: compiler.warn.unchecked.call.mbr.of.raw.type: getAnnotation(java.lang.Class), java.lang.reflect.Constructor
1 error
1 warning
diff --git a/test/langtools/tools/javac/OverrideChecks/6400189/T6400189b.out b/test/langtools/tools/javac/OverrideChecks/6400189/T6400189b.out
index 904cd3e677f..91e34b5beca 100644
--- a/test/langtools/tools/javac/OverrideChecks/6400189/T6400189b.out
+++ b/test/langtools/tools/javac/OverrideChecks/6400189/T6400189b.out
@@ -1,4 +1,4 @@
-T6400189b.java:24:24: compiler.warn.unchecked.call.mbr.of.raw.type: m(T6400189b), T6400189b.B
T6400189b.java:24:24: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer)
+T6400189b.java:24:24: compiler.warn.unchecked.call.mbr.of.raw.type: m(T6400189b), T6400189b.B
1 error
1 warning
diff --git a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.enabled.out b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.enabled.out
index 78285aa45d9..b2dde3ff0ef 100644
--- a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.enabled.out
+++ b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.enabled.out
@@ -1,7 +1,7 @@
+DanglingDocCommentsClass.java:15:5: compiler.warn.dangling.doc.comment
+DanglingDocCommentsClass.java:19:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:10:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:14:8: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass.java:14:69: compiler.warn.dangling.doc.comment
-DanglingDocCommentsClass.java:15:5: compiler.warn.dangling.doc.comment
-DanglingDocCommentsClass.java:19:5: compiler.warn.dangling.doc.comment
6 warnings
diff --git a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Line.enabled.out b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Line.enabled.out
index 3ed89c5f5bc..e97bd630ad8 100644
--- a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Line.enabled.out
+++ b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Line.enabled.out
@@ -1,7 +1,7 @@
+DanglingDocCommentsClass_Line.java:21:5: compiler.warn.dangling.doc.comment
+DanglingDocCommentsClass_Line.java:26:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:11:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:15:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:17:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Line.java:19:9: compiler.warn.dangling.doc.comment
-DanglingDocCommentsClass_Line.java:21:5: compiler.warn.dangling.doc.comment
-DanglingDocCommentsClass_Line.java:26:5: compiler.warn.dangling.doc.comment
6 warnings
diff --git a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Mixed.enabled.out b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Mixed.enabled.out
index 1eda729da19..13e15493579 100644
--- a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Mixed.enabled.out
+++ b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass_Mixed.enabled.out
@@ -1,4 +1,4 @@
-DanglingDocCommentsClass_Mixed.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Mixed.java:17:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsClass_Mixed.java:21:5: compiler.warn.dangling.doc.comment
+DanglingDocCommentsClass_Mixed.java:13:1: compiler.warn.dangling.doc.comment
3 warnings
diff --git a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsEnum.enabled.out b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsEnum.enabled.out
index ddf1b2964de..33938e86078 100644
--- a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsEnum.enabled.out
+++ b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsEnum.enabled.out
@@ -1,8 +1,8 @@
+DanglingDocCommentsEnum.java:16:5: compiler.warn.dangling.doc.comment
+DanglingDocCommentsEnum.java:22:5: compiler.warn.dangling.doc.comment
+DanglingDocCommentsEnum.java:28:5: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:10:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:13:1: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:14:8: compiler.warn.dangling.doc.comment
DanglingDocCommentsEnum.java:14:67: compiler.warn.dangling.doc.comment
-DanglingDocCommentsEnum.java:16:5: compiler.warn.dangling.doc.comment
-DanglingDocCommentsEnum.java:22:5: compiler.warn.dangling.doc.comment
-DanglingDocCommentsEnum.java:28:5: compiler.warn.dangling.doc.comment
7 warnings
diff --git a/test/langtools/tools/javac/generics/diamond/7188968/T7188968.out b/test/langtools/tools/javac/generics/diamond/7188968/T7188968.out
index efceb84c8c7..3c93e1711d6 100644
--- a/test/langtools/tools/javac/generics/diamond/7188968/T7188968.out
+++ b/test/langtools/tools/javac/generics/diamond/7188968/T7188968.out
@@ -1,11 +1,11 @@
T7188968.java:20:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
-T7188968.java:20:9: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List,java.lang.Object), T7188968.Foo
T7188968.java:21:20: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
-T7188968.java:21:29: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List,java.lang.Object), T7188968.Foo
T7188968.java:22:22: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
+T7188968.java:23:24: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
+T7188968.java:20:9: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List,java.lang.Object), T7188968.Foo
+T7188968.java:21:29: compiler.warn.unchecked.call.mbr.of.raw.type: T7188968.Foo(java.util.List,java.lang.Object), T7188968.Foo
T7188968.java:22:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, , java.util.List,java.lang.Object, java.util.List,unknown, kindname.class, T7188968.Foo
T7188968.java:22:19: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List
-T7188968.java:23:24: compiler.err.cant.resolve.location: kindname.variable, unknown, , , (compiler.misc.location: kindname.class, T7188968, null)
T7188968.java:23:20: compiler.warn.unchecked.meth.invocation.applied: kindname.method, makeFoo, java.util.List,java.lang.Object, java.util.List,unknown, kindname.class, T7188968.Foo
T7188968.java:23:21: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List
4 errors
diff --git a/test/langtools/tools/javac/lambda/TargetType22.out b/test/langtools/tools/javac/lambda/TargetType22.out
index d94b2cc60b3..c19aef2411f 100644
--- a/test/langtools/tools/javac/lambda/TargetType22.out
+++ b/test/langtools/tools/javac/lambda/TargetType22.out
@@ -1,4 +1,4 @@
-TargetType22.java:29:21: compiler.warn.unchecked.varargs.non.reifiable.type: A
TargetType22.java:40:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType22.Sam1), TargetType22, kindname.method, call(TargetType22.SamX), TargetType22
+TargetType22.java:29:21: compiler.warn.unchecked.varargs.non.reifiable.type: A
1 error
1 warning
diff --git a/test/langtools/tools/javac/lint/LexicalLintNesting.java b/test/langtools/tools/javac/lint/LexicalLintNesting.java
new file mode 100644
index 00000000000..f167921df81
--- /dev/null
+++ b/test/langtools/tools/javac/lint/LexicalLintNesting.java
@@ -0,0 +1,170 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8224228
+ * @summary Verify lexical lint warnings handle nested declarations with SuppressWarnings correctly
+ * @compile/fail/ref=LexicalLintNesting.out -XDrawDiagnostics -Xlint:text-blocks -Werror LexicalLintNesting.java
+ */
+
+//@SuppressWarnings("text-blocks")
+public class LexicalLintNesting {
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s1 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ String s2 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ public static class Nested1 {
+
+ @SuppressWarnings("text-blocks")
+ String s3 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s4 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ public static class Nested1A {
+
+ //@SuppressWarnings("text-blocks")
+ String s5 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ String s6 = """
+ trailing space here:\u0020
+ """;
+
+ }
+
+ @SuppressWarnings("text-blocks")
+ String s7 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s8 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ public static class Nested1B {
+
+ @SuppressWarnings("text-blocks")
+ String s9 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s10 = """
+ trailing space here:\u0020
+ """;
+
+ }
+
+ @SuppressWarnings("text-blocks")
+ String s11 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s12 = """
+ trailing space here:\u0020
+ """;
+
+ }
+
+ @SuppressWarnings("text-blocks")
+ String s13 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s14 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ public static class Nested2 {
+
+ @SuppressWarnings("text-blocks")
+ String s15 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ String s16 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ public static class Nested2A {
+
+ //@SuppressWarnings("text-blocks")
+ String s17 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ String s18 = """
+ trailing space here:\u0020
+ """; // SHOULD NOT get a warning here
+
+ }
+
+ @SuppressWarnings("text-blocks")
+ String s19 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ String s20 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ public static class Nested2B {
+
+ @SuppressWarnings("text-blocks")
+ String s21 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ String s22 = """
+ trailing space here:\u0020
+ """;
+
+ }
+
+ @SuppressWarnings("text-blocks")
+ String s23 = """
+ trailing space here:\u0020
+ """;
+
+ //@SuppressWarnings("text-blocks")
+ String s24 = """
+ trailing space here:\u0020
+ """;
+
+ }
+
+ //@SuppressWarnings("text-blocks")
+ /* WARNING HERE */ String s25 = """
+ trailing space here:\u0020
+ """;
+
+ @SuppressWarnings("text-blocks")
+ String s26 = """
+ trailing space here:\u0020
+ """;
+}
diff --git a/test/langtools/tools/javac/lint/LexicalLintNesting.out b/test/langtools/tools/javac/lint/LexicalLintNesting.out
new file mode 100644
index 00000000000..b16db47cf52
--- /dev/null
+++ b/test/langtools/tools/javac/lint/LexicalLintNesting.out
@@ -0,0 +1,10 @@
+LexicalLintNesting.java:12:36: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:30:40: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:55:40: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:68:45: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:80:41: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:92:37: compiler.warn.trailing.white.space.will.be.removed
+LexicalLintNesting.java:162:37: compiler.warn.trailing.white.space.will.be.removed
+- compiler.err.warnings.and.werror
+1 error
+7 warnings
diff --git a/test/langtools/tools/javac/lint/TextBlockSuppress.java b/test/langtools/tools/javac/lint/TextBlockSuppress.java
new file mode 100644
index 00000000000..05019be6bc2
--- /dev/null
+++ b/test/langtools/tools/javac/lint/TextBlockSuppress.java
@@ -0,0 +1,61 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8224228
+ * @summary Verify SuppressWarnings works for LintCategore.TEXT_BLOCKS
+ * @compile/fail/ref=TextBlockSuppress.out -XDrawDiagnostics -Xlint:text-blocks -Werror TextBlockSuppress.java
+ */
+
+public class TextBlockSuppress {
+
+ public static class Example1 {
+ public void method() {
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD get a warning here
+ }
+ }
+
+ @SuppressWarnings("text-blocks")
+ public static class Example2 {
+ public void method() {
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example3 {
+ @SuppressWarnings("text-blocks")
+ public void method() {
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example4 {
+ {
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD get a warning here
+ }
+ }
+
+ @SuppressWarnings("text-blocks")
+ public static class Example5 {
+ {
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example6 {
+ public void method() {
+ @SuppressWarnings("text-blocks")
+ String s = """
+ trailing space here:\u0020
+ """; // SHOULD NOT get a warning here
+ }
+ }
+}
diff --git a/test/langtools/tools/javac/lint/TextBlockSuppress.out b/test/langtools/tools/javac/lint/TextBlockSuppress.out
new file mode 100644
index 00000000000..d16f080a133
--- /dev/null
+++ b/test/langtools/tools/javac/lint/TextBlockSuppress.out
@@ -0,0 +1,5 @@
+TextBlockSuppress.java:12:24: compiler.warn.trailing.white.space.will.be.removed
+TextBlockSuppress.java:38:24: compiler.warn.trailing.white.space.will.be.removed
+- compiler.err.warnings.and.werror
+1 error
+2 warnings
diff --git a/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5.out b/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5.out
index 6fe57b8979d..1656d8eeff5 100644
--- a/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5.out
+++ b/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5.out
@@ -1,4 +1,4 @@
-Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
P.java:10:18: compiler.warn.has.been.deprecated: foo(), Q
+Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
Q.java:17:25: compiler.warn.has.been.deprecated: foo(), Q
3 warnings
diff --git a/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5b.out b/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5b.out
index fe4a91e2584..5dee9c1414c 100644
--- a/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5b.out
+++ b/test/langtools/tools/javac/mandatoryWarnings/deprecated/Test5b.out
@@ -1,4 +1,4 @@
-Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
P.java:10:18: compiler.warn.has.been.deprecated: foo(), Q
+Q.java:7:10: compiler.warn.has.been.deprecated: bar(), Q2
- compiler.note.deprecated.filename.additional: Q.java
2 warnings
diff --git a/test/langtools/tools/javac/modules/AnnotationsOnModules.java b/test/langtools/tools/javac/modules/AnnotationsOnModules.java
index 6d9bfaad406..f9858a105eb 100644
--- a/test/langtools/tools/javac/modules/AnnotationsOnModules.java
+++ b/test/langtools/tools/javac/modules/AnnotationsOnModules.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2025, 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
@@ -599,8 +599,8 @@ public class AnnotationsOnModules extends ModuleTestBase {
"1 warning");
} else if (suppress.equals(DEPRECATED_JAVADOC)) {
expected = Arrays.asList(
- "module-info.java:1:19: compiler.warn.missing.deprecated.annotation",
"module-info.java:2:14: compiler.warn.has.been.deprecated.module: m1x",
+ "module-info.java:1:19: compiler.warn.missing.deprecated.annotation",
"2 warnings");
} else {
expected = Arrays.asList("");
diff --git a/test/langtools/tools/javac/preview/PreviewErrors.java b/test/langtools/tools/javac/preview/PreviewErrors.java
index eab5b2af9bf..db17aabbd42 100644
--- a/test/langtools/tools/javac/preview/PreviewErrors.java
+++ b/test/langtools/tools/javac/preview/PreviewErrors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025, 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
@@ -324,7 +324,9 @@ public class PreviewErrors extends ComboInstance {
ok = true;
switch (elementType) {
case LANGUAGE -> {
- if (lint == Lint.ENABLE_PREVIEW) {
+ if (suppress == Suppress.YES) {
+ expected = Set.of();
+ } else if (lint == Lint.ENABLE_PREVIEW) {
expected = Set.of("5:41:compiler.warn.preview.feature.use");
} else {
expected = Set.of("-1:-1:compiler.note.preview.filename",
diff --git a/test/langtools/tools/javac/preview/PreviewTest.java b/test/langtools/tools/javac/preview/PreviewTest.java
index 36f1e70acd0..e681f3f837e 100644
--- a/test/langtools/tools/javac/preview/PreviewTest.java
+++ b/test/langtools/tools/javac/preview/PreviewTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, 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
@@ -587,12 +587,12 @@ public class PreviewTest extends TestRunner {
"Test.java:19:11: compiler.err.is.preview: test()",
"Test.java:20:11: compiler.err.is.preview: test()",
"Test.java:21:11: compiler.err.is.preview: test()",
- "Test.java:24:11: compiler.warn.is.preview.reflective: test()",
"Test.java:29:16: compiler.err.is.preview: preview.api.Preview",
"Test.java:32:21: compiler.err.is.preview: test()",
"Test.java:36:21: compiler.err.is.preview: test()",
"Test.java:40:13: compiler.err.is.preview: test()",
"Test.java:41:21: compiler.err.is.preview: FIELD",
+ "Test.java:24:11: compiler.warn.is.preview.reflective: test()",
"17 errors",
"1 warning");
@@ -792,6 +792,99 @@ public class PreviewTest extends TestRunner {
throw new Exception("expected output not found" + log);
}
+ @Test //JDK-8224228:
+ public void testSuppressWarnings(Path base) throws Exception {
+ Path apiSrc = base.resolve("api-src");
+ tb.writeJavaFiles(apiSrc,
+ """
+ package preview.api;
+ @jdk.internal.javac.PreviewFeature(feature=jdk.internal.javac.PreviewFeature.Feature.TEST)
+ public class Preview {
+ public static int test() {
+ return 0;
+ }
+ }
+ """);
+ Path apiClasses = base.resolve("api-classes");
+
+ new JavacTask(tb, Task.Mode.CMDLINE)
+ .outdir(apiClasses)
+ .options("--patch-module", "java.base=" + apiSrc.toString(),
+ "-Werror")
+ .files(tb.findJavaFiles(apiSrc))
+ .run()
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ Path testSrc = base.resolve("test-src");
+ tb.writeJavaFiles(testSrc,
+ """
+ package test;
+ import preview.api.Preview;
+ public class Test {
+
+ public static class Example1 {
+ public void method() {
+ Preview.test(); // SHOULD get a warning here
+ }
+ }
+
+ @SuppressWarnings("preview")
+ public static class Example2 {
+ public void method() {
+ Preview.test(); // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example3 {
+ @SuppressWarnings("preview")
+ public void method() {
+ Preview.test(); // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example4 {
+ {
+ Preview.test(); // SHOULD get a warning here
+ }
+ }
+
+ @SuppressWarnings("preview")
+ public static class Example5 {
+ {
+ Preview.test(); // SHOULD NOT get a warning here
+ }
+ }
+
+ public static class Example6 {
+ @SuppressWarnings("preview")
+ int x = Preview.test(); // SHOULD NOT get a warning here
+ }
+ }
+ """);
+ Path testClasses = base.resolve("test-classes");
+ List log = new JavacTask(tb, Task.Mode.CMDLINE)
+ .outdir(testClasses)
+ .options("--patch-module", "java.base=" + apiClasses.toString(),
+ "--add-exports", "java.base/preview.api=ALL-UNNAMED",
+ "--enable-preview",
+ "-Xlint:preview",
+ "-source", String.valueOf(Runtime.version().feature()),
+ "-XDrawDiagnostics")
+ .files(tb.findJavaFiles(testSrc))
+ .run(Task.Expect.SUCCESS)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ List expected =
+ List.of("Test.java:7:11: compiler.warn.is.preview: preview.api.Preview",
+ "Test.java:27:11: compiler.warn.is.preview: preview.api.Preview",
+ "2 warnings");
+
+ if (!log.equals(expected))
+ throw new Exception("expected output not found: " + log);
+ }
+
@Test //JDK-8343540:
public void nonPreviewImplementsPreview5(Path base) throws Exception {
Path apiSrc = base.resolve("api-src");
diff --git a/test/langtools/tools/javac/varargs/7097436/T7097436.out b/test/langtools/tools/javac/varargs/7097436/T7097436.out
index 5e35910d2fa..392869f3b9f 100644
--- a/test/langtools/tools/javac/varargs/7097436/T7097436.out
+++ b/test/langtools/tools/javac/varargs/7097436/T7097436.out
@@ -1,6 +1,6 @@
-T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
-T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List[], java.lang.String)
T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.util.List[], java.lang.Integer[])
+T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls
+T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls
2 errors
2 warnings
diff --git a/test/langtools/tools/javac/warnings/6594914/T6594914a.out b/test/langtools/tools/javac/warnings/6594914/T6594914a.out
index 62f99072a7a..d3d759ca044 100644
--- a/test/langtools/tools/javac/warnings/6594914/T6594914a.out
+++ b/test/langtools/tools/javac/warnings/6594914/T6594914a.out
@@ -1,7 +1,7 @@
T6594914a.java:11:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:16: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:16:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:17:20: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6594914a.java:24:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
6 warnings
diff --git a/test/langtools/tools/javac/warnings/7090499/T7090499.out b/test/langtools/tools/javac/warnings/7090499/T7090499.out
index 1ff9e164e48..2241c0a04bb 100644
--- a/test/langtools/tools/javac/warnings/7090499/T7090499.out
+++ b/test/langtools/tools/javac/warnings/7090499/T7090499.out
@@ -1,14 +1,14 @@
+T7090499.java:26:10: compiler.err.improperly.formed.type.inner.raw.param
+T7090499.java:27:10: compiler.err.improperly.formed.type.inner.raw.param
+T7090499.java:28:17: compiler.err.improperly.formed.type.inner.raw.param
+T7090499.java:28:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:18:5: compiler.warn.raw.class.use: T7090499, T7090499
T7090499.java:18:22: compiler.warn.raw.class.use: T7090499, T7090499
T7090499.java:20:10: compiler.warn.raw.class.use: T7090499.A.X, T7090499.A.X
T7090499.java:21:10: compiler.warn.raw.class.use: T7090499.A.Z, T7090499.A.Z
T7090499.java:24:17: compiler.warn.raw.class.use: T7090499.B, T7090499.B
-T7090499.java:26:10: compiler.err.improperly.formed.type.inner.raw.param
-T7090499.java:27:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:18: compiler.warn.raw.class.use: T7090499.B, T7090499.B
-T7090499.java:28:17: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:28:11: compiler.warn.raw.class.use: T7090499.B, T7090499.B
-T7090499.java:28:10: compiler.err.improperly.formed.type.inner.raw.param
T7090499.java:30:32: compiler.warn.raw.class.use: T7090499.B, T7090499.B
T7090499.java:33:13: compiler.warn.raw.class.use: T7090499.A, T7090499.A
T7090499.java:33:24: compiler.warn.raw.class.use: T7090499.A, T7090499.A
diff --git a/test/langtools/tools/javac/warnings/UnneededStrictfpWarningToolBox.java b/test/langtools/tools/javac/warnings/UnneededStrictfpWarningToolBox.java
index b5062a9b63f..a9101b47e42 100644
--- a/test/langtools/tools/javac/warnings/UnneededStrictfpWarningToolBox.java
+++ b/test/langtools/tools/javac/warnings/UnneededStrictfpWarningToolBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, 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
@@ -116,8 +116,8 @@ public class UnneededStrictfpWarningToolBox extends TestRunner {
var expected = List.of("UnneededStrictfpWarning1.java:1:17: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:10:10: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:12:29: compiler.warn.strictfp",
- "UnneededStrictfpWarning1.java:16:28: compiler.warn.strictfp",
"UnneededStrictfpWarning1.java:18:21: compiler.warn.strictfp",
+ "UnneededStrictfpWarning1.java:16:28: compiler.warn.strictfp",
"5 warnings");
checkLog(log, expected);
}
diff --git a/test/langtools/tools/javac/warnings/suppress/T6480588.out b/test/langtools/tools/javac/warnings/suppress/T6480588.out
index 630ba55523d..267ef32c964 100644
--- a/test/langtools/tools/javac/warnings/suppress/T6480588.out
+++ b/test/langtools/tools/javac/warnings/suppress/T6480588.out
@@ -1,19 +1,19 @@
T6480588.java:16:24: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:16:51: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
T6480588.java:15:2: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
+T6480588.java:18:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:18:12: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:18:65: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:30:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:33:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:33:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
+T6480588.java:32:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:17:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
-T6480588.java:18:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:29:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:19:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:19:34: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:21:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
T6480588.java:21:25: compiler.warn.deprecated.annotation.has.no.effect: kindname.variable
T6480588.java:21:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6480588.java:30:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6480588.java:29:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
T6480588.java:30:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6480588.java:33:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6480588.java:33:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
-T6480588.java:32:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
18 warnings
diff --git a/test/lib/jdk/test/lib/cds/CDSAppTester.java b/test/lib/jdk/test/lib/cds/CDSAppTester.java
index cfe17a0be14..fd244c6acc6 100644
--- a/test/lib/jdk/test/lib/cds/CDSAppTester.java
+++ b/test/lib/jdk/test/lib/cds/CDSAppTester.java
@@ -402,8 +402,6 @@ abstract public class CDSAppTester {
public OutputAnalyzer productionRun(String[] extraVmArgs, String[] extraAppArgs) throws Exception {
RunMode runMode = RunMode.PRODUCTION;
String[] cmdLine = StringArrayUtils.concat(vmArgs(runMode),
- "-XX:+UnlockDiagnosticVMOptions",
- "-XX:VerifyArchivedFields=2", // make sure archived heap objects are good.
logToFile(productionRunLog(), "aot", "cds"));
cmdLine = addCommonVMArgs(runMode, cmdLine);
diff --git a/test/lib/jdk/test/lib/cds/CDSTestUtils.java b/test/lib/jdk/test/lib/cds/CDSTestUtils.java
index be6fddc17aa..56e3baa2e25 100644
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java
@@ -440,7 +440,6 @@ public class CDSTestUtils {
opts.archiveName = getDefaultArchiveName();
cmd.add("-XX:SharedArchiveFile=" + opts.archiveName);
}
- addVerifyArchivedFields(cmd);
if (opts.useVersion)
cmd.add("-version");