Bug 519167: [9] Create rtstubs9.jar for Java 9 test setup
diff --git a/org.eclipse.jdt.ui.tests/META-INF/MANIFEST.MF b/org.eclipse.jdt.ui.tests/META-INF/MANIFEST.MF
index 84487e0..109e59c 100644
--- a/org.eclipse.jdt.ui.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.jdt.ui.tests/META-INF/MANIFEST.MF
@@ -39,6 +39,7 @@
org.eclipse.jdt.ui.tests.wizardapi;x-internal:=true
Require-Bundle:
org.eclipse.core.expressions,
+ org.eclipse.core.filesystem,
org.eclipse.core.resources,
org.eclipse.core.runtime,
org.eclipse.debug.core,
diff --git a/org.eclipse.jdt.ui.tests/plugin.xml b/org.eclipse.jdt.ui.tests/plugin.xml
index b051006..d12ed4d 100644
--- a/org.eclipse.jdt.ui.tests/plugin.xml
+++ b/org.eclipse.jdt.ui.tests/plugin.xml
@@ -2,6 +2,40 @@
<?eclipse version="3.0"?>
<plugin>
+<!-- **************** See testresources/rtstubs-README.txt ******************* -->
+ <extension
+ point="org.eclipse.ui.popupMenus">
+ <objectContribution
+ objectClass="org.eclipse.jdt.core.IJavaElement"
+ id="org.eclipse.jdt.ui.tests.contribution">
+ <visibility>
+ <or>
+ <objectClass
+ name="org.eclipse.jdt.core.IPackageFragment">
+ </objectClass>
+ <objectClass
+ name="org.eclipse.jdt.core.IPackageFragmentRoot">
+ </objectClass>
+ </or>
+ </visibility>
+ <menu
+ label="&jdt.ui test tools"
+ path="additions"
+ id="org.eclipse.jdt.ui.tests.menu">
+ <separator
+ name="group">
+ </separator>
+ </menu>
+ <action
+ label="Create stubs in pro&ject..."
+ class="org.eclipse.jdt.testplugin.util.CreateStubsAction"
+ menubarPath="org.eclipse.jdt.ui.tests.menu/group"
+ enablesFor="+"
+ id="org.eclipse.jdt.ui.examples.CreateStubsAction">
+ </action>
+ </objectContribution>
+ </extension>
+
<!-- **************** TEST DECORATOR ******************* -->
<extension
point="org.eclipse.ui.decorators">
diff --git a/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaTestPlugin.java b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaTestPlugin.java
index f60f1b9..b099332 100644
--- a/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaTestPlugin.java
+++ b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/JavaTestPlugin.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2009 IBM Corporation and others.
+ * Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,14 +19,15 @@
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
-public class JavaTestPlugin extends Plugin {
+
+public class JavaTestPlugin extends AbstractUIPlugin {
private static JavaTestPlugin fgDefault;
diff --git a/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/util/CreateStubsAction.java b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/util/CreateStubsAction.java
new file mode 100644
index 0000000..15e140f
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/test plugin/org/eclipse/jdt/testplugin/util/CreateStubsAction.java
@@ -0,0 +1,215 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2017 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.testplugin.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.jdt.testplugin.JavaProjectHelper;
+import org.eclipse.jdt.testplugin.JavaTestPlugin;
+
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.IInputValidator;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.window.Window;
+
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+
+import org.eclipse.jdt.internal.corext.refactoring.binary.StubCreationOperation;
+
+/**
+ * See testresources/rtstubs-README.txt
+ */
+public final class CreateStubsAction implements IObjectActionDelegate {
+
+ private static final String[] DEFAULT_PACKAGES= new String[] {
+ "java.beans",
+ "java.io",
+ "java.lang",
+ "java.lang.annotation",
+ "java.lang.ref",
+ "java.lang.reflect",
+ "java.math",
+ "java.net",
+ "java.nio",
+ "java.nio.channels",
+ "java.nio.channels.spi",
+ "java.nio.charset",
+ "java.nio.charset.spi",
+ "java.security",
+ "java.security.acl",
+ "java.security.cert",
+ "java.security.interfaces",
+ "java.security.spec",
+ "java.sql",
+ "java.text",
+ "java.util",
+ "java.util.jar",
+ "java.util.regex",
+ "java.util.zip",
+ //1.7:
+ "java.lang.invoke",
+ "java.nio.file",
+ "java.nio.file.attribute",
+ "java.util.concurrent",
+ //1.8:
+ "java.util.function",
+ "java.util.stream",
+ "javax.annotation",
+ "javax.annotation.processing",
+ "javax.lang.model",
+ "javax.lang.model.element",
+ "javax.lang.model.type",
+ "javax.lang.model.util",
+ "javax.tools",
+ //9:
+ "java.lang.module",
+ "java.nio.file.spi",
+ };
+
+ private static final String SETTINGS_ID_STUBS_PROJECT= "stubsProject";
+
+ private static final String CREATE_STUBS_DIALOG_TITLE= "Create Stubs"; //$NON-NLS-1$
+
+ private IWorkbenchPart fTargetPart;
+
+ public CreateStubsAction() {
+ super();
+ }
+
+ void createJavaProject(String projectName) throws CoreException {
+ IJavaProject javaProject= JavaProjectHelper.createJavaProject(projectName, "bin");
+ JavaProjectHelper.addSourceContainer(javaProject, "src");
+ }
+
+ private void fail(String msg) {
+ Shell shell= fTargetPart.getSite().getShell();
+ MessageDialog.openInformation(shell, CREATE_STUBS_DIALOG_TITLE, msg);
+ }
+
+ @Override
+ public void run(IAction action) {
+ ISelection selection= fTargetPart.getSite().getSelectionProvider().getSelection();
+ if (!(selection instanceof IStructuredSelection)) {
+ fail("Select packages to create stubs."); //$NON-NLS-1$
+ return;
+ }
+ final IStructuredSelection structuredSelection= (IStructuredSelection) selection;
+
+ Shell shell= fTargetPart.getSite().getShell();
+ String initialValue= JavaTestPlugin.getDefault().getDialogSettings().get(SETTINGS_ID_STUBS_PROJECT); //$NON-NLS-1$
+ if (initialValue == null)
+ initialValue = "stubs"; //$NON-NLS-1$
+ final InputDialog inputDialog= new InputDialog(shell, CREATE_STUBS_DIALOG_TITLE, "Target project name:", initialValue, new IInputValidator() { //$NON-NLS-1$
+ @Override
+ public String isValid(String newText) {
+ IStatus status = ResourcesPlugin.getWorkspace().validateName(newText, IResource.PROJECT);
+ return status.isOK() ? null : (String) status.getMessage();
+ }
+ });
+ if (inputDialog.open() != Window.OK)
+ return;
+ try {
+
+ final String name= inputDialog.getValue();
+ JavaTestPlugin.getDefault().getDialogSettings().put(SETTINGS_ID_STUBS_PROJECT, name); //$NON-NLS-1$
+ long start= System.currentTimeMillis();
+
+ ArrayList<String> defaultPackages= new ArrayList<>(Arrays.asList(DEFAULT_PACKAGES));
+
+ ProgressMonitorDialog progressMonitorDialog= new ProgressMonitorDialog(shell);
+ progressMonitorDialog.run(true, true, new IRunnableWithProgress() {
+
+ @Override
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ try {
+ createJavaProject(name);
+ IFolder target = ResourcesPlugin.getWorkspace().getRoot().getProject(inputDialog.getValue()).getFolder("src"); //$NON-NLS-1$
+ List<IPackageFragment> packageFragments= new ArrayList<>();
+
+ boolean checkCompletionOfDefaultPackages= false;
+ for (Object sel : structuredSelection.toList()) {
+ if (sel instanceof IPackageFragment) {
+ packageFragments.add((IPackageFragment) sel);
+ } else if (sel instanceof IPackageFragmentRoot) {
+ IPackageFragmentRoot root = (IPackageFragmentRoot) sel;
+ for (Iterator<String> iter= defaultPackages.iterator(); iter.hasNext();) {
+ String packName= iter.next();
+ IPackageFragment packageFragment = root.getPackageFragment(packName);
+ if (packageFragment.exists()) {
+ packageFragments.add(packageFragment);
+ iter.remove();
+ } else {
+ checkCompletionOfDefaultPackages= true;
+ }
+ }
+ }
+ }
+ ResourcesPlugin.getWorkspace().run(new StubCreationOperation(target.getLocationURI(), packageFragments), monitor);
+ if (!checkCompletionOfDefaultPackages) {
+ defaultPackages.clear();
+ }
+ } catch (CoreException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+ });
+ IProject project= ResourcesPlugin.getWorkspace().getRoot().getProject(name);
+ project.refreshLocal(IResource.DEPTH_INFINITE, null);
+ long end= System.currentTimeMillis();
+ String message= "Took " + ((end - start) / 1000) + "s to create the stubs";
+ if (!defaultPackages.isEmpty() ) {
+ message+= "\n\nNo stubs generated for packages: " + defaultPackages.toString();
+ }
+ MessageDialog.openInformation(fTargetPart.getSite().getShell(), CREATE_STUBS_DIALOG_TITLE, message);
+ } catch (InterruptedException e) {
+ // Do not log
+ } catch (InvocationTargetException e) {
+ JavaTestPlugin.log(e);
+ } catch (CoreException exception) {
+ JavaTestPlugin.log(exception);
+ }
+ }
+
+ @Override
+ public void selectionChanged(IAction action, ISelection selection) {
+ // Do nothing
+ }
+
+ @Override
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ fTargetPart= targetPart;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests/testresources/rtstubs-README.txt b/org.eclipse.jdt.ui.tests/testresources/rtstubs-README.txt
new file mode 100644
index 0000000..0d267fc
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/testresources/rtstubs-README.txt
@@ -0,0 +1,62 @@
+About rtstubs*.jar
+*****************
+
+Many JDT tests require a specific JRE version that may be newer or older than
+the default JRE that is being used to run the tests. To create a stable
+environment, tests usually put rtstubs*.jar on the classpath.
+
+rtstubs*.jar contain class file stubs for a few of the most basic java.*
+packages. The class files only contain the APIs, but no method bodies etc.
+(except for required super constructor invocations).
+
+The process of creating a new rtstubs*.jar is partly automated, but there's
+still quite some manual work involved to get a source project that compiles
+without errors.
+
+Here are the generator classes that likely need some tweaks in the future:
+- org.eclipse.jdt.testplugin.util.CreateStubsAction: add packages to
+ DEFAULT_PACKAGES if there are many references to them
+- org.eclipse.jdt.internal.corext.refactoring.binary.StubCreator: Make sure new
+ or newly used language constructs are properly handled.
+
+Building rtstubs*.jar
+*********************
+- Have org.eclipse.jdt.ui.tests in your JDT source workspace.
+- Start a runtime workbench.
+- Create a Java project with the JRE for which you need to generate stubs
+ (e.g. "JDK9")
+
+- Select the all the modules. This will use the hardcoded default list of
+ packages. In Java 9: from modules java.base, java.compiler, java.desktop, and
+ java.sql. Before Java 9: select rt.jar.
+ (in CreateStubsAction, add additionally required packages there).
+- Alternatively, select the package(s) for which to (re-)create stubs.
+
+- Context menu > jdt.ui test tools > Create stubs in project...
+- Enter name of target project (e.g. "stubs9") and click OK. Use a new project
+ or one that doesn't contain any JRE System Library on the build path -- we
+ want a self-sufficient source folder that doesn't depend on binaries.
+
+- Team > Share Project... > Git, and commit a base version in case you later
+ want to revert.
+
+- Manually remove everything from the java.beans package, except for:
+PropertyChangeEvent
+PropertyChangeListener
+
+- Manually remove the following: (hint: use Ctrl+Shift+C to comment lines or
+ Ctrl+Shift+/ to comment supertypes)
+ - default-accessible types with errors (Java Browsing perspective or
+ "Java Type Indicator" decorator help :-)
+ - all methods/implements clauses with references to javax, sun, or java.time.*
+ (could maybe generate java.time* in the future if this avoids manual work)
+
+- Make sure there are no compile errors remaining.
+
+- Create a module-info.java that declares module java.base and exports all
+ packages.
+
+- On project preference page 'Java Compiler', uncheck all options for
+ 'Classfile Generation'
+
+- Export generated class files to rtstubs*.jar
diff --git a/org.eclipse.jdt.ui.tests/testresources/rtstubs9.jar b/org.eclipse.jdt.ui.tests/testresources/rtstubs9.jar
new file mode 100644
index 0000000..6278e02
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests/testresources/rtstubs9.jar
Binary files differ
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/binary/StubCreator.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/binary/StubCreator.java
index 61ee17f..fe868a9 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/binary/StubCreator.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/binary/StubCreator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2014 IBM Corporation and others.
+ * Copyright (c) 2006, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -135,11 +135,11 @@
private void appendAnnotation(IAnnotation annotation) throws JavaModelException {
String name= annotation.getElementName();
- if (!fStubInvisible && name.startsWith("sun.")) //$NON-NLS-1$
+ if (!fStubInvisible && name.startsWith("sun.") || name.startsWith("jdk.internal.")) //$NON-NLS-1$ //$NON-NLS-2$
return; // skip Sun-internal annotations
fBuffer.append('@');
- fBuffer.append(name);
+ fBuffer.append(name.replace('$', '.'));
fBuffer.append('(');
IMemberValuePair[] memberValuePairs= annotation.getMemberValuePairs();
@@ -194,7 +194,8 @@
final boolean isDefault= !Flags.isPublic(flags) && !Flags.isProtected(flags) && !isPrivate;
final boolean stub= fStubInvisible || (!isPrivate && !isDefault);
if (child instanceof IType) {
- if (stub)
+ if (stub || "java.lang.invoke.MethodHandle".equals(type.getFullyQualifiedName()) //$NON-NLS-1$
+ || "java.util.concurrent.ConcurrentHashMap$CollectionView".equals(((IType) child).getFullyQualifiedName())) //$NON-NLS-1$
appendTypeDeclaration((IType) child, new SubProgressMonitor(monitor, 1));
} else if (child instanceof IField) {
if (stub && !Flags.isEnum(flags) && !Flags.isSynthetic(flags))
@@ -350,6 +351,11 @@
fBuffer.append(","); //$NON-NLS-1$
fBuffer.append(Signature.toString(exceptionTypes[index]));
}
+ if (Flags.isAnnnotationDefault(flags) ) {
+ fBuffer.append(" default "); //$NON-NLS-1$
+ IMemberValuePair pair= method.getDefaultValue();
+ appendAnnotationValue(pair.getValue(), pair.getValueKind());
+ }
if (Flags.isAbstract(flags) || Flags.isNative(flags))
fBuffer.append(";"); //$NON-NLS-1$
else {