From 53a4f4cd6296e54337c07bb780f72a638d25448c Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Thu, 23 Oct 2014 11:42:20 +0200 Subject: [PATCH 001/134] 8058506: ThreadMXBeanStateTest throws exception Reviewed-by: egahlin, dholmes --- jdk/test/ProblemList.txt | 3 - .../lang/Thread/ThreadStateController.java | 84 ++++++++++------- .../ThreadMXBean/ThreadMXBeanStateTest.java | 12 ++- .../jdk/testlibrary/LockFreeLogManager.java | 90 +++++++++++++++++++ 4 files changed, 152 insertions(+), 37 deletions(-) create mode 100644 jdk/test/lib/testlibrary/jdk/testlibrary/LockFreeLogManager.java diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 1d824bea96b..106a7cb3de3 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -138,9 +138,6 @@ com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java # 8058492 java/lang/management/ThreadMXBean/FindDeadlocks.java generic-all -# 8058506 -java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java generic-all - ############################################################################ # jdk_jmx diff --git a/jdk/test/java/lang/Thread/ThreadStateController.java b/jdk/test/java/lang/Thread/ThreadStateController.java index 2d876b0ec41..e2c6341b471 100644 --- a/jdk/test/java/lang/Thread/ThreadStateController.java +++ b/jdk/test/java/lang/Thread/ThreadStateController.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014 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,6 +27,8 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; +import jdk.testlibrary.LockFreeLogManager; + /** * ThreadStateController allows a thread to request this thread to transition * to a specific thread state. The {@linkplain #transitionTo request} is @@ -94,8 +96,12 @@ public class ThreadStateController extends Thread { private static final int S_TERMINATE = 8; // for debugging - private AtomicInteger iterations = new AtomicInteger(); - private AtomicInteger interrupted = new AtomicInteger(); + private final AtomicInteger iterations = new AtomicInteger(); + private final AtomicInteger interrupted = new AtomicInteger(); + + private final LockFreeLogManager logManager = new LockFreeLogManager(); + + @Override public void run() { // this thread has started while (!done) { @@ -119,13 +125,13 @@ public class ThreadStateController extends Thread { break; } case S_BLOCKED: { - System.out.format("%d: %s is going to block (interations %d)%n", - getId(), getName(), iterations.get()); + log("%d: %s is going to block (iterations %d)%n", + getId(), getName(), iterations.get()); stateChange(nextState); // going to block on lock synchronized (lock) { - System.out.format("%d: %s acquired the lock (interations %d)%n", - getId(), getName(), iterations.get()); + log("%d: %s acquired the lock (iterations %d)%n", + getId(), getName(), iterations.get()); try { // this thread has escaped the BLOCKED state // release the lock and a short wait before continue @@ -139,13 +145,13 @@ public class ThreadStateController extends Thread { } case S_WAITING: { synchronized (lock) { - System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n", - getId(), getName(), iterations.get(), interrupted.get()); + log("%d: %s is going to waiting (iterations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); try { stateChange(nextState); lock.wait(); - System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n", - getId(), getName(), iterations.get(), interrupted.get()); + log("%d: %s wakes up from waiting (iterations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); } catch (InterruptedException e) { // ignore interrupted.incrementAndGet(); @@ -155,13 +161,13 @@ public class ThreadStateController extends Thread { } case S_TIMED_WAITING: { synchronized (lock) { - System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n", - getId(), getName(), iterations.get(), interrupted.get()); + log("%d: %s is going to timed waiting (iterations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); try { stateChange(nextState); lock.wait(10000); - System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n", - getId(), getName(), iterations.get(), interrupted.get()); + log("%d: %s wakes up from timed waiting (iterations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); } catch (InterruptedException e) { // ignore interrupted.incrementAndGet(); @@ -170,23 +176,23 @@ public class ThreadStateController extends Thread { break; } case S_PARKED: { - System.out.format("%d: %s is going to park (interations %d)%n", - getId(), getName(), iterations.get()); + log("%d: %s is going to park (iterations %d)%n", + getId(), getName(), iterations.get()); stateChange(nextState); LockSupport.park(); break; } case S_TIMED_PARKED: { - System.out.format("%d: %s is going to timed park (interations %d)%n", - getId(), getName(), iterations.get()); + log("%d: %s is going to timed park (iterations %d)%n", + getId(), getName(), iterations.get()); long deadline = System.currentTimeMillis() + 10000*1000; stateChange(nextState); LockSupport.parkUntil(deadline); break; } case S_SLEEPING: { - System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n", - getId(), getName(), iterations.get(), interrupted.get()); + log("%d: %s is going to sleep (iterations %d interrupted %d)%n", + getId(), getName(), iterations.get(), interrupted.get()); try { stateChange(nextState); Thread.sleep(1000000); @@ -219,8 +225,8 @@ public class ThreadStateController extends Thread { if (newState == nextState) { state = nextState; phaser.arrive(); - System.out.format("%d: state change: %s %s%n", - getId(), toStateName(nextState), phaserToString(phaser)); + log("%d: state change: %s %s%n", + getId(), toStateName(nextState), phaserToString(phaser)); return; } @@ -270,12 +276,12 @@ public class ThreadStateController extends Thread { private void nextState(int s) throws InterruptedException { final long id = Thread.currentThread().getId(); - System.out.format("%d: wait until the thread transitions to %s %s%n", - id, toStateName(s), phaserToString(phaser)); + log("%d: wait until the thread transitions to %s %s%n", + id, toStateName(s), phaserToString(phaser)); this.newState = s; int phase = phaser.arrive(); - System.out.format("%d: awaiting party arrive %s %s%n", - id, toStateName(s), phaserToString(phaser)); + log("%d: awaiting party arrive %s %s%n", + id, toStateName(s), phaserToString(phaser)); for (;;) { // when this thread has changed its state before it waits or parks // on a lock, a potential race might happen if it misses the notify @@ -301,20 +307,22 @@ public class ThreadStateController extends Thread { } try { phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS); - System.out.format("%d: arrived at %s %s%n", - id, toStateName(s), phaserToString(phaser)); + log("%d: arrived at %s %s%n", + id, toStateName(s), phaserToString(phaser)); return; } catch (TimeoutException ex) { // this thread hasn't arrived at this phase - System.out.format("%d: Timeout: %s%n", id, phaser); + log("%d: Timeout: %s%n", id, phaser); } } } + private String phaserToString(Phaser p) { return "[phase = " + p.getPhase() + " parties = " + p.getRegisteredParties() + " arrived = " + p.getArrivedParties() + "]"; } + private String toStateName(int state) { switch (state) { case S_RUNNABLE: @@ -337,4 +345,20 @@ public class ThreadStateController extends Thread { return "unknown " + state; } } + + private void log(String msg, Object ... params) { + logManager.log(msg, params); + } + + /** + * Waits for the controller to complete the test run and returns the + * generated log + * @return The controller log + * @throws InterruptedException + */ + public String getLog() throws InterruptedException { + this.join(); + + return logManager.toString(); + } } diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java index 10e374f9cba..c56bb27dd2c 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java +++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ * @author Mandy Chung * * @library ../../Thread + * @library /lib/testlibrary + * @build jdk.testlibrary.LockFreeLogManager * @build ThreadMXBeanStateTest ThreadStateController * @run main ThreadMXBeanStateTest */ @@ -44,15 +46,17 @@ public class ThreadMXBeanStateTest { private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean(); static class Lock { - private String name; + private final String name; Lock(String name) { this.name = name; } + @Override public String toString() { return name; } } - private static Lock globalLock = new Lock("my lock"); + + private static final Lock globalLock = new Lock("my lock"); public static void main(String[] argv) throws Exception { // Force thread state initialization now before the test @@ -109,7 +113,7 @@ public class ThreadMXBeanStateTest { thread.checkThreadState(TERMINATED); try { - thread.join(); + System.out.println(thread.getLog()); } catch (InterruptedException e) { e.printStackTrace(); System.out.println("TEST FAILED: Unexpected exception."); diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/LockFreeLogManager.java b/jdk/test/lib/testlibrary/jdk/testlibrary/LockFreeLogManager.java new file mode 100644 index 00000000000..f895018be44 --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/LockFreeLogManager.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, 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. + */ + +package jdk.testlibrary; + +import java.util.Collection; +import java.util.Formatter; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * A log manager designed specifically to allow collecting ordered log messages + * in a multi-threaded environment without involving any kind of locking. + *

+ * It is particularly useful in situations when one needs to assert various + * details about the tested thread state or the locks it hold while also wanting + * to produce diagnostic log messages. + *

+ * The log manager does not provide any guarantees about the completness of the + * logs written from different threads - it is up to the caller to make sure + * {@code toString()} method is called only when all the activity has ceased + * and the per-thread logs contain all the necessary data. + * + * @author Jaroslav Bachorik + **/ +public class LockFreeLogManager { + private final AtomicInteger logCntr = new AtomicInteger(0); + private final Collection> allRecords = new ConcurrentLinkedQueue<>(); + private final ThreadLocal> records = new ThreadLocal>() { + @Override + protected Map initialValue() { + Map m = new ConcurrentHashMap<>(); + allRecords.add(m); + return m; + } + + }; + + /** + * Log a message + * @param format Message format + * @param params Message parameters + */ + public void log(String format, Object ... params) { + int id = logCntr.getAndIncrement(); + try (Formatter formatter = new Formatter()) { + records.get().put(id, formatter.format(format, params).toString()); + } + } + + /** + * Will generate an aggregated log of chronologically ordered messages. + *

+ * Make sure that you call this method only when all the related threads + * have finished; otherwise you might get incomplete data. + * + * @return An aggregated log of chronologically ordered messages + */ + @Override + public String toString() { + return allRecords.stream() + .flatMap(m->m.entrySet().stream()) + .sorted((l, r)->l.getKey().compareTo(r.getKey())) + .map(e->e.getValue()) + .collect(Collectors.joining()); + } +} From 302bc3438c47e90e87866535e2e3127624e8ae40 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 23 Oct 2014 19:59:27 +0400 Subject: [PATCH 002/134] 8059941: [D3D] The fix for JDK-8029253 should be ported to d3d pipeline Reviewed-by: bae, prr --- .../classes/sun/java2d/d3d/D3DBlitLoops.java | 60 ++++++++++++++++--- .../UnmanagedDrawImagePerformance.java | 2 +- 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java index 94495da083e..93dc53d4f27 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, 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 @@ -48,7 +48,7 @@ import sun.java2d.pipe.RenderQueue; import static sun.java2d.pipe.BufferedOpCodes.*; import sun.java2d.windows.GDIWindowSurfaceData; -class D3DBlitLoops { +final class D3DBlitLoops { static void register() { Blit blitIntArgbPreToSurface = @@ -57,7 +57,9 @@ class D3DBlitLoops { Blit blitIntArgbPreToTexture = new D3DSwToTextureBlit(SurfaceType.IntArgbPre, D3DSurfaceData.ST_INT_ARGB_PRE); - + TransformBlit transformBlitIntArgbPreToSurface = + new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre, + D3DSurfaceData.ST_INT_ARGB_PRE); GraphicsPrimitive[] primitives = { // prevent D3DSurface -> Screen blits new D3DSurfaceToGDIWindowSurfaceBlit(), @@ -123,8 +125,6 @@ class D3DBlitLoops { new D3DSwToSurfaceTransform(SurfaceType.IntArgb, D3DSurfaceData.ST_INT_ARGB), - new D3DSwToSurfaceTransform(SurfaceType.IntArgbPre, - D3DSurfaceData.ST_INT_ARGB_PRE), new D3DSwToSurfaceTransform(SurfaceType.IntRgb, D3DSurfaceData.ST_INT_RGB), new D3DSwToSurfaceTransform(SurfaceType.IntBgr, @@ -140,6 +140,9 @@ class D3DBlitLoops { // REMIND: we don't have a native sw loop to back this loop up // new D3DSwToSurfaceTransform(SurfaceType.ByteIndexedBm, // D3DSurfaceData.ST_BYTE_INDEXED_BM), + transformBlitIntArgbPreToSurface, + + new D3DGeneralTransformedBlit(transformBlitIntArgbPreToSurface), // texture->surface ops new D3DTextureToSurfaceBlit(), @@ -712,11 +715,11 @@ class D3DTextureToSurfaceTransform extends TransformBlit { * This general Blit implementation converts any source surface to an * intermediate IntArgbPre surface, and then uses the more specific * IntArgbPre->D3DSurface/Texture loop to get the intermediate - * (premultiplied) surface down to D3D. + * (premultiplied) surface down to D3D using simple blit. */ class D3DGeneralBlit extends Blit { - private Blit performop; + private final Blit performop; private WeakReference srcTmp; D3DGeneralBlit(SurfaceType dstType, @@ -757,6 +760,49 @@ class D3DGeneralBlit extends Blit { } } +/** + * This general TransformedBlit implementation converts any source surface to an + * intermediate IntArgbPre surface, and then uses the more specific + * IntArgbPre->D3DSurface/Texture loop to get the intermediate + * (premultiplied) surface down to D3D using simple transformBlit. + */ +final class D3DGeneralTransformedBlit extends TransformBlit { + + private final TransformBlit performop; + private WeakReference srcTmp; + + D3DGeneralTransformedBlit(final TransformBlit performop) { + super(SurfaceType.Any, CompositeType.AnyAlpha, + D3DSurfaceData.D3DSurface); + this.performop = performop; + } + + @Override + public synchronized void Transform(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + AffineTransform at, int hint, int srcx, + int srcy, int dstx, int dsty, int width, + int height){ + Blit convertsrc = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + SurfaceType.IntArgbPre); + // use cached intermediate surface, if available + final SurfaceData cachedSrc = srcTmp != null ? srcTmp.get() : null; + // convert source to IntArgbPre + src = convertFrom(convertsrc, src, srcx, srcy, width, height, cachedSrc, + BufferedImage.TYPE_INT_ARGB_PRE); + + // transform IntArgbPre intermediate surface to D3D surface + performop.Transform(src, dst, comp, clip, at, hint, 0, 0, dstx, dsty, + width, height); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } +} + /* * The following classes prohibit copying D3DSurfaces to the screen * (the D3D->sysmem->GDI path is known to be very very slow). diff --git a/jdk/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java b/jdk/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java index 67ea6b5af99..e08bb9dec16 100644 --- a/jdk/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java +++ b/jdk/test/java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java @@ -41,7 +41,7 @@ import static java.awt.image.BufferedImage.*; /* * @test - * @bug 8029253 + * @bug 8029253 8059941 * @summary Unmanaged images should be drawn fast. * @author Sergey Bylokhov */ From 71ae76123cee4dca0b9a91b24fada23419d7debc Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 24 Oct 2014 11:41:08 +0400 Subject: [PATCH 003/134] 7154054: [macosx] Can't distinguish the focus move to next cell Reviewed-by: azvegint, alexsch --- .../swing/JTable/4222153/bug4222153.html | 31 ++++ .../swing/JTable/4222153/bug4222153.java | 48 +++++ .../KeyBoardNavigation.html | 43 +++++ .../KeyBoardNavigation.java | 170 ++++++++++++++++++ jdk/test/javax/swing/JTable/TAB/TAB.html | 43 +++++ jdk/test/javax/swing/JTable/TAB/TAB.java | 169 +++++++++++++++++ 6 files changed, 504 insertions(+) create mode 100644 jdk/test/javax/swing/JTable/4222153/bug4222153.html create mode 100644 jdk/test/javax/swing/JTable/4222153/bug4222153.java create mode 100644 jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.html create mode 100644 jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.java create mode 100644 jdk/test/javax/swing/JTable/TAB/TAB.html create mode 100644 jdk/test/javax/swing/JTable/TAB/TAB.java diff --git a/jdk/test/javax/swing/JTable/4222153/bug4222153.html b/jdk/test/javax/swing/JTable/4222153/bug4222153.html new file mode 100644 index 00000000000..efa7e634c53 --- /dev/null +++ b/jdk/test/javax/swing/JTable/4222153/bug4222153.html @@ -0,0 +1,31 @@ + + + + +Click in the upper-left cell and then press TAB two times. +If table cell selection is not on the left cell of the second row +then test fails. + + + diff --git a/jdk/test/javax/swing/JTable/4222153/bug4222153.java b/jdk/test/javax/swing/JTable/4222153/bug4222153.java new file mode 100644 index 00000000000..75871c59974 --- /dev/null +++ b/jdk/test/javax/swing/JTable/4222153/bug4222153.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JApplet; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +/** + * @test + * @bug 4222153 + * @author Konstantin Eremin + * @run applet/manual=yesno bug4222153.html + */ +public class bug4222153 extends JApplet { + + public void init() { + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel( + "javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + getContentPane().add(new JTable(2, 2)); + }); + } +} diff --git a/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.html b/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.html new file mode 100644 index 00000000000..324f84be764 --- /dev/null +++ b/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.html @@ -0,0 +1,43 @@ + + + + + + Keyboard Navigation in JTable + + + +

Keyboard Navigation in JTable

+ + + +

+ Refer to bug report 4112270 for spec of keyboard navigation. Check all combinations of navigational keys in all four modes shift and control verifying each change to the selection against the spec. + If it does, press "pass", otherwise press "fail". +


+
Philip Milne
+ + + + diff --git a/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.java b/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.java new file mode 100644 index 00000000000..39ce0acdf3f --- /dev/null +++ b/jdk/test/javax/swing/JTable/KeyBoardNavigation/KeyBoardNavigation.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.DefaultCellEditor; +import javax.swing.JApplet; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + + +/** + * @test + * @bug 4112270 + * @summary + * Keyboard Navigation in JTable + * @author milne + * @run applet/manual=yesno KeyBoardNavigation.html + */ +public class KeyBoardNavigation extends JApplet +{ + static void initTest(Container contentPane) + { + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", new Integer(2), new Boolean(true)}, + {"Tom", "Ball", "Blue", new Integer(99), new Boolean(false)}, + {"Alan", "Chung", "Green", new Integer(838), new Boolean(false)}, + {"Jeff", "Dinkins", "Turquois", new Integer(8), new Boolean(true)}, + {"Amy", "Fowler", "Yellow", new Integer(3), new Boolean(false)}, + {"Brian", "Gerhold", "Green", new Integer(0), new Boolean(false)}, + {"James", "Gosling", "Pink", new Integer(21), new Boolean(false)}, + {"David", "Karlton", "Red", new Integer(1), new Boolean(false)}, + {"Dave", "Kloba", "Yellow", new Integer(14), new Boolean(false)}, + {"Peter", "Korn", "Purple", new Integer(12), new Boolean(false)}, + {"Phil", "Milne", "Purple", new Integer(3), new Boolean(false)}, + {"Dave", "Moore", "Green", new Integer(88), new Boolean(false)}, + {"Hans", "Muller", "Maroon", new Integer(5), new Boolean(false)}, + {"Rick", "Levenson", "Blue", new Integer(2), new Boolean(false)}, + {"Tim", "Prinzing", "Blue", new Integer(22), new Boolean(false)}, + {"Chester", "Rose", "Black", new Integer(0), new Boolean(false)}, + {"Ray", "Ryan", "Gray", new Integer(77), new Boolean(false)}, + {"Georges", "Saab", "Red", new Integer(4), new Boolean(false)}, + {"Willie", "Walker", "Phthalo Blue", new Integer(4), new Boolean(false)}, + {"Kathy", "Walrath", "Blue", new Integer(8), new Boolean(false)}, + {"Arnaud", "Weber", "Green", new Integer(44), new Boolean(false)} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { return names.length; } + public int getRowCount() { return data.length;} + public Object getValueAt(int row, int col) {return data[row][col];} + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) {return names[column];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return true;} + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + contentPane.add(scrollpane); + } + + + public void init() { + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel( + "javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + initTest(getContentPane()); + }); + } +} diff --git a/jdk/test/javax/swing/JTable/TAB/TAB.html b/jdk/test/javax/swing/JTable/TAB/TAB.html new file mode 100644 index 00000000000..7c378253659 --- /dev/null +++ b/jdk/test/javax/swing/JTable/TAB/TAB.html @@ -0,0 +1,43 @@ + + + + + + Tabbing test + + + +

Tabbing test

+ + + +

+ Select a cell by double clicking it, press tab. Check that the focus moves to the next cell. + If it does, press "pass", otherwise press "fail". +


+
Philip Milne
+ + + + diff --git a/jdk/test/javax/swing/JTable/TAB/TAB.java b/jdk/test/javax/swing/JTable/TAB/TAB.java new file mode 100644 index 00000000000..8c4f7035772 --- /dev/null +++ b/jdk/test/javax/swing/JTable/TAB/TAB.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.DefaultCellEditor; +import javax.swing.JApplet; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.BevelBorder; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableModel; + +/** + * @test + * @bug 4128521 + * @summary + * Tabbing test + * @author milne + * @run applet/manual=yesno TAB.html + */ +public class TAB extends JApplet +{ + static void initTest(Container contentPane) + { + // Take the dummy data from SwingSet. + final String[] names = {"First Name", "Last Name", "Favorite Color", + "Favorite Number", "Vegetarian"}; + final Object[][] data = { + {"Mark", "Andrews", "Red", new Integer(2), new Boolean(true)}, + {"Tom", "Ball", "Blue", new Integer(99), new Boolean(false)}, + {"Alan", "Chung", "Green", new Integer(838), new Boolean(false)}, + {"Jeff", "Dinkins", "Turquois", new Integer(8), new Boolean(true)}, + {"Amy", "Fowler", "Yellow", new Integer(3), new Boolean(false)}, + {"Brian", "Gerhold", "Green", new Integer(0), new Boolean(false)}, + {"James", "Gosling", "Pink", new Integer(21), new Boolean(false)}, + {"David", "Karlton", "Red", new Integer(1), new Boolean(false)}, + {"Dave", "Kloba", "Yellow", new Integer(14), new Boolean(false)}, + {"Peter", "Korn", "Purple", new Integer(12), new Boolean(false)}, + {"Phil", "Milne", "Purple", new Integer(3), new Boolean(false)}, + {"Dave", "Moore", "Green", new Integer(88), new Boolean(false)}, + {"Hans", "Muller", "Maroon", new Integer(5), new Boolean(false)}, + {"Rick", "Levenson", "Blue", new Integer(2), new Boolean(false)}, + {"Tim", "Prinzing", "Blue", new Integer(22), new Boolean(false)}, + {"Chester", "Rose", "Black", new Integer(0), new Boolean(false)}, + {"Ray", "Ryan", "Gray", new Integer(77), new Boolean(false)}, + {"Georges", "Saab", "Red", new Integer(4), new Boolean(false)}, + {"Willie", "Walker", "Phthalo Blue", new Integer(4), new Boolean(false)}, + {"Kathy", "Walrath", "Blue", new Integer(8), new Boolean(false)}, + {"Arnaud", "Weber", "Green", new Integer(44), new Boolean(false)} + }; + + // Create a model of the data. + TableModel dataModel = new AbstractTableModel() { + // These methods always need to be implemented. + public int getColumnCount() { return names.length; } + public int getRowCount() { return data.length;} + public Object getValueAt(int row, int col) {return data[row][col];} + + // The default implementations of these methods in + // AbstractTableModel would work, but we can refine them. + public String getColumnName(int column) {return names[column];} + public Class getColumnClass(int c) {return getValueAt(0, c).getClass();} + public boolean isCellEditable(int row, int col) {return true;} + public void setValueAt(Object aValue, int row, int column) { + System.out.println("Setting value to: " + aValue); + data[row][column] = aValue; + } + }; + + // Create the table + JTable tableView = new JTable(dataModel); + // Turn off auto-resizing so that we can set column sizes programmatically. + // In this mode, all columns will get their preferred widths, as set blow. + tableView.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); + + // Create a combo box to show that you can use one in a table. + JComboBox comboBox = new JComboBox(); + comboBox.addItem("Red"); + comboBox.addItem("Orange"); + comboBox.addItem("Yellow"); + comboBox.addItem("Green"); + comboBox.addItem("Blue"); + comboBox.addItem("Indigo"); + comboBox.addItem("Violet"); + + TableColumn colorColumn = tableView.getColumn("Favorite Color"); + // Use the combo box as the editor in the "Favorite Color" column. + colorColumn.setCellEditor(new DefaultCellEditor(comboBox)); + + // Set a pink background and tooltip for the Color column renderer. + DefaultTableCellRenderer colorColumnRenderer = new DefaultTableCellRenderer(); + colorColumnRenderer.setBackground(Color.pink); + colorColumnRenderer.setToolTipText("Click for combo box"); + colorColumn.setCellRenderer(colorColumnRenderer); + + // Set a tooltip for the header of the colors column. + TableCellRenderer headerRenderer = colorColumn.getHeaderRenderer(); + if (headerRenderer instanceof DefaultTableCellRenderer) + ((DefaultTableCellRenderer)headerRenderer).setToolTipText("Hi Mom!"); + + // Set the width of the "Vegetarian" column. + TableColumn vegetarianColumn = tableView.getColumn("Vegetarian"); + vegetarianColumn.setPreferredWidth(100); + + // Show the values in the "Favorite Number" column in different colors. + TableColumn numbersColumn = tableView.getColumn("Favorite Number"); + DefaultTableCellRenderer numberColumnRenderer = new DefaultTableCellRenderer() { + public void setValue(Object value) { + int cellValue = (value instanceof Number) ? ((Number)value).intValue() : 0; + setForeground((cellValue > 30) ? Color.black : Color.red); + setText((value == null) ? "" : value.toString()); + } + }; + numberColumnRenderer.setHorizontalAlignment(JLabel.RIGHT); + numbersColumn.setCellRenderer(numberColumnRenderer); + numbersColumn.setPreferredWidth(110); + + // Finish setting up the table. + JScrollPane scrollpane = new JScrollPane(tableView); + scrollpane.setBorder(new BevelBorder(BevelBorder.LOWERED)); + scrollpane.setPreferredSize(new Dimension(430, 200)); + + contentPane.add(scrollpane); + } + + + public void init() { + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel( + "javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + initTest(getContentPane()); + }); + } +} From aca235b12101c803f3864c5e5c080b110783fb4c Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Thu, 6 Nov 2014 17:39:57 -0500 Subject: [PATCH 004/134] 8062245: Test executes incorrect class Fix issue with test executing incorrect class, and trivial test failure linked to different subclasses of CharSequance. Reviewed-by: jjg --- .../processing/model/type/BoundsTest.java | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/langtools/test/tools/javac/processing/model/type/BoundsTest.java b/langtools/test/tools/javac/processing/model/type/BoundsTest.java index c67f4882a71..23ddcca9d06 100644 --- a/langtools/test/tools/javac/processing/model/type/BoundsTest.java +++ b/langtools/test/tools/javac/processing/model/type/BoundsTest.java @@ -25,7 +25,6 @@ * @test * @bug 6499673 * @library /tools/javac/lib - * @ignore 8062245 Test executes incorrect class * @build JavacTestingAbstractProcessor BoundsTest * @run main BoundsTest * @summary Assertion check for TypeVariable.getUpperBound() fails @@ -86,8 +85,8 @@ public class BoundsTest { }; private static final String[] NoBounds_supers = {}; - private HashSet expected_bounds; - private HashSet expected_supers; + private HashSet expected_bounds; + private HashSet expected_supers; private static final File classesdir = new File("intersectionproperties"); private static final JavaCompiler comp = @@ -99,8 +98,8 @@ public class BoundsTest { final String[] Test_bounds, final String[] Test_supers) throws IOException { System.err.println("Testing " + Test_name); - expected_bounds = new HashSet(Arrays.asList(Test_bounds)); - expected_supers = new HashSet(Arrays.asList(Test_supers)); + expected_bounds = new HashSet<>(Arrays.asList(Test_bounds)); + expected_supers = new HashSet<>(Arrays.asList(Test_supers)); final Iterable files = fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents))); final JavacTask ct = @@ -130,7 +129,7 @@ public class BoundsTest { } public static void main(String... args) throws IOException { - new IntersectionPropertiesTest().run(); + new BoundsTest().run(); } private static File writeFile(File dir, String path, String body) @@ -166,18 +165,17 @@ public class BoundsTest { final List bounds = typeParameterElement.getBounds(); final List supers = processingEnv.getTypeUtils().directSupertypes(upperBound); - final HashSet actual_bounds = new HashSet(); - final HashSet actual_supers = new HashSet(); + final HashSet actual_bounds = new HashSet<>(); + final HashSet actual_supers = new HashSet<>(); for(TypeMirror ty : bounds) { - actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName()); + actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString()); } for(TypeMirror ty : supers) { - actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName()); + actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString()); } - if (!expected_bounds.equals(actual_bounds)) { System.err.println("Mismatched expected and actual bounds."); System.err.println("Expected:"); @@ -190,7 +188,7 @@ public class BoundsTest { } if (!expected_supers.equals(actual_supers)) { - System.err.println("Mismatched expected and actual bounds."); + System.err.println("Mismatched expected and actual supers."); System.err.println("Expected:"); for(CharSequence tm : expected_supers) System.err.println(" " + tm); From ab1b9a9cf13b0f208bb413bb8b9a96cd44045a0c Mon Sep 17 00:00:00 2001 From: Eric McCorkle Date: Fri, 7 Nov 2014 07:54:35 -0500 Subject: [PATCH 005/134] 8029012: parameter_index for type annotation not updated after outer.this added Fix javac's handling of type annotations when synthetic parameters are added Reviewed-by: jjg, mcimadamore --- .../javac/code/TypeAnnotationPosition.java | 2 +- .../com/sun/tools/javac/comp/Lower.java | 20 +- .../classfile/ClassfileInspector.java | 950 ++++++++++++++++++ .../classfile/SyntheticParameters.java | 130 +++ .../referenceinfos/Constructors.java | 12 +- 5 files changed, 1104 insertions(+), 10 deletions(-) create mode 100644 langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java create mode 100644 langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index fdf746f6d0d..d3aecdb2126 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -145,7 +145,7 @@ public class TypeAnnotationPosition { public final int bound_index; // For type parameter and method parameter - public final int parameter_index; + public int parameter_index; // For class extends, implements, and throws clauses public final int type_index; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java index ac78ad720bc..1a470cc9112 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java @@ -2642,9 +2642,10 @@ public class Lower extends TreeTranslator { syms.intType, tree.sym); ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC; - tree.params = tree.params.prepend(ordParam).prepend(nameParam); - MethodSymbol m = tree.sym; + tree.params = tree.params.prepend(ordParam).prepend(nameParam); + incrementParamTypeAnnoIndexes(m, 2); + m.extraParams = m.extraParams.prepend(ordParam.sym); m.extraParams = m.extraParams.prepend(nameParam.sym); Type olderasure = m.erasure(types); @@ -2667,6 +2668,17 @@ public class Lower extends TreeTranslator { } } //where + private void incrementParamTypeAnnoIndexes(MethodSymbol m, + int amount) { + for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) { + // Increment the parameter_index of any existing formal + // parameter annotations. + if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) { + anno.position.parameter_index += amount; + } + } + } + private void visitMethodDefInternal(JCMethodDecl tree) { if (tree.name == names.init && (currentClass.isInner() || currentClass.isLocal())) { @@ -2697,8 +2709,10 @@ public class Lower extends TreeTranslator { // Add this$n (if needed) in front of and free variables behind // constructor parameter list. tree.params = tree.params.appendList(fvdefs); - if (currentClass.hasOuterInstance()) + if (currentClass.hasOuterInstance()) { tree.params = tree.params.prepend(otdef); + incrementParamTypeAnnoIndexes(m, 1); + } // If this is an initial constructor, i.e., it does not start with // this(...), insert initializers for this$n and proxies diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java new file mode 100644 index 00000000000..864787e2f3a --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/ClassfileInspector.java @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.*; +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/** + * A class providing utilities for writing tests that inspect class + * files directly, looking for specific type annotations. + * + * Note: this framework does not currently handle repeating + * annotations. + */ +public class ClassfileInspector { + + /** + * A group of expected annotations to be found in a given class. + * If the class name is null, then the template will be applied to + * every class. + */ + public static class Expected { + /** + * The name of the class. If {@code null} this template will + * apply to every class; otherwise, it will only be applied to + * the named class. + */ + public final String classname; + + /** + * The expected class annotations. These will be checked + * against the class' attributes. + */ + public final ExpectedTypeAnnotation[] classAnnos; + + /** + * The expected method annotations. These will be checked + * against all methods in the class. + */ + public final ExpectedMethodTypeAnnotation[] methodAnnos; + + /** + * The expected field annotations. These will be checked + * against all fields in the class. + */ + public final ExpectedFieldTypeAnnotation[] fieldAnnos; + + /** + * Create an {@code Expected} from its components. + * + * @param classname The name of the class to match, or {@code + * null} for all classes. + * @param classAnnos The expected class annotations. + * @param methodAnnos The expected method annotations. + * @param fieldAnnos The expected field annotations. + */ + public Expected(String classname, + ExpectedTypeAnnotation[] classAnnos, + ExpectedMethodTypeAnnotation[] methodAnnos, + ExpectedFieldTypeAnnotation[] fieldAnnos) { + this.classname = classname; + this.classAnnos = classAnnos; + this.methodAnnos = methodAnnos; + this.fieldAnnos = fieldAnnos; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + final String newline = System.lineSeparator(); + sb.append("Expected on class ").append(classname); + if (null != classAnnos) { + sb.append(newline).append("Class annotations:").append(newline); + for(ExpectedTypeAnnotation anno : classAnnos) { + sb.append(anno).append(newline); + } + } + if (null != methodAnnos) { + sb.append(newline).append("Method annotations:").append(newline); + for(ExpectedTypeAnnotation anno : methodAnnos) { + sb.append(anno).append(newline); + } + } + if (null != fieldAnnos) { + sb.append(newline).append("Field annotations:").append(newline); + for(ExpectedTypeAnnotation anno : fieldAnnos) { + sb.append(anno).append(newline); + } + } + return sb.toString(); + } + + /** + * See if this template applies to a class. + * + * @param classname The classname to check. + * @return Whether or not this template should apply. + */ + public boolean matchClassName(String classname) { + return this.classname == null || this.classname.equals(classname); + } + + /** + * After applying the template to all classes, check to see if + * any of the expected annotations weren't matched. + * + * @return The number of missed matches. + */ + public int check() { + int count = 0; + if (classAnnos != null) { + for(ExpectedTypeAnnotation expected : classAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (methodAnnos != null) { + for(ExpectedMethodTypeAnnotation expected : methodAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (fieldAnnos != null) { + for(ExpectedFieldTypeAnnotation expected : fieldAnnos) { + if (!expected.check()) { + count++; + } + } + } + return count; + } + } + + /** + * An expected type annotation. This is both a superclass for + * method and field type annotations, as well as a class for type + * annotations on a class. + */ + public static class ExpectedTypeAnnotation { + private int count = 0; + protected final String expectedName; + protected final int expectedCount; + protected final TypeAnnotation.TargetType targetType; + protected final int bound_index; + protected final int parameter_index; + protected final int type_index; + protected final int exception_index; + protected final TypeAnnotation.Position.TypePathEntry[] typePath; + protected final boolean visibility; + + /** + * Create an {@code ExpectedTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should + * be seen. If 0, this asserts that the + * described annotation is not present. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedTypeAnnotation(String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + this.expectedName = expectedName; + this.visibility = visibility; + this.expectedCount = expectedCount; + this.targetType = targetType; + this.bound_index = bound_index; + this.parameter_index = parameter_index; + this.type_index = type_index; + this.exception_index = exception_index; + this.typePath = typePath; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(targetType); + sb.append(", bound_index = "); + sb.append(bound_index); + sb.append(", parameter_index = "); + sb.append(parameter_index); + sb.append(", type_index = "); + sb.append(type_index); + sb.append(", exception_index = "); + sb.append(exception_index); + sb.append(", type_path = ["); + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]"); + return sb.toString(); + } + + /** + * See if this template matches the given visibility. + * + * @param Whether or not the annotation is visible at runtime. + * @return Whether or not this template matches the visibility. + */ + public boolean matchVisibility(boolean visibility) { + return this.visibility == visibility; + } + + /** + * Attempty to match this template against an annotation. If + * it does match, then the match count for the template will + * be incremented. Otherwise, nothing will be done. + * + * @param anno The annotation to attempt to match. + */ + public void matchAnnotation(TypeAnnotation anno) { + boolean matches = true; + + try { + matches = anno.constant_pool.getUTF8Info(anno.annotation.type_index).value.equals("L" + expectedName + ";"); + } catch(Exception e) { + matches = false; + } + + matches = matches && anno.position.type == targetType; + matches = matches && anno.position.bound_index == bound_index; + matches = matches && anno.position.parameter_index == parameter_index; + matches = matches && anno.position.type_index == type_index; + matches = matches && anno.position.exception_index == exception_index; + matches = matches && anno.position.location.size() == typePath.length; + + if (matches) { + int i = 0; + for(TypeAnnotation.Position.TypePathEntry entry : + anno.position.location) { + matches = matches && typePath[i++].equals(entry); + } + } + + if (matches) { + count++; + } + } + + /** + * After all matching, check to see if the expected number of + * matches equals the actual number. If not, then print a + * failure message and return {@code false}. + * + * @return Whether or not the expected number of matched + * equals the actual number. + */ + public boolean check() { + if (count != expectedCount) { + System.err.println(this + ", but saw " + count); + return false; + } else { + return true; + } + } + + /** + * A builder class for creating {@code + * ExpectedTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder { + protected final String expectedName; + protected final int expectedCount; + protected final TypeAnnotation.TargetType targetType; + protected final boolean visibility; + protected int bound_index = Integer.MIN_VALUE; + protected int parameter_index = Integer.MIN_VALUE; + protected int type_index = Integer.MIN_VALUE; + protected int exception_index = Integer.MIN_VALUE; + protected TypeAnnotation.Position.TypePathEntry[] typePath = + new TypeAnnotation.Position.TypePathEntry[0]; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + this.expectedName = expectedName; + this.visibility = visibility; + this.expectedCount = expectedCount; + this.targetType = targetType; + } + + /** + * Create an {@code ExpectedTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedTypeAnnotation}. + */ + public ExpectedTypeAnnotation build() { + return new ExpectedTypeAnnotation(expectedName, visibility, + expectedCount, targetType, + bound_index, parameter_index, + type_index, exception_index, + typePath); + } + + /** + * Provide a bound index parameter. + * + * @param bound_index The bound_index value. + */ + public Builder setBoundIndex(int bound_index) { + this.bound_index = bound_index; + return this; + } + + /** + * Provide a parameter index parameter. + * + * @param bound_index The parameter_index value. + */ + public Builder setParameterIndex(int parameter_index) { + this.parameter_index = parameter_index; + return this; + } + + /** + * Provide a type index parameter. + * + * @param type_index The type_index value. + */ + public Builder setTypeIndex(int type_index) { + this.type_index = type_index; + return this; + } + + /** + * Provide an exception index parameter. + * + * @param exception_index The exception_index value. + */ + public Builder setExceptionIndex(int exception_index) { + this.exception_index = exception_index; + return this; + } + + /** + * Provide a type path parameter. + * + * @param typePath The type path value. + */ + public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) { + this.typePath = typePath; + return this; + } + } + } + + /** + * A type annotation found on a method. + */ + public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation { + private final String methodname; + + /** + * Create an {@code ExpectedMethodTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param methodname The expected method name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedMethodTypeAnnotation(String methodname, + String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + super(expectedName, visibility, expectedCount, targetType, bound_index, + parameter_index, type_index, exception_index, typePath); + this.methodname = methodname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(targetType); + sb.append(", bound_index = "); + sb.append(bound_index); + sb.append(", parameter_index = "); + sb.append(parameter_index); + sb.append(", type_index = "); + sb.append(type_index); + sb.append(", exception_index = "); + sb.append(exception_index); + sb.append(", type_path = ["); + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]"); + sb.append(" on method "); + sb.append(methodname); + return sb.toString(); + } + + /** + * See if this template applies to a method. + * + * @param methodname The method name to check. + * @return Whether or not this template should apply. + */ + public boolean matchMethodName(String methodname) { + return this.methodname.equals(methodname); + } + + /** + * A builder class for creating {@code + * ExpectedMethodTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedMethodTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedMethodTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder extends ExpectedTypeAnnotation.Builder { + protected final String methodname; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param methodname The expected method name. + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String methodname, + String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + super(expectedName, targetType, visibility, expectedCount); + this.methodname = methodname; + } + + /** + * Create an {@code ExpectedMethodTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedMethodTypeAnnotation}. + */ + public ExpectedMethodTypeAnnotation build() { + return new ExpectedMethodTypeAnnotation(methodname, expectedName, + visibility, expectedCount, + targetType, bound_index, + parameter_index, type_index, + exception_index, typePath); + } + } + } + + /** + * A type annotation found on a field. + */ + public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation { + private final String fieldname; + + /** + * Create an {@code ExpectedFieldTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param fieldname The expected field name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedFieldTypeAnnotation(String fieldname, + String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + super(expectedName, visibility, expectedCount, targetType, bound_index, + parameter_index, type_index, exception_index, typePath); + this.fieldname = fieldname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected ").append(expectedCount) + .append(" annotation ").append(expectedName) + .append(visibility ? ", runtime visibile " : ", runtime invisibile ") + .append(targetType) + .append(", bound_index = ").append(bound_index) + .append(", parameter_index = ").append(parameter_index) + .append(", type_index = ").append(type_index) + .append(", exception_index = ").append(exception_index) + .append(", type_path = ["); + + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]") + .append(" on field ").append(fieldname); + return sb.toString(); + } + + /** + * See if this template applies to a field. + * + * @param fieldname The field name to check. + * @return Whether or not this template should apply. + */ + public boolean matchFieldName(String fieldname) { + return this.fieldname.equals(fieldname); + } + + /** + * A builder class for creating {@code + * ExpectedFieldTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedFieldTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedFieldTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder extends ExpectedTypeAnnotation.Builder { + protected final String fieldname; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param fieldname The expected field name. + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String fieldname, + String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + super(expectedName, targetType, visibility, expectedCount); + this.fieldname = fieldname; + } + + /** + * Create an {@code ExpectedFieldTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedFieldTypeAnnotation}. + */ + public ExpectedFieldTypeAnnotation build() { + return new ExpectedFieldTypeAnnotation(fieldname, expectedName, + visibility, expectedCount, + targetType, bound_index, + parameter_index, type_index, + exception_index, typePath); + } + } + } + + private void matchClassTypeAnnotation(ClassFile classfile, + ExpectedTypeAnnotation expected) + throws ConstantPoolException { + for(Attribute attr : classfile.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + + private void matchMethodTypeAnnotation(ClassFile classfile, + ExpectedMethodTypeAnnotation expected) + throws ConstantPoolException { + for(Method meth : classfile.methods) { + if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { + for(Attribute attr : meth.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + } + } + + private void matchFieldTypeAnnotation(ClassFile classfile, + ExpectedFieldTypeAnnotation expected) + throws ConstantPoolException { + for(Field field : classfile.fields) { + if (expected.matchFieldName(field.getName(classfile.constant_pool))) { + for(Attribute attr : field.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + } + } + + private void matchClassTypeAnnotations(ClassFile classfile, + ExpectedTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedTypeAnnotation one : expected) { + matchClassTypeAnnotation(classfile, one); + } + } + + private void matchMethodTypeAnnotations(ClassFile classfile, + ExpectedMethodTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedMethodTypeAnnotation one : expected) { + matchMethodTypeAnnotation(classfile, one); + } + } + + private void matchFieldTypeAnnotations(ClassFile classfile, + ExpectedFieldTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedFieldTypeAnnotation one : expected) { + matchFieldTypeAnnotation(classfile, one); + } + } + + /** + * Run a template on a single {@code ClassFile}. + * + * @param classfile The {@code ClassFile} on which to run tests. + * @param expected The expected annotation template. + */ + public void run(ClassFile classfile, + Expected... expected) + throws ConstantPoolException { + run(new ClassFile[] { classfile }, expected); + } + + /** + * Run a template on multiple {@code ClassFile}s. + * + * @param classfile The {@code ClassFile}s on which to run tests. + * @param expected The expected annotation template. + */ + public void run(ClassFile[] classfiles, + Expected... expected) + throws ConstantPoolException { + for(ClassFile classfile : classfiles) { + for(Expected one : expected) { + if (one.matchClassName(classfile.getName())) { + if (one.classAnnos != null) + matchClassTypeAnnotations(classfile, one.classAnnos); + if (one.methodAnnos != null) + matchMethodTypeAnnotations(classfile, one.methodAnnos); + if (one.fieldAnnos != null) + matchFieldTypeAnnotations(classfile, one.fieldAnnos); + } + } + } + int count = 0; + for (Expected one : expected) { + count += one.check(); + } + + if (count != 0) { + throw new RuntimeException(count + " errors occurred in test"); + } + } + + /** + * Get a {@code ClassFile} from its file name. + * + * @param name The class' file name. + * @return The {@code ClassFile} + */ + public static ClassFile getClassFile(String name) + throws IOException, ConstantPoolException { + final URL url = ClassfileInspector.class.getResource(name); + final InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + private static final Attribute.Visitor typeAnnoMatcher = + new Attribute.Visitor() { + + @Override + public Void visitBootstrapMethods(BootstrapMethods_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitDefault(DefaultAttribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCode(Code_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCompilationID(CompilationID_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitConstantValue(ConstantValue_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitDeprecated(Deprecated_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitExceptions(Exceptions_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitInnerClasses(InnerClasses_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLineNumberTable(LineNumberTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitMethodParameters(MethodParameters_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSignature(Signature_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceFile(SourceFile_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceID(SourceID_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitStackMap(StackMap_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitStackMapTable(StackMapTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSynthetic(Synthetic_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + if (expected.matchVisibility(true)) { + for(TypeAnnotation anno : attr.annotations) { + expected.matchAnnotation(anno); + } + } + + return null; + } + + @Override + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + if (expected.matchVisibility(false)) { + for(TypeAnnotation anno : attr.annotations) { + expected.matchAnnotation(anno); + } + } + + return null; + } + }; +} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java new file mode 100644 index 00000000000..35477d21086 --- /dev/null +++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014, 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 SyntheticParameters + * @summary Test generation of annotations on inner class parameters. + * @build ClassfileInspector + * @run main SyntheticParameters + */ + +import java.io.*; +import java.lang.annotation.*; + +import com.sun.tools.classfile.*; + +public class SyntheticParameters extends ClassfileInspector { + + private static final String Inner_class = "SyntheticParameters$Inner.class"; + private static final String Foo_class = "SyntheticParameters$Foo.class"; + private static final Expected Inner_expected = + new Expected("SyntheticParameters$Inner", + null, + new ExpectedMethodTypeAnnotation[] { + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // this$0 parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(1).build(), + (ExpectedMethodTypeAnnotation) + new ExpectedMethodTypeAnnotation.Builder( + "foo", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + new ExpectedMethodTypeAnnotation.Builder( + "foo", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(1).build() + }, + null); + private static final Expected Foo_expected = + new Expected("SyntheticParameters$Foo", + null, + new ExpectedMethodTypeAnnotation[] { + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // $enum$name parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // $enum$ordinal parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(1).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(2).build() + }, + null); + + public static void main(String... args) throws Exception { + new SyntheticParameters().run( + new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) }, + new Expected[] { Inner_expected, Foo_expected }); + } + + public class Inner { + public Inner(@A int a) {} + public void foo(@A int a, int b) {} + } + + public static enum Foo { + ONE(null); + Foo(@A Object a) {} + } +} + +@Target({ElementType.TYPE_USE}) +@interface A {} diff --git a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java index 78e9acab2ab..2775fdd9790 100644 --- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java +++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java @@ -43,7 +43,7 @@ public class Constructors { @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0}) @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}) - @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("%TEST_CLASS_NAME%$Inner") public String innerClass() { return "class %TEST_CLASS_NAME% { class Inner {" + @@ -56,7 +56,7 @@ public class Constructors { @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}) @TADescription(annotation = "TC", type = METHOD_RECEIVER) @TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0}) - @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("%TEST_CLASS_NAME%$Inner") public String innerClass2() { return "class %TEST_CLASS_NAME% { class Inner {" + @@ -70,7 +70,7 @@ public class Constructors { @TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}) @TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0}) @TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}) - @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("Outer$Middle$Inner") public String innerClass3() { return "class Outer { class Middle { class Inner {" + @@ -89,7 +89,7 @@ public class Constructors { @TADescription(annotation = "RTAs", type = METHOD_RETURN, genericLocation = {1, 0}) @TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0}) - @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("%TEST_CLASS_NAME%$Inner") public String innerClassRepeatableAnnotation() { return "class %TEST_CLASS_NAME% { class Inner {" + @@ -102,7 +102,7 @@ public class Constructors { @TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0}) @TADescription(annotation = "RTCs", type = METHOD_RECEIVER) @TADescription(annotation = "RTDs", type = METHOD_RETURN, genericLocation = {1, 0}) - @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("%TEST_CLASS_NAME%$Inner") public String innerClassRepeatableAnnotation2() { return "class %TEST_CLASS_NAME% { class Inner {" + @@ -116,7 +116,7 @@ public class Constructors { @TADescription(annotation = "RTCs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}) @TADescription(annotation = "RTDs", type = METHOD_RECEIVER, genericLocation = {1, 0}) @TADescription(annotation = "RTEs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}) - @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) @TestClass("Outer$Middle$Inner") public String innerClassRepatableAnnotation3() { return "class Outer { class Middle { class Inner {" + From 3f3f44af47cd52b4d03ed169cecbeac3e4bd33a1 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 7 Nov 2014 18:22:36 +0100 Subject: [PATCH 006/134] 8058489: More adjustments of langtools/make/build.xml to modularized layout Re-structuring the langtools/make/build.xml to reflect the modular layout, cleanup of the build script Reviewed-by: jjg, mcimadamore, ksrini --- langtools/make/build.properties | 191 +--- langtools/make/build.xml | 971 +++++------------- langtools/make/launcher.sh-template | 9 +- langtools/make/netbeans/langtools/build.xml | 127 ++- .../netbeans/langtools/nbproject/project.xml | 42 +- .../make/tools/anttasks/SelectToolTask.java | 54 +- 6 files changed, 420 insertions(+), 974 deletions(-) diff --git a/langtools/make/build.properties b/langtools/make/build.properties index 9d92c73944c..b224a9721d2 100644 --- a/langtools/make/build.properties +++ b/langtools/make/build.properties @@ -23,25 +23,46 @@ # questions. # -# This is the JDK used to build and run the bootstrap version of javac. -# The bootstrap javac is used to compile both boostrap versions of the -# other tools, and product versions of all the tools. -# Override this path as needed, either on the command line or in -# one of the standard user build.properties files (see build.xml) +#javac configuration for "normal build" (these will be passed to the bootstrap compiler): +javac.debug = true +javac.debuglevel = source,lines,vars +javac.extra.opts=-XDignore.symbol.file=true +javac.includes= +javac.lint.opts = -Xlint:all,-deprecation -Werror +javac.source = 8 +javac.target = 8 -# boot.java.home = /opt/jdk/1.7.0 -boot.java = ${boot.java.home}/bin/java -boot.javac = ${boot.java.home}/bin/javac +#javac configuration for bootstrap build (these will be passed to the compiler from the given boot JDK): +boot.javac.extra.opts=-XDignore.symbol.file=true +boot.javac.includes = \ + javax/annotation/processing/ \ + javax/lang/model/ \ + javax/tools/ \ + jdk/ \ + com/sun/source/ \ + com/sun/tools/javac/ \ + com/sun/tools/doclint/ +boot.javac.lint.opts= boot.javac.source = 8 boot.javac.target = 8 -# This is the JDK used to run the product version of the tools, -# for example, for testing. If you're building a complete JDK, specify that. -# Override this path as needed, either on the command line or in -# one of the standard user build.properties files (see build.xml) +#configuration of submodules (share by both the bootstrap and normal compilation): +langtools.modules=java.base:java.compiler:jdk.compiler:jdk.dev:jdk.javadoc +java.base.dependencies= +java.compiler.dependencies=java.base +jdk.compiler.dependencies=java.base:java.compiler +jdk.javadoc.dependencies=java.base:java.compiler:jdk.compiler +jdk.dev.dependencies=java.base:java.compiler:jdk.compiler -# target.java.home = /opt/jdk/1.8.0 -target.java = ${target.java.home}/bin/java +#test configuration: +jtreg.tests= +boot.javac.tests = tools/javac +crules.tests = ../make/test/crules + +#javadoc configuration +javadoc.jls.cite=The Java™ Language Specification +javadoc.jls.option=-tag "jls:a:See <cite>${javadoc.jls.cite}</cite>:" \ + -tag "implNote:a:Implementation Note:" # Version info -- override as needed jdk.version = 1.9.0 @@ -55,146 +76,4 @@ milestone = internal # timestamps # FIXME -- need to include openjdk as needed release = ${jdk.version}-${milestone} -bootstrap.release = ${release}_bootstrap full.version = ${release}-${build.number} -bootstrap.full.version = ${bootstrap.release}-${build.number} - -# options for the tasks used to compile the tools -javac.source = 8 -javac.target = 8 -javac.debug = true -javac.debuglevel = source,lines -javac.no.jdk.warnings = -XDignore.symbol.file=true -# set the following to -version to verify the versions of javac being used -javac.version.opt = -# in time, there should be no exceptions to -Xlint:all -javac.lint.opts = -Xlint:all,-deprecation -Werror - -# options for the task for javac -#javadoc.jls3.url=http://java.sun.com/docs/books/jls/ -#javadoc.jls3.cite=<a href="${javadoc.jls3.url}">The Java Language Specification, Third Edition</a> -#javadoc.jls3.option=-tag "jls3:a:See <cite>${javadoc.jls3.cite}</cite>:" - - -javadoc.jls.cite=The Java™ Language Specification - -javadoc.jls.option=-tag "jls:a:See <cite>${javadoc.jls.cite}</cite>:" - - - - - -# jtreg, used to run the JDK regression tests -# See http://openjdk.java.net/jtreg/ -# Override this path as needed, either on the command line or in -# one of the standard user build.properties files (see build.xml) - -# jtreg.home = /opt/jtreg/4.1 - -# findbugs -# See http://findbugs.sourceforge.net/ -# Override this path as needed, either on the command line or in -# one of the standard user build.properties files (see build.xml) - -# findbugs.home = /opt/findbugs/1.2.1 - -# vizant (graph visualization tool for Ant) -# See http://vizant.sourceforge.net/ -# Override this path as needed, either on the command line or in -# one of the standard user build.properties files (see build.xml) - -# vizant.jar = /opt/vizant/0.1.2/vizant-0.1.2.jar -# dot = dot - -#------------------------------------------------------------ - -# The following properties define the packages for each of the tools. -# Syntactically, they should be suitable as arguments for the "includes" -# parameter of Ant filesets. In particular, note the trailing '/'. - -javac.includes = \ - javax/annotation/processing/ \ - javax/lang/model/ \ - javax/tools/ \ - jdk/ \ - com/sun/source/ \ - com/sun/tools/javac/ \ - com/sun/tools/doclint/ - -javac.tests = \ - tools/javac - -# - -javadoc.includes = \ - com/sun/javadoc/ \ - com/sun/tools/javadoc/ \ - com/sun/tools/doclets/ - -javadoc.tests = \ - tools/javadoc/ \ - com/sun/javadoc/ - -# - -javah.includes = \ - com/sun/tools/javah/ - -javah.tests = \ - tools/javah/ - -# - -javap.includes = \ - com/sun/tools/classfile/ \ - com/sun/tools/javap/ \ - com/sun/tools/jdeps/ \ - sun/tools/javap/ - -javap.tests = \ - tools/javap/ - -# - -sjavac.includes = \ - com/sun/tools/sjavac/ - -sjavac.tests = \ - tools/sjavac - -crules.tests = ../make/test/crules - -# - -# The following files require the latest JDK to be available. -# The API can be provided by using a suitable boot.java.home -# or by setting import.jdk -require.latest.jdk.files = \ - com/sun/tools/javac/nio/*.java - -# The following files in the import jdk source directory are required -# in order to compile the files defined in ${require.latest.jdk.files} -# -# For NIO, the list of stub files is defined by the contents of the primary -# API packages, together with such types that may be required in order to -# compile the stubs. Some of these dependencies would go away if the stub -# generator were to be improved -- e.g. by removing unnecessary imports. -# -import.jdk.stub.files = \ - java/io/File.java \ - java/nio/file/**.java \ - java/nio/file/attribute/**.java \ - java/nio/file/spi/**.java \ - java/nio/channels/AsynchronousChannel.java \ - java/nio/channels/AsynchronousFileChannel.java \ - java/nio/channels/CompletionHandler.java \ - java/nio/channels/SeekableByteChannel.java - -# The following value is used by the main jtreg target. -# An empty value means all tests -# Override as desired to run a specific set of tests -jtreg.tests = - -# Check style configuration -# overridable name and version -checkstyle.name.version = checkstyle-5.4 diff --git a/langtools/make/build.xml b/langtools/make/build.xml index 2d4488d4f3f..d2e543a6d56 100644 --- a/langtools/make/build.xml +++ b/langtools/make/build.xml @@ -25,10 +25,10 @@ --> @@ -99,13 +68,6 @@ **** Global property definitions. --> - - - - - @@ -119,36 +81,24 @@ - - - - - - + + - + - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -325,9 +254,13 @@ warningsProperty="findbugs.all.warnings" jvm="${target.java.home}/bin/java" jvmargs="-Xmx512M"> - + + + + + - + @@ -339,49 +272,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -391,7 +282,7 @@ destdir="${build.dir}/diag-examples/classes" includes="ArgTypeCompilerFactory.java,Example.java,FileManager.java,HTMLWriter.java,RunExamples.java,DocCommentProcessor.java" sourcepath="" - classpath="${dist.lib.dir}/javac.jar;${dist.lib.dir}/javap.jar" + classpath="${langtools.classes}" includeAntRuntime="no" debug="${javac.debug}" debuglevel="${javac.debuglevel}"> @@ -400,7 +291,7 @@ @@ -413,56 +304,16 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + @@ -515,17 +365,12 @@ - + - - - ant.home = ${ant.home} @@ -536,257 +381,32 @@ checkstyle.home = ${checkstyle.home} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + crules.CodingRulesAnalyzerPlugin - - - - - - - - - - - + extra.jvmargs="-Xbootclasspath/a:${build.crules.dir}/classes" /> - - + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + @@ -866,84 +516,73 @@ - - - - - - - - + + + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - + + + - - + + - - + + + + + + + + + + + + + + + + + - + - + @@ -957,13 +596,20 @@ + + + + + + + - - - - - + + + + - + - + @@ -991,42 +636,15 @@ - + - - - - - - - - - - - - - - - - + + @@ -1048,55 +666,9 @@ classpath="${build.toolclasses.dir}/"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1106,7 +678,7 @@
Unofficial Javadoc generated from developer sources for preview purposes only]]>
- - - + - + - + - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1184,6 +729,7 @@ + @@ -1191,6 +737,7 @@ + @@ -1204,7 +751,7 @@ samevm="@{samevm}" verbose="@{verbose}" failonerror="false" resultproperty="jtreg.@{name}.result" javacoptions="-g" - vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}${build.classes.dir} @{jpda.jvmargs} @{extra.jvmargs}"> + vmoptions="${coverage.options} -Xbootclasspath/p:${coverage.classpath}${path.separator}@{langtools.classes} @{jpda.jvmargs} @{extra.jvmargs}"> @@ -1220,21 +767,12 @@
- - - - - - - - - - - + - + + + @@ -1265,7 +803,7 @@ jvmargs="-Xmx512M" > - + @@ -1276,11 +814,6 @@ - - - - - diff --git a/langtools/make/launcher.sh-template b/langtools/make/launcher.sh-template index 05d765022f2..f82d610564d 100644 --- a/langtools/make/launcher.sh-template +++ b/langtools/make/launcher.sh-template @@ -43,10 +43,9 @@ mylib="$mydir/../lib" # dependent jar files for additional dependencies. if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then - cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF | - grep "Class-Path:" | - sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'` - bcp="$mylib/#PROGRAM#.jar#PS#$cp" + cp=`echo "$mylib"/*.jar | + sed -e 's|\([a-z.]*\.jar\) *|\1#PS#|g'` + bcp=$cp fi # tools currently assumes that assertions are enabled in the launcher @@ -72,4 +71,4 @@ done unset DUALCASE IFS=$nl -"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} -jar "${mylib}/#PROGRAM#.jar" ${toolOpts} +"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} com.sun.tools.#PROGRAM#.Main ${toolOpts} diff --git a/langtools/make/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml index 4e85a1e4790..bb57ee77a8a 100644 --- a/langtools/make/netbeans/langtools/build.xml +++ b/langtools/make/netbeans/langtools/build.xml @@ -46,48 +46,34 @@ --> - + - - - - - - - - - - - - - + + + - - - - + - + Must set property 'includes' - + + debuglevel="${javac.debuglevel}"> + + - + + + + + + + + - + Must set property 'run.classname' @@ -115,22 +109,22 @@ test all tools. --> - - - - + + + - + - + - + @@ -165,7 +159,7 @@ - + @@ -179,20 +173,29 @@ - + Must set property 'jtreg.tests' - + - + Must set property 'class' + + + @@ -205,31 +208,10 @@ test all tools. --> - - - - - - - - - - - - - - - - - - - + - - + @@ -253,6 +235,15 @@ /> + + + + + + + + + @@ -262,7 +253,7 @@ - + @@ -278,11 +269,11 @@ - + - + compile-single - src/java.base/share/classes + java.base includes ${root}/src/java.base/share/classes @@ -120,7 +120,7 @@ compile-single - src/java.compiler/share/classes + java.compiler includes ${root}/src/java.compiler/share/classes @@ -133,7 +133,7 @@ compile-single - src/jdk.compiler/share/classes + jdk.compiler includes ${root}/src/jdk.compiler/share/classes @@ -146,7 +146,7 @@ compile-single - src/jdk.dev/share/classes + jdk.dev includes ${root}/src/jdk.dev/share/classes @@ -159,7 +159,7 @@ compile-single - src/jdk.javadoc/share/classes + jdk.javadoc includes ${root}/src/jdk.javadoc/share/classes @@ -333,7 +333,7 @@ debug-fix - src/java.base/share/classes + java.base class ${root}/src/java.base/share/classes @@ -346,7 +346,7 @@ debug-fix - src/java.compiler/share/classes + java.compiler class ${root}/src/java.compiler/share/classes @@ -359,7 +359,7 @@ debug-fix - src/jdk.compiler/share/classes + jdk.compiler class ${root}/src/jdk.compiler/share/classes @@ -372,7 +372,7 @@ debug-fix - src/jdk.dev/share/classes + jdk.dev class ${root}/src/jdk.dev/share/classes @@ -385,7 +385,7 @@ debug-fix - src/jdk.dev/share/classes + jdk.javadoc class ${root}/src/jdk.javadoc/share/classes @@ -478,11 +478,31 @@ ${root}/src/java.base/share/classes + ${root}/build/java.base/classes + 1.8 + + ${root}/src/java.compiler/share/classes + ${root}/build/java.base/classes + ${root}/build/java.compiler/classes + 1.8 + + ${root}/src/jdk.compiler/share/classes + ${root}/build/java.base/classes:${root}/build/java.compiler/classes + ${root}/build/jdk.compiler/classes + 1.8 + + ${root}/src/jdk.dev/share/classes + ${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes + ${root}/build/jdk.dev/classes + 1.8 + + ${root}/src/jdk.javadoc/share/classes - ${root}/build/classes + ${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes + ${root}/build/jdk.javadoc/classes 1.8 diff --git a/langtools/make/tools/anttasks/SelectToolTask.java b/langtools/make/tools/anttasks/SelectToolTask.java index a26bc3e689f..db4451db5ab 100644 --- a/langtools/make/tools/anttasks/SelectToolTask.java +++ b/langtools/make/tools/anttasks/SelectToolTask.java @@ -74,7 +74,18 @@ public class SelectToolTask extends Task { enum ToolChoices { NONE(""), - JAVAC("javac"), + BOOSTRAP_JAVAC("bootstrap-javac", true) { + @Override + public ToolChoices baseTool() { + return JAVAC; + } + }, + JAVAC("javac") { + @Override + public ToolChoices asBootstrap() { + return BOOSTRAP_JAVAC; + } + }, JAVADOC("javadoc"), JAVAH("javah"), JAVAP("javap"); @@ -91,6 +102,14 @@ public class SelectToolTask extends Task { this.bootstrap = bootstrap; } + public ToolChoices asBootstrap() { + return this; + } + + public ToolChoices baseTool() { + return this; + } + @Override public String toString() { return toolName; @@ -176,9 +195,11 @@ public class SelectToolTask extends Task { JOptionPane p = createPane(guiProps); p.createDialog("Select Tool").setVisible(true); - toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; + ToolChoices tool = (ToolChoices)toolChoice.getSelectedItem(); + + toolName = tool.baseTool().toolName; + toolBootstrap = tool.bootstrap; toolArgs = argsField.getText(); - toolBootstrap = bootstrapCheckbox.isSelected(); if (defaultCheck.isSelected()) { if (toolName.equals("")) { fileProps.remove("tool.name"); @@ -213,30 +234,31 @@ public class SelectToolTask extends Task { EnumSet toolChoices = toolProperty == null ? EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP); toolChoice = new JComboBox<>(toolChoices.toArray()); - if (toolName != null) - toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase())); + ToolChoices tool = toolName != null ? ToolChoices.valueOf(toolName.toUpperCase()) : null; + if (toolName != null) { + if (toolBootstrap) + tool = tool.asBootstrap(); + toolChoice.setSelectedItem(tool); + } toolChoice.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { - String tn = ((ToolChoices)e.getItem()).toolName; - argsField.setText(getDefaultArgsForTool(props, tn)); + ToolChoices tool = (ToolChoices)e.getItem(); + argsField.setText(getDefaultArgsForTool(props, tool)); if (toolProperty != null) - okButton.setEnabled(!tn.equals("")); + okButton.setEnabled(tool != ToolChoices.NONE); } }); - GridBagConstraints checkConstraint = new GridBagConstraints(); fc.anchor = GridBagConstraints.EAST; GridBagConstraints toolConstraint = new GridBagConstraints(); fc.anchor = GridBagConstraints.WEST; toolPane.add(toolChoice, toolConstraint); - bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap); - toolPane.add(bootstrapCheckbox, checkConstraint); body.add(toolPane, fc); - argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40); + argsField = new JTextField(getDefaultArgsForTool(props, tool), 40); if (toolProperty == null || argsProperty != null) { JLabel argsLabel = new JLabel("Args:"); body.add(argsLabel, lc); @@ -322,8 +344,11 @@ public class SelectToolTask extends Task { } } - String getDefaultArgsForTool(Properties props, String tn) { - return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", ""); + String getDefaultArgsForTool(Properties props, ToolChoices tool) { + if (tool == null) + return ""; + String toolName = tool.baseTool().toolName; + return toolName.equals("") ? "" : props.getProperty(toolName + ".args", ""); } // Ant task parameters @@ -335,7 +360,6 @@ public class SelectToolTask extends Task { // GUI components private JComboBox toolChoice; - private JCheckBox bootstrapCheckbox; private JTextField argsField; private JCheckBox defaultCheck; private JButton okButton; From de2b97f13351a01dbd38de957bcf00c2f69a7d64 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 7 Nov 2014 14:51:35 -0800 Subject: [PATCH 007/134] 8063145: ToolBox should support extracting classes from a JavaFileManager/Location Reviewed-by: ksrini --- .../javac/6508981/TestInferBinaryName.java | 84 ++++++--- langtools/test/tools/lib/ToolBox.java | 174 ++++++++++++++---- 2 files changed, 194 insertions(+), 64 deletions(-) diff --git a/langtools/test/tools/javac/6508981/TestInferBinaryName.java b/langtools/test/tools/javac/6508981/TestInferBinaryName.java index e94ba29b4dc..01da20b42ba 100644 --- a/langtools/test/tools/javac/6508981/TestInferBinaryName.java +++ b/langtools/test/tools/javac/6508981/TestInferBinaryName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2014, 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 @@ -26,7 +26,8 @@ * @bug 6508981 * @summary cleanup file separator handling in JavacFileManager * (This test is specifically to test the new impl of inferBinaryName) - * @build p.A + * @library /tools/lib + * @build ToolBox p.A * @run main TestInferBinaryName */ @@ -61,51 +62,75 @@ public class TestInferBinaryName { //System.err.println(System.getProperties()); testDirectory(); testSymbolArchive(); - testZipArchive(); - testZipFileIndexArchive(); - testZipFileIndexArchive2(); + + File testJar = createJar(); + + testZipArchive(testJar); + testZipFileIndexArchive(testJar); + testZipFileIndexArchive2(testJar); if (errors > 0) throw new Exception(errors + " error found"); } + File createJar() throws IOException { + File f = new File("test.jar"); + try (JavaFileManager fm = new JavacFileManager(new Context(), false, null)) { + ToolBox tb = new ToolBox(); + tb.new JarTask(f.getPath()) + .files(fm, StandardLocation.PLATFORM_CLASS_PATH, "java.lang.*") + .run(); + } + return f; + } + void testDirectory() throws IOException { String testClassName = "p.A"; - JavaFileManager fm = - getFileManager("test.classes", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testDirectory", - fm, testClassName, "com.sun.tools.javac.file.RegularFileObject"); + List testClasses = Arrays.asList(new File(System.getProperty("test.classes"))); + try (JavaFileManager fm = + getFileManager(testClasses, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) { + test("testDirectory", + fm, testClassName, "com.sun.tools.javac.file.RegularFileObject"); + } } void testSymbolArchive() throws IOException { String testClassName = "java.lang.String"; - JavaFileManager fm = - getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX); - test("testSymbolArchive", - fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject"); + List path = getPath(System.getProperty("sun.boot.class.path")); + try (JavaFileManager fm = + getFileManager(path, USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) { + test("testSymbolArchive", + fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject"); + } } - void testZipArchive() throws IOException { + void testZipArchive(File testJar) throws IOException { String testClassName = "java.lang.String"; - JavaFileManager fm = - getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX); - test("testZipArchive", - fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject"); + List path = Arrays.asList(testJar); + try (JavaFileManager fm = + getFileManager(path, IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) { + test("testZipArchive", + fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject"); + } } - void testZipFileIndexArchive() throws IOException { + void testZipFileIndexArchive(File testJar) throws IOException { String testClassName = "java.lang.String"; - JavaFileManager fm = - getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testZipFileIndexArchive", - fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + List path = Arrays.asList(testJar); + try (JavaFileManager fm = + getFileManager(path, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) { + test("testZipFileIndexArchive", + fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + } } - void testZipFileIndexArchive2() throws IOException { + void testZipFileIndexArchive2(File testJar) throws IOException { String testClassName = "java.lang.String"; - JavaFileManager fm = - getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX); - test("testZipFileIndexArchive2", - fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + List path = Arrays.asList(testJar); + try (JavaFileManager fm = + getFileManager(path, IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) { + test("testZipFileIndexArchive2", + fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject"); + } } /** @@ -133,7 +158,7 @@ public class TestInferBinaryName { System.err.println("OK"); } - JavaFileManager getFileManager(String classpathProperty, + JavaFileManager getFileManager(List path, boolean symFileKind, boolean zipFileIndexKind) throws IOException { @@ -145,7 +170,6 @@ public class TestInferBinaryName { if (symFileKind == IGNORE_SYMBOL_FILE) options.put("ignore.symbol.file", "true"); JavacFileManager fm = new JavacFileManager(ctx, false, null); - List path = getPath(System.getProperty(classpathProperty)); fm.setLocation(CLASS_PATH, path); return fm; } diff --git a/langtools/test/tools/lib/ToolBox.java b/langtools/test/tools/lib/ToolBox.java index c052f463a36..859765b2db1 100644 --- a/langtools/test/tools/lib/ToolBox.java +++ b/langtools/test/tools/lib/ToolBox.java @@ -21,6 +21,7 @@ * questions. */ +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; @@ -28,6 +29,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FilterOutputStream; import java.io.FilterWriter; +import java.io.IOError; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -49,12 +51,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumMap; +import java.util.EnumSet; import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; @@ -64,18 +69,20 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; + import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.JavaFileManager.Location; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.StandardLocation; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.api.JavacTool; -import java.io.IOError; /** * Utility methods and classes for writing jtreg tests for @@ -233,7 +240,7 @@ public class ToolBox { public void createDirectories(String... paths) throws IOException { if (paths.length == 0) throw new IllegalArgumentException("no directories specified"); - for (String p: paths) + for (String p : paths) Files.createDirectories(Paths.get(p)); } @@ -248,7 +255,7 @@ public class ToolBox { public void createDirectories(Path... paths) throws IOException { if (paths.length == 0) throw new IllegalArgumentException("no directories specified"); - for (Path p: paths) + for (Path p : paths) Files.createDirectories(p); } @@ -262,7 +269,7 @@ public class ToolBox { public void deleteFiles(String... files) throws IOException { if (files.length == 0) throw new IllegalArgumentException("no files specified"); - for (String file: files) + for (String file : files) Files.delete(Paths.get(file)); } @@ -392,7 +399,7 @@ public class ToolBox { public void writeJavaFiles(Path dir, String... contents) throws IOException { if (contents.length == 0) throw new IllegalArgumentException("no content specified for any files"); - for (String c: contents) { + for (String c : contents) { new JavaSource(c).write(dir); } } @@ -1090,7 +1097,7 @@ public class ToolBox { private List toFiles(String path) { List result = new ArrayList<>(); - for (String s: path.split(File.pathSeparator)) { + for (String s : path.split(File.pathSeparator)) { if (!s.isEmpty()) result.add(new File(s)); } @@ -1108,7 +1115,7 @@ public class ToolBox { if (fileObjects == null) return filesAsFileObjects; List combinedList = new ArrayList<>(); - for (JavaFileObject o: filesAsFileObjects) + for (JavaFileObject o : filesAsFileObjects) combinedList.add(o); combinedList.addAll(fileObjects); return combinedList; @@ -1308,6 +1315,7 @@ public class ToolBox { private String mainClass; private Path baseDir; private List paths; + private Set fileObjects; /** * Creates a task to write jar files, using API mode. @@ -1315,6 +1323,7 @@ public class ToolBox { public JarTask() { super(Mode.API); paths = Collections.emptyList(); + fileObjects = new LinkedHashSet<>(); } /** @@ -1391,6 +1400,53 @@ public class ToolBox { return this; } + /** + * Adds a set of file objects to be written into the jar file, by copying them + * from a Location in a JavaFileManager. + * The file objects to be written are specified by a series of paths; + * each path can be in one of the following forms: + *
    + *
  • The name of a class. For example, java.lang.Object. + * In this case, the corresponding .class file will be written to the jar file. + *
  • the name of a package followed by {@code .*}. For example, {@code java.lang.*}. + * In this case, all the class files in the specified package will be written to + * the jar file. + *
  • the name of a package followed by {@code .**}. For example, {@code java.lang.**}. + * In this case, all the class files in the specified package, and any subpackages + * will be written to the jar file. + *
+ * + * @param fm the file manager in which to find the file objects + * @param l the location in which to find the file objects + * @param paths the paths specifying the file objects to be copied + * @return this task object + * @throws IOException if errors occur while determining the set of file objects + */ + public JarTask files(JavaFileManager fm, Location l, String... paths) + throws IOException { + for (String p : paths) { + if (p.endsWith(".**")) + addPackage(fm, l, p.substring(0, p.length() - 3), true); + else if (p.endsWith(".*")) + addPackage(fm, l, p.substring(0, p.length() - 2), false); + else + addFile(fm, l, p); + } + return this; + } + + private void addPackage(JavaFileManager fm, Location l, String pkg, boolean recurse) + throws IOException { + for (JavaFileObject fo : fm.list(l, pkg, EnumSet.allOf(JavaFileObject.Kind.class), recurse)) { + fileObjects.add(fo); + } + } + + private void addFile(JavaFileManager fm, Location l, String path) throws IOException { + JavaFileObject fo = fm.getJavaFileForInput(l, path, Kind.CLASS); + fileObjects.add(fo); + } + /** * Provides limited jar command-like functionality. * The supported commands are: @@ -1464,42 +1520,19 @@ public class ToolBox { StreamOutput sysOut = new StreamOutput(System.out, System::setOut); StreamOutput sysErr = new StreamOutput(System.err, System::setErr); - int rc; Map outputMap = new HashMap<>(); try (OutputStream os = Files.newOutputStream(jar); JarOutputStream jos = openJar(os, m)) { - Path base = (baseDir == null) ? currDir : baseDir; - for (Path path: paths) { - Files.walkFileTree(base.resolve(path), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - try { - String p = base.relativize(file) - .normalize() - .toString() - .replace(File.separatorChar, '/'); - JarEntry e = new JarEntry(p); - jos.putNextEntry(e); - jos.write(Files.readAllBytes(file)); - jos.closeEntry(); - return FileVisitResult.CONTINUE; - } catch (IOException e) { - System.err.println("Error adding " + file + " to jar file: " + e); - return FileVisitResult.TERMINATE; - } - } - }); - } - rc = 0; + writeFiles(jos); + writeFileObjects(jos); } catch (IOException e) { - System.err.println("Error opening " + jar + ": " + e); - rc = 1; + error("Exception while opening " + jar, e); } finally { outputMap.put(OutputKind.STDOUT, sysOut.close()); outputMap.put(OutputKind.STDERR, sysErr.close()); } - return checkExit(new Result(this, rc, outputMap)); + return checkExit(new Result(this, (errors == 0) ? 0 : 1, outputMap)); } private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException { @@ -1512,6 +1545,79 @@ public class ToolBox { } } + private void writeFiles(JarOutputStream jos) throws IOException { + Path base = (baseDir == null) ? currDir : baseDir; + for (Path path : paths) { + Files.walkFileTree(base.resolve(path), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + String p = base.relativize(file) + .normalize() + .toString() + .replace(File.separatorChar, '/'); + JarEntry e = new JarEntry(p); + jos.putNextEntry(e); + try { + jos.write(Files.readAllBytes(file)); + } finally { + jos.closeEntry(); + } + return FileVisitResult.CONTINUE; + } catch (IOException e) { + error("Exception while adding " + file + " to jar file", e); + return FileVisitResult.TERMINATE; + } + } + }); + } + } + + private void writeFileObjects(JarOutputStream jos) throws IOException { + for (FileObject fo : fileObjects) { + String p = guessPath(fo); + JarEntry e = new JarEntry(p); + jos.putNextEntry(e); + try { + byte[] buf = new byte[1024]; + try (BufferedInputStream in = new BufferedInputStream(fo.openInputStream())) { + int n; + while ((n = in.read(buf)) > 0) + jos.write(buf, 0, n); + } catch (IOException ex) { + error("Exception while adding " + fo.getName() + " to jar file", ex); + } + } finally { + jos.closeEntry(); + } + } + } + + /* + * A jar: URL is of the form jar:URL!/entry where URL is a URL for the .jar file itself. + * In Symbol files (i.e. ct.sym) the underlying entry is prefixed META-INF/sym/. + */ + private final Pattern jarEntry = Pattern.compile(".*!/(?:META-INF/sym/[^/]+/)?(.*)"); + + private String guessPath(FileObject fo) { + URI u = fo.toUri(); + switch (u.getScheme()) { + case "jar": + Matcher m = jarEntry.matcher(u.getSchemeSpecificPart()); + if (m.matches()) { + return m.group(1); + } + break; + } + throw new IllegalArgumentException(fo.getName()); + } + + private void error(String message, Throwable t) { + out.println("Error: " + message + ": " + t); + errors++; + } + + private int errors; } /** From 1de8cf1b7f6c35f898e8441441b6eeb5d8cc9bb0 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Sat, 8 Nov 2014 22:00:31 +0000 Subject: [PATCH 008/134] 8064367: Fix IntelliJ langtools support to use new dev build Update ant hooks in langtools IntelliJ project Reviewed-by: jlahoda --- langtools/make/intellij/build.xml | 4 +-- .../src/idea/LangtoolsIdeaAntLogger.java | 32 +++++++++++-------- langtools/make/intellij/workspace.xml | 22 ++++++------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/langtools/make/intellij/build.xml b/langtools/make/intellij/build.xml index ed1db8342df..c67b66555d0 100644 --- a/langtools/make/intellij/build.xml +++ b/langtools/make/intellij/build.xml @@ -2,10 +2,8 @@ diff --git a/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java b/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java index 685b2fa89ec..0e6e9da4d71 100644 --- a/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java +++ b/langtools/make/intellij/src/idea/LangtoolsIdeaAntLogger.java @@ -26,7 +26,9 @@ package idea; import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildListener; import org.apache.tools.ant.DefaultLogger; +import org.apache.tools.ant.Project; import java.util.EnumSet; import java.util.Stack; @@ -166,21 +168,17 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger { } }, /** build bootstrap tool target - executed when bootstrapping javac */ - BUILD_BOOTSTRAP_TOOL("build-bootstrap-.*") { + BUILD_BOOTSTRAP_JAVAC("build-bootstrap-javac-classes") { @Override String getDisplayMessage(BuildEvent e) { - String targetName = e.getTarget().getName(); - String tool = targetName.split("-")[2]; - return "Building bootstrap " + tool + "..."; + return "Building bootstrap javac..."; } }, /** build classes target - executed when building classes of given tool */ - BUILD_TOOL("build-classes-.*") { + BUILD_ALL_CLASSES("build-all-classes") { @Override String getDisplayMessage(BuildEvent e) { - String targetName = e.getTarget().getName(); - String tool = targetName.split("-")[2]; - return "Building " + tool + "..."; + return "Building all classes..."; } }, /** synthetic target catching any other target not in this list */ @@ -195,14 +193,14 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger { } }; - String targetRegex; + String targetName; - Target(String targetRegex) { - this.targetRegex = targetRegex; + Target(String targetName) { + this.targetName = targetName; } boolean matches(String msg) { - return msg.matches(targetRegex); + return msg.equals(targetName); } abstract String getDisplayMessage(BuildEvent e); @@ -253,8 +251,14 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger { /** stack of pending tasks */ Stack tasks = new Stack<>(); - public LangtoolsIdeaAntLogger(DefaultLogger logger) { - this.logger = logger; + public LangtoolsIdeaAntLogger(Project project) { + for (Object o : project.getBuildListeners()) { + if (o instanceof DefaultLogger) { + this.logger = (DefaultLogger)o; + project.removeBuildListener((BuildListener)o); + project.addBuildListener(this); + } + } tasks.push(Task.ROOT); } diff --git a/langtools/make/intellij/workspace.xml b/langtools/make/intellij/workspace.xml index eb5e3adb181..6f613f966a6 100644 --- a/langtools/make/intellij/workspace.xml +++ b/langtools/make/intellij/workspace.xml @@ -10,7 +10,7 @@