--- a/langtools/make/build.properties Thu May 19 17:48:04 2016 +0000
+++ b/langtools/make/build.properties Thu May 19 19:47:04 2016 +0000
@@ -28,6 +28,10 @@
javac.source = 9
javac.target = 9
+#version used to compile build tools
+javac.build.source = 8
+javac.build.target = 8
+
langtools.resource.includes = \
com/sun/tools/javac/resources/compiler.properties
--- a/langtools/make/build.xml Thu May 19 17:48:04 2016 +0000
+++ b/langtools/make/build.xml Thu May 19 19:47:04 2016 +0000
@@ -239,11 +239,12 @@
</condition>
<replace file=".idea/ant.xml" token="@IDEA_JTREG_HOME@" value="${idea.jtreg.home}"/>
<replace file=".idea/ant.xml" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
- <replace file=".idea/workspace.xml" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
- <replace file=".idea/workspace.xml" token="@XPATCH@" value="${xpatch.cmd}"/>
- <replace file=".idea/workspace.xml" token="@PATH_SEP@" value="${path.separator}"/>
+ <replace dir=".idea/runConfigurations" token="@IDEA_TARGET_JDK@" value="${idea.target.jdk}"/>
+ <replace dir=".idea/runConfigurations" token="@XPATCH@" value="${xpatch.cmd}"/>
<mkdir dir=".idea/classes"/>
- <javac srcdir="make/intellij/src"
+ <javac source="${javac.build.source}"
+ target="${javac.build.target}"
+ srcdir="make/intellij/src"
destdir=".idea/classes"/>
</target>
@@ -255,10 +256,8 @@
<copy todir="${build.tools}/propertiesparser" >
<fileset dir="${make.tools.dir}/propertiesparser" includes="**/resources/**"/>
</copy>
- <javac fork="true"
- source="${javac.source}"
- target="${javac.target}"
- executable="${langtools.jdk.home}/bin/javac"
+ <javac source="${javac.build.source}"
+ target="${javac.build.target}"
srcdir="${make.tools.dir}"
includes="propertiesparser/* anttasks/PropertiesParser* anttasks/PathFileSet*"
destdir="${build.tools}"
@@ -273,10 +272,9 @@
</target>
<target name="-def-pcompile">
- <javac fork="true"
- source="${javac.source}"
- target="${javac.target}"
- executable="${langtools.jdk.home}/bin/javac"
+ <javac
+ source="${javac.build.source}"
+ target="${javac.build.target}"
srcdir="${make.tools.dir}"
includes="compileproperties/* anttasks/CompileProperties* anttasks/PathFileSet*"
destdir="${build.dir}/toolclasses/"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/javac.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,22 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="javac" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
+ <option name="VM_PARAMETERS" value="@XPATCH@" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/javadoc.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,22 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="javadoc" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.sun.tools.javadoc.Main" />
+ <option name="VM_PARAMETERS" value="@XPATCH@" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/javah.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,22 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="javah" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.sun.tools.javah.Main" />
+ <option name="VM_PARAMETERS" value="@XPATCH@ -XaddExports:jdk.compiler/com.sun.tools.javah=ALL-UNNAMED" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/javap.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,22 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="javap" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.sun.tools.javap.Main" />
+ <option name="VM_PARAMETERS" value="@XPATCH@ -XaddExports:jdk.jdeps/com.sun.tools.javap=ALL-UNNAMED" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/jshell.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,20 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="jshell" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="jdk.internal.jshell.tool.JShellTool" />
+ <option name="VM_PARAMETERS" value="@XPATCH@ -XaddExports:jdk.jshell/jdk.internal.jshell.tool=ALL-UNNAMED" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/jtreg__debug_.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,18 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="jtreg (debug)" type="Remote" factoryName="Remote" singleton="true">
+ <option name="USE_SOCKET_TRANSPORT" value="true" />
+ <option name="SERVER_MODE" value="true" />
+ <option name="SHMEM_ADDRESS" />
+ <option name="HOST" value="localhost" />
+ <option name="PORT" value="5900" />
+ <RunnerSettings RunnerId="Debug">
+ <option name="DEBUG_PORT" value="5900" />
+ <option name="TRANSPORT" value="0" />
+ <option name="LOCAL" value="false" />
+ </RunnerSettings>
+ <ConfigurationWrapper RunnerId="Debug" />
+ <method>
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="jtreg-debug" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/jtreg__run_.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,8 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="jtreg (run)" type="AntRunConfiguration" factoryName="Ant Target">
+ <antsettings antfile="file://$PROJECT_DIR$/.idea/build.xml" target="jtreg" />
+ <method>
+ <option name="Make" enabled="false" />
+ </method>
+ </configuration>
+</component>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/intellij/runConfigurations/sjavac.xml Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,22 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="sjavac" type="Application" factoryName="Application">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.sun.tools.sjavac.Main" />
+ <option name="VM_PARAMETERS" value="@XPATCH@ -XaddExports:jdk.compiler/com.sun.tools.sjavac=ALL-UNNAMED" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
+ <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="langtools" />
+ <envs />
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method>
+ <option name="Make" enabled="false" />
+ <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
+ </method>
+ </configuration>
+</component>
--- a/langtools/make/intellij/workspace.xml Thu May 19 17:48:04 2016 +0000
+++ b/langtools/make/intellij/workspace.xml Thu May 19 19:47:04 2016 +0000
@@ -1,157 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
- <component name="ChangeListManager">
- <ignored path=".idea/" />
- </component>
- <component name="CompilerWorkspaceConfiguration">
- <option name="MAKE_PROJECT_ON_SAVE" value="true" />
- </component>
- <component name="RunManager" selected="Application.javac">
- <!-- javac -->
- <configuration default="false" name="javac" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
- <option name="VM_PARAMETERS" value="@XPATCH@" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- javadoc -->
- <configuration default="false" name="javadoc" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="com.sun.tools.javadoc.Main" />
- <option name="VM_PARAMETERS" value="@XPATCH@" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- javap -->
- <configuration default="false" name="javap" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="com.sun.tools.javap.Main" />
- <option name="VM_PARAMETERS" value="@XPATCH@" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- javah -->
- <configuration default="false" name="javah" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="com.sun.tools.javah.Main" />
- <option name="VM_PARAMETERS" value="@XPATCH@" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- sjavac -->
- <configuration default="false" name="sjavac" type="Application" factoryName="Application">
- <option name="MAIN_CLASS_NAME" value="com.sun.tools.sjavac.Main" />
- <option name="VM_PARAMETERS" value="@XPATCH@" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- jshell -->
- <configuration default="false" name="jshell" type="Application" factoryName="Application">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <option name="MAIN_CLASS_NAME" value="jdk.internal.jshell.tool.JShellTool" />
- <option name="VM_PARAMETERS" value="@XPATCH@ -XaddExports:jdk.jshell/jdk.internal.jshell.tool=ALL-UNNAMED" />
- <option name="PROGRAM_PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
- <option name="ALTERNATIVE_JRE_PATH" value="@IDEA_TARGET_JDK@" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="langtools" />
- <envs />
- <method>
- <option name="Make" enabled="false" />
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
- </method>
- </configuration>
- <!-- jtreg run -->
- <configuration default="false" name="jtreg (run)" type="AntRunConfiguration" factoryName="Ant Target">
- <antsettings antfile="file://$PROJECT_DIR$/.idea/build.xml" target="jtreg" />
- <method>
- <option name="Make" enabled="false" />
- </method>
- </configuration>
- <!-- jtreg debug -->
- <configuration default="false" name="jtreg (debug)" type="Remote" factoryName="Remote" singleton="true">
- <option name="USE_SOCKET_TRANSPORT" value="true" />
- <option name="SERVER_MODE" value="true" />
- <option name="SHMEM_ADDRESS" />
- <option name="HOST" value="localhost" />
- <option name="PORT" value="5900" />
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="5900" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="false" />
- </RunnerSettings>
- <ConfigurationWrapper RunnerId="Debug" />
- <method>
- <option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="jtreg-debug" />
- </method>
- <method />
- </configuration>
- </component>
<component name="StructureViewFactory">
<option name="ACTIVE_ACTIONS" value=",ALPHA_COMPARATOR" />
</component>
--- a/langtools/make/tools/crules/AssertCheckAnalyzer.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/make/tools/crules/AssertCheckAnalyzer.java Thu May 19 19:47:04 2016 +0000
@@ -37,6 +37,9 @@
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Assert;
+/**This analyzer guards against complex messages (i.e. those that use string concatenation) passed
+ * to various Assert.check methods.
+ */
public class AssertCheckAnalyzer extends AbstractCodingRulesAnalyzer {
enum AssertOverloadKind {
--- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java Thu May 19 19:47:04 2016 +0000
@@ -41,6 +41,7 @@
import static com.sun.tools.javac.code.Flags.SYNTHETIC;
import static com.sun.tools.javac.code.Kinds.Kind.*;
+/**This analyzer guards against non-final static fields.*/
public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer {
public MutableFieldsAnalyzer(JavacTask task) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java Thu May 19 19:47:04 2016 +0000
@@ -365,18 +365,22 @@
@Override
Type speculativeType(Symbol msym, MethodResolutionPhase phase) {
- for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) {
- DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext();
- if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) {
- return _entry.getValue();
+ if (pertinentToApplicability) {
+ for (Map.Entry<ResultInfo, Type> _entry : speculativeTypes.entrySet()) {
+ DeferredAttrContext deferredAttrContext = _entry.getKey().checkContext.deferredAttrContext();
+ if (deferredAttrContext.phase == phase && deferredAttrContext.msym == msym) {
+ return _entry.getValue();
+ }
}
+ return Type.noType;
+ } else {
+ return super.speculativeType(msym, phase);
}
- return Type.noType;
}
@Override
JCTree speculativeTree(DeferredAttrContext deferredAttrContext) {
- return speculativeTree;
+ return pertinentToApplicability ? speculativeTree : super.speculativeTree(deferredAttrContext);
}
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu May 19 19:47:04 2016 +0000
@@ -2678,6 +2678,7 @@
class ExpressionLambdaReturnContext extends FunctionalReturnContext {
JCExpression expr;
+ boolean expStmtExpected;
ExpressionLambdaReturnContext(JCExpression expr, CheckContext enclosingContext) {
super(enclosingContext);
@@ -2685,10 +2686,23 @@
}
@Override
+ public void report(DiagnosticPosition pos, JCDiagnostic details) {
+ if (expStmtExpected) {
+ enclosingContext.report(pos, diags.fragment(Fragments.StatExprExpected));
+ } else {
+ super.report(pos, details);
+ }
+ }
+
+ @Override
public boolean compatible(Type found, Type req, Warner warn) {
//a void return is compatible with an expression statement lambda
- return TreeInfo.isExpressionStatement(expr) && req.hasTag(VOID) ||
- super.compatible(found, req, warn);
+ if (req.hasTag(VOID)) {
+ expStmtExpected = true;
+ return TreeInfo.isExpressionStatement(expr);
+ } else {
+ return super.compatible(found, req, warn);
+ }
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu May 19 19:47:04 2016 +0000
@@ -35,6 +35,7 @@
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.GraphUtils.DependencyKind;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Attr.ResultInfo;
@@ -44,9 +45,10 @@
import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.LinkedHashMap;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@@ -172,6 +174,7 @@
public JCExpression tree;
Env<AttrContext> env;
AttrMode mode;
+ boolean pertinentToApplicability = true;
SpeculativeCache speculativeCache;
DeferredType(JCExpression tree, Env<AttrContext> env) {
@@ -290,6 +293,7 @@
resultInfo.checkContext.deferredAttrContext();
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
if (deferredStuckPolicy.isStuck()) {
+ pertinentToApplicability = false;
deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
return Type.noType;
} else {
@@ -574,28 +578,11 @@
*/
void complete() {
while (!deferredAttrNodes.isEmpty()) {
- Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<>();
- List<Type> stuckVars = List.nil();
boolean progress = false;
//scan a defensive copy of the node list - this is because a deferred
//attribution round can add new nodes to the list
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
- if (!deferredAttrNode.process(this)) {
- List<Type> restStuckVars =
- List.from(deferredAttrNode.deferredStuckPolicy.stuckVars())
- .intersect(inferenceContext.restvars());
- stuckVars = stuckVars.prependList(restStuckVars);
- //update dependency map
- for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars())
- .intersect(inferenceContext.restvars())) {
- Set<Type> prevDeps = depVarsMap.get(t);
- if (prevDeps == null) {
- prevDeps = new LinkedHashSet<>();
- depVarsMap.put(t, prevDeps);
- }
- prevDeps.addAll(restStuckVars);
- }
- } else {
+ if (deferredAttrNode.process(this)) {
deferredAttrNodes.remove(deferredAttrNode);
progress = true;
}
@@ -610,7 +597,9 @@
//remove all variables that have already been instantiated
//from the list of stuck variables
try {
- inferenceContext.solveAny(stuckVars, depVarsMap, warn);
+ //find stuck expression to unstuck
+ DeferredAttrNode toUnstuck = pickDeferredNode();
+ inferenceContext.solveAny(List.from(toUnstuck.deferredStuckPolicy.stuckVars()), warn);
inferenceContext.notifyChange();
} catch (Infer.GraphStrategy.NodeNotFoundException ex) {
//this means that we are in speculative mode and the
@@ -632,6 +621,59 @@
}
return dac.parent.insideOverloadPhase();
}
+
+ /**
+ * Pick the deferred node to be unstuck. The chosen node is the first strongly connected
+ * component containing exactly one node found in the dependency graph induced by deferred nodes.
+ * If no such component is found, the first deferred node is returned.
+ */
+ DeferredAttrNode pickDeferredNode() {
+ List<StuckNode> nodes = deferredAttrNodes.stream()
+ .map(StuckNode::new)
+ .collect(List.collector());
+ //init stuck expression graph; a deferred node A depends on a deferred node B iff
+ //the intersection between A's input variable and B's output variable is non-empty.
+ for (StuckNode sn1 : nodes) {
+ for (Type t : sn1.data.deferredStuckPolicy.stuckVars()) {
+ for (StuckNode sn2 : nodes) {
+ if (sn1 != sn2 && sn2.data.deferredStuckPolicy.depVars().contains(t)) {
+ sn1.deps.add(sn2);
+ }
+ }
+ }
+ }
+ //compute tarjan on the stuck graph
+ List<? extends StuckNode> csn = GraphUtils.tarjan(nodes).get(0);
+ return csn.length() == 1 ? csn.get(0).data : deferredAttrNodes.get(0);
+ }
+
+ class StuckNode extends GraphUtils.TarjanNode<DeferredAttrNode, StuckNode> {
+
+ Set<StuckNode> deps = new HashSet<>();
+
+ StuckNode(DeferredAttrNode data) {
+ super(data);
+ }
+
+ @Override
+ public DependencyKind[] getSupportedDependencyKinds() {
+ return new DependencyKind[] { Infer.DependencyKind.STUCK };
+ }
+
+ @Override
+ public Collection<? extends StuckNode> getDependenciesByKind(DependencyKind dk) {
+ if (dk == Infer.DependencyKind.STUCK) {
+ return deps;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ @Override
+ public Iterable<? extends StuckNode> getAllDependencies() {
+ return deps;
+ }
+ }
}
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu May 19 19:47:04 2016 +0000
@@ -2345,10 +2345,11 @@
// assigned before reading their value
public void visitSelect(JCFieldAccess tree) {
super.visitSelect(tree);
+ JCTree sel = TreeInfo.skipParens(tree.selected);
if (enforceThisDotInit &&
- tree.selected.hasTag(IDENT) &&
- ((JCIdent)tree.selected).name == names._this &&
- tree.sym.kind == VAR) {
+ sel.hasTag(IDENT) &&
+ ((JCIdent)sel).name == names._this &&
+ tree.sym.kind == VAR) {
checkInit(tree.pos(), (VarSymbol)tree.sym);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu May 19 19:47:04 2016 +0000
@@ -52,11 +52,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -1655,12 +1653,10 @@
class GraphSolver {
InferenceContext inferenceContext;
- Map<Type, Set<Type>> stuckDeps;
Warner warn;
- GraphSolver(InferenceContext inferenceContext, Map<Type, Set<Type>> stuckDeps, Warner warn) {
+ GraphSolver(InferenceContext inferenceContext, Warner warn) {
this.inferenceContext = inferenceContext;
- this.stuckDeps = stuckDeps;
this.warn = warn;
}
@@ -1671,7 +1667,7 @@
*/
void solve(GraphStrategy sstrategy) {
doIncorporation(inferenceContext, warn); //initial propagation of bounds
- InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps);
+ InferenceGraph inferenceGraph = new InferenceGraph();
while (!sstrategy.done()) {
if (dependenciesFolder != null) {
//add this graph to the pending queue
@@ -1720,12 +1716,12 @@
*/
class Node extends GraphUtils.TarjanNode<ListBuffer<Type>, Node> implements DottableNode<ListBuffer<Type>, Node> {
- /** map listing all dependencies (grouped by kind) */
- EnumMap<DependencyKind, Set<Node>> deps;
+ /** node dependencies */
+ Set<Node> deps;
Node(Type ivar) {
super(ListBuffer.of(ivar));
- this.deps = new EnumMap<>(DependencyKind.class);
+ this.deps = new HashSet<>();
}
@Override
@@ -1734,76 +1730,53 @@
}
public Iterable<? extends Node> getAllDependencies() {
- return getDependencies(DependencyKind.values());
+ return deps;
}
@Override
public Collection<? extends Node> getDependenciesByKind(GraphUtils.DependencyKind dk) {
- return getDependencies((DependencyKind)dk);
- }
-
- /**
- * Retrieves all dependencies with given kind(s).
- */
- protected Set<Node> getDependencies(DependencyKind... depKinds) {
- Set<Node> buf = new LinkedHashSet<>();
- for (DependencyKind dk : depKinds) {
- Set<Node> depsByKind = deps.get(dk);
- if (depsByKind != null) {
- buf.addAll(depsByKind);
- }
+ if (dk == DependencyKind.BOUND) {
+ return deps;
+ } else {
+ throw new IllegalStateException();
}
- return buf;
}
/**
* Adds dependency with given kind.
*/
- protected void addDependency(DependencyKind dk, Node depToAdd) {
- Set<Node> depsByKind = deps.get(dk);
- if (depsByKind == null) {
- depsByKind = new LinkedHashSet<>();
- deps.put(dk, depsByKind);
- }
- depsByKind.add(depToAdd);
+ protected void addDependency(Node depToAdd) {
+ deps.add(depToAdd);
}
/**
* Add multiple dependencies of same given kind.
*/
- protected void addDependencies(DependencyKind dk, Set<Node> depsToAdd) {
+ protected void addDependencies(Set<Node> depsToAdd) {
for (Node n : depsToAdd) {
- addDependency(dk, n);
+ addDependency(n);
}
}
/**
* Remove a dependency, regardless of its kind.
*/
- protected Set<DependencyKind> removeDependency(Node n) {
- Set<DependencyKind> removedKinds = new HashSet<>();
- for (DependencyKind dk : DependencyKind.values()) {
- Set<Node> depsByKind = deps.get(dk);
- if (depsByKind == null) continue;
- if (depsByKind.remove(n)) {
- removedKinds.add(dk);
- }
- }
- return removedKinds;
+ protected boolean removeDependency(Node n) {
+ return deps.remove(n);
}
/**
* Compute closure of a give node, by recursively walking
* through all its dependencies (of given kinds)
*/
- protected Set<Node> closure(DependencyKind... depKinds) {
+ protected Set<Node> closure() {
boolean progress = true;
Set<Node> closure = new HashSet<>();
closure.add(this);
while (progress) {
progress = false;
for (Node n1 : new HashSet<>(closure)) {
- progress = closure.addAll(n1.getDependencies(depKinds));
+ progress = closure.addAll(n1.deps);
}
}
return closure;
@@ -1815,9 +1788,8 @@
*/
protected boolean isLeaf() {
//no deps, or only one self dep
- Set<Node> allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK);
- if (allDeps.isEmpty()) return true;
- for (Node n : allDeps) {
+ if (deps.isEmpty()) return true;
+ for (Node n : deps) {
if (n != this) {
return false;
}
@@ -1834,24 +1806,15 @@
for (Node n : nodes) {
Assert.check(n.data.length() == 1, "Attempt to merge a compound node!");
data.appendList(n.data);
- for (DependencyKind dk : DependencyKind.values()) {
- addDependencies(dk, n.getDependencies(dk));
- }
+ addDependencies(n.deps);
}
//update deps
- EnumMap<DependencyKind, Set<Node>> deps2 = new EnumMap<>(DependencyKind.class);
- for (DependencyKind dk : DependencyKind.values()) {
- for (Node d : getDependencies(dk)) {
- Set<Node> depsByKind = deps2.get(dk);
- if (depsByKind == null) {
- depsByKind = new LinkedHashSet<>();
- deps2.put(dk, depsByKind);
- }
- if (data.contains(d.data.first())) {
- depsByKind.add(this);
- } else {
- depsByKind.add(d);
- }
+ Set<Node> deps2 = new HashSet<>();
+ for (Node d : deps) {
+ if (data.contains(d.data.first())) {
+ deps2.add(this);
+ } else {
+ deps2.add(d);
}
}
deps = deps2;
@@ -1862,9 +1825,9 @@
* topology.
*/
private void graphChanged(Node from, Node to) {
- for (DependencyKind dk : removeDependency(from)) {
+ if (removeDependency(from)) {
if (to != null) {
- addDependency(dk, to);
+ addDependency(to);
}
}
}
@@ -1880,22 +1843,19 @@
public Properties dependencyAttributes(Node sink, GraphUtils.DependencyKind dk) {
Properties p = new Properties();
p.put("style", ((DependencyKind)dk).dotSyle);
- if (dk == DependencyKind.STUCK) return p;
- else {
- StringBuilder buf = new StringBuilder();
- String sep = "";
- for (Type from : data) {
- UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
- for (Type bound : uv.getBounds(InferenceBound.values())) {
- if (bound.containsAny(List.from(sink.data))) {
- buf.append(sep);
- buf.append(bound);
- sep = ",";
- }
+ StringBuilder buf = new StringBuilder();
+ String sep = "";
+ for (Type from : data) {
+ UndetVar uv = (UndetVar)inferenceContext.asUndetVar(from);
+ for (Type bound : uv.getBounds(InferenceBound.values())) {
+ if (bound.containsAny(List.from(sink.data))) {
+ buf.append(sep);
+ buf.append(bound);
+ sep = ",";
}
}
- p.put("label", "\"" + buf.toString() + "\"");
}
+ p.put("label", "\"" + buf.toString() + "\"");
return p;
}
}
@@ -1903,8 +1863,8 @@
/** the nodes in the inference graph */
ArrayList<Node> nodes;
- InferenceGraph(Map<Type, Set<Type>> optDeps) {
- initNodes(optDeps);
+ InferenceGraph() {
+ initNodes();
}
/**
@@ -1946,7 +1906,7 @@
* in the graph. For each component containing more than one node, a super node is
* created, effectively replacing the original cyclic nodes.
*/
- void initNodes(Map<Type, Set<Type>> stuckDeps) {
+ void initNodes() {
//add nodes
nodes = new ArrayList<>();
for (Type t : inferenceContext.restvars()) {
@@ -1955,17 +1915,12 @@
//add dependencies
for (Node n_i : nodes) {
Type i = n_i.data.first();
- Set<Type> optDepsByNode = stuckDeps.get(i);
for (Node n_j : nodes) {
Type j = n_j.data.first();
UndetVar uv_i = (UndetVar)inferenceContext.asUndetVar(i);
if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) {
//update i's bound dependencies
- n_i.addDependency(DependencyKind.BOUND, n_j);
- }
- if (optDepsByNode != null && optDepsByNode.contains(j)) {
- //update i's stuck dependencies
- n_i.addDependency(DependencyKind.STUCK, n_j);
+ n_i.addDependency(n_j);
}
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java Thu May 19 19:47:04 2016 +0000
@@ -469,15 +469,11 @@
}
}
- private void solve(GraphStrategy ss, Warner warn) {
- solve(ss, new HashMap<Type, Set<Type>>(), warn);
- }
-
/**
* Solve with given graph strategy.
*/
- private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) {
- GraphSolver s = infer.new GraphSolver(this, stuckDeps, warn);
+ private void solve(GraphStrategy ss, Warner warn) {
+ GraphSolver s = infer.new GraphSolver(this, warn);
s.solve(ss);
}
@@ -506,12 +502,12 @@
/**
* Solve at least one variable in given list.
*/
- public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, Warner warn) {
+ public void solveAny(List<Type> varsToSolve, Warner warn) {
solve(infer.new BestLeafSolver(varsToSolve.intersect(restvars())) {
public boolean done() {
return instvars().intersect(varsToSolve).nonEmpty();
}
- }, optDeps, warn);
+ }, warn);
}
/**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu May 19 19:47:04 2016 +0000
@@ -380,13 +380,17 @@
dest = CharBuffer.allocate(newCapacity).put(dest);
} else if (result.isMalformed() || result.isUnmappable()) {
// bad character in input
+ StringBuilder unmappable = new StringBuilder();
+ int len = result.length();
- log.error(new SimpleDiagnosticPosition(dest.limit()),
- "illegal.char.for.encoding",
- charset == null ? encodingName : charset.name());
+ for (int i = 0; i < len; i++) {
+ unmappable.append(String.format("%02X", inbuf.get()));
+ }
- // skip past the coding error
- inbuf.position(inbuf.position() + result.length());
+ String charsetName = charset == null ? encodingName : charset.name();
+
+ log.error(dest.limit(),
+ Errors.IllegalCharForEncoding(unmappable.toString(), charsetName));
// undo the flip() to prepare the output buffer
// for more translation
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu May 19 19:47:04 2016 +0000
@@ -1138,7 +1138,7 @@
}
}
- if (warn && false) { // temp disable
+ if (warn && false) { // temp disable, when enabled, massage examples.not-yet.txt suitably.
log.warning(Warnings.LocnUnknownFileOnModulePath(p));
}
return null;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu May 19 19:47:04 2016 +0000
@@ -522,8 +522,9 @@
compiler.err.illegal.char=\
illegal character: ''{0}''
+# 0: string, 1: string
compiler.err.illegal.char.for.encoding=\
- unmappable character for encoding {0}
+ unmappable character (0x{0}) for encoding {1}
# 0: set of modifier, 1: set of modifier
compiler.err.illegal.combination.of.modifiers=\
@@ -779,6 +780,10 @@
bad return type in lambda expression\n\
{0}
+compiler.misc.stat.expr.expected=\
+ lambda body is not compatible with a void functional interface\n\
+ (consider using a block lambda body, or use a statement expression instead)
+
# 0: type
compiler.misc.incompatible.ret.type.in.mref=\
bad return type in method reference\n\
@@ -2747,9 +2752,6 @@
compiler.err.module.decl.sb.in.module-info.java=\
module declarations should be in a file named module-info.java
-compiler.err.unexpected.after.module=\
- unexpected input after module declaration
-
compiler.err.module-info.with.xmodule.sourcepath=\
illegal combination of -Xmodule and module-info on sourcepath
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java Thu May 19 19:47:04 2016 +0000
@@ -714,43 +714,43 @@
}
public String getText(String key) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key);
- } catch (Exception e) {
- //Check the shared properties file.
- return message.getText(key);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key);
}
+ // Check the shared properties file.
+ return message.getText(key);
}
public String getText(String key, String a1) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1);
- } catch (Exception e) {
- //Check the shared properties file.
- return message.getText(key, a1);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1);
}
+ // Check the shared properties file.
+ return message.getText(key, a1);
}
public String getText(String key, String a1, String a2) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1, a2);
- } catch (Exception e) {
- //Check the shared properties file.
- return message.getText(key, a1, a2);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1, a2);
}
+ // Check the shared properties file.
+ return message.getText(key, a1, a2);
}
public String getText(String key, String a1, String a2, String a3) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1, a2, a3);
- } catch (Exception e) {
- //Check the shared properties file.
- return message.getText(key, a1, a2, a3);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1, a2, a3);
}
+ // Check the shared properties file.
+ return message.getText(key, a1, a2, a3);
}
public abstract Content newContent();
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Thu May 19 19:47:04 2016 +0000
@@ -83,6 +83,34 @@
this.resourcelocation = resourcelocation;
}
+ private ResourceBundle initRB() {
+ ResourceBundle bundle = messageRB;
+ if (bundle == null) {
+ try {
+ messageRB = bundle =
+ ResourceBundle.getBundle(resourcelocation, configuration.getLocale());
+ } catch (MissingResourceException e) {
+ throw new Error("Fatal: Resource (" + resourcelocation
+ + ") for javadoc doclets is missing.");
+ }
+ }
+ return bundle;
+ }
+
+ /**
+ * Determines whether the given <code>key</code> can be retrieved
+ * from this <code>MessageRetriever</code>
+ *
+ * @param key
+ * the resource <code>key</code>
+ * @return <code>true</code> if the given <code>key</code> is
+ * contained in the underlying <code>ResourceBundle</code>.
+ */
+ public boolean containsKey(String key) {
+ ResourceBundle bundle = initRB();
+ return bundle.containsKey(key);
+ }
+
/**
* Get and format message string from resource
*
@@ -92,15 +120,8 @@
* exist in the properties file.
*/
public String getText(String key, Object... args) throws MissingResourceException {
- if (messageRB == null) {
- try {
- messageRB = ResourceBundle.getBundle(resourcelocation);
- } catch (MissingResourceException e) {
- throw new Error("Fatal: Resource (" + resourcelocation +
- ") for javadoc doclets is missing.");
- }
- }
- String message = messageRB.getString(key);
+ ResourceBundle bundle = initRB();
+ String message = bundle.getString(key);
return MessageFormat.format(message, args);
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java Thu May 19 19:47:04 2016 +0000
@@ -894,43 +894,43 @@
}
public String getText(String key) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key);
- } catch (Exception e) {
- //Check the shared properties file.
- return message.getText(key);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key);
}
+ // Check the shared properties file.
+ return message.getText(key);
}
public String getText(String key, String a1) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1);
- } catch (MissingResourceException e) {
- //Check the shared properties file.
- return message.getText(key, a1);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1);
}
+ // Check the shared properties file.
+ return message.getText(key, a1);
}
public String getText(String key, String a1, String a2) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1, a2);
- } catch (MissingResourceException e) {
- //Check the shared properties file.
- return message.getText(key, a1, a2);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1, a2);
}
+ // Check the shared properties file.
+ return message.getText(key, a1, a2);
}
public String getText(String key, String a1, String a2, String a3) {
- try {
- //Check the doclet specific properties file.
- return getDocletSpecificMsg().getText(key, a1, a2, a3);
- } catch (MissingResourceException e) {
- //Check the shared properties file.
- return message.getText(key, a1, a2, a3);
+ // Check the doclet specific properties file.
+ MessageRetriever docletMessage = getDocletSpecificMsg();
+ if (docletMessage.containsKey(key)) {
+ return docletMessage.getText(key, a1, a2, a3);
}
+ // Check the shared properties file.
+ return message.getText(key, a1, a2, a3);
}
public abstract Content newContent();
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/MessageRetriever.java Thu May 19 19:47:04 2016 +0000
@@ -86,15 +86,32 @@
this.resourcelocation = resourcelocation;
}
- private void initRB() {
- if (messageRB == null) {
+ private ResourceBundle initRB() {
+ ResourceBundle bundle = messageRB;
+ if (bundle == null) {
try {
- messageRB = ResourceBundle.getBundle(resourcelocation, configuration.getLocale());
+ messageRB = bundle =
+ ResourceBundle.getBundle(resourcelocation, configuration.getLocale());
} catch (MissingResourceException e) {
throw new Error("Fatal: Resource (" + resourcelocation
+ ") for javadoc doclets is missing.");
}
}
+ return bundle;
+ }
+
+ /**
+ * Determines whether the given <code>key</code> can be retrieved
+ * from this <code>MessageRetriever</code>
+ *
+ * @param key
+ * the resource <code>key</code>
+ * @return <code>true</code> if the given <code>key</code> is
+ * contained in the underlying <code>ResourceBundle</code>.
+ */
+ public boolean containsKey(String key) {
+ ResourceBundle bundle = initRB();
+ return bundle.containsKey(key);
}
/**
@@ -107,8 +124,8 @@
* exist in the properties file.
*/
public String getText(String key, Object... args) throws MissingResourceException {
- initRB();
- String message = messageRB.getString(key);
+ ResourceBundle bundle = initRB();
+ String message = bundle.getString(key);
return MessageFormat.format(message, args);
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java Thu May 19 19:47:04 2016 +0000
@@ -33,6 +33,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import com.sun.tools.classfile.Dependency.Filter;
@@ -561,13 +562,10 @@
}
static abstract class BasicDependencyFinder implements Finder {
- private Map<String,Location> locations = new HashMap<>();
+ private Map<String,Location> locations = new ConcurrentHashMap<>();
Location getLocation(String className) {
- Location l = locations.get(className);
- if (l == null)
- locations.put(className, l = new SimpleLocation(className));
- return l;
+ return locations.computeIfAbsent(className, cn -> new SimpleLocation(cn));
}
class Visitor implements ConstantPool.Visitor<Void,Void>, Type.Visitor<Void, Void> {
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java Thu May 19 19:47:04 2016 +0000
@@ -25,23 +25,24 @@
package com.sun.tools.jdeps;
-import java.io.PrintStream;
-import java.util.ArrayList;
+import static com.sun.tools.jdeps.JdepsConfiguration.*;
+
+import com.sun.tools.classfile.Dependency.Location;
+import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
+import java.util.MissingResourceException;
import java.util.Objects;
+import java.util.Optional;
+import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import com.sun.tools.classfile.Dependency.Location;
-
/**
* Dependency Analyzer.
*/
@@ -52,6 +53,7 @@
*/
public enum Type {
SUMMARY,
+ MODULE, // equivalent to summary in addition, print module descriptor
PACKAGE,
CLASS,
VERBOSE
@@ -62,9 +64,11 @@
* Only the accepted dependencies are recorded.
*/
interface Filter {
- boolean accepts(Location origin, Archive originArchive, Location target, Archive targetArchive);
+ boolean accepts(Location origin, Archive originArchive,
+ Location target, Archive targetArchive);
}
+ protected final JdepsConfiguration configuration;
protected final Type type;
protected final Filter filter;
protected final Map<Archive, Dependences> results = new HashMap<>();
@@ -78,7 +82,8 @@
* @param type Type of the dependency analysis
* @param filter
*/
- public Analyzer(Type type, Filter filter) {
+ Analyzer(JdepsConfiguration config, Type type, Filter filter) {
+ this.configuration = config;
this.type = type;
this.filter = filter;
}
@@ -86,16 +91,10 @@
/**
* Performs the dependency analysis on the given archives.
*/
- public boolean run(Stream<? extends Archive> archives) {
- return run(archives.collect(Collectors.toList()));
- }
-
- /**
- * Performs the dependency analysis on the given archives.
- */
- public boolean run(Iterable<? extends Archive> archives) {
- // build a map from Location to Archive
- buildLocationArchiveMap(archives);
+ boolean run(Iterable<? extends Archive> archives,
+ Map<Location, Archive> locationMap)
+ {
+ this.locationToArchive.putAll(locationMap);
// traverse and analyze all dependencies
for (Archive archive : archives) {
@@ -106,40 +105,50 @@
return true;
}
- protected void buildLocationArchiveMap(Iterable<? extends Archive> archives) {
- // build a map from Location to Archive
- for (Archive archive: archives) {
- archive.getClasses()
- .forEach(l -> locationToArchive.putIfAbsent(l, archive));
- }
+ /**
+ * Returns the analyzed archives
+ */
+ Set<Archive> archives() {
+ return results.keySet();
}
- public boolean hasDependences(Archive archive) {
+ /**
+ * Returns true if the given archive has dependences.
+ */
+ boolean hasDependences(Archive archive) {
if (results.containsKey(archive)) {
return results.get(archive).dependencies().size() > 0;
}
return false;
}
- public Set<String> dependences(Archive source) {
+ /**
+ * Returns the dependences, either class name or package name
+ * as specified in the given verbose level, from the given source.
+ */
+ Set<String> dependences(Archive source) {
if (!results.containsKey(source)) {
return Collections.emptySet();
}
- Dependences result = results.get(source);
- return result.dependencies().stream()
- .map(Dep::target)
- .collect(Collectors.toSet());
+
+ return results.get(source).dependencies()
+ .stream()
+ .map(Dep::target)
+ .collect(Collectors.toSet());
}
- public Stream<Archive> requires(Archive source) {
+ /**
+ * Returns the direct dependences of the given source
+ */
+ Stream<Archive> requires(Archive source) {
if (!results.containsKey(source)) {
return Stream.empty();
}
- Dependences result = results.get(source);
- return result.requires().stream().filter(a -> !a.isEmpty());
+ return results.get(source).requires()
+ .stream();
}
- public interface Visitor {
+ interface Visitor {
/**
* Visits a recorded dependency from origin to target which can be
* a fully-qualified classname, a package name, a module or
@@ -153,7 +162,7 @@
* Visit the dependencies of the given source.
* If the requested level is SUMMARY, it will visit the required archives list.
*/
- public void visitDependences(Archive source, Visitor v, Type level) {
+ void visitDependences(Archive source, Visitor v, Type level) {
if (level == Type.SUMMARY) {
final Dependences result = results.get(source);
final Set<Archive> reqs = result.requires();
@@ -187,7 +196,7 @@
}
}
- public void visitDependences(Archive source, Visitor v) {
+ void visitDependences(Archive source, Visitor v) {
visitDependences(source, v, type);
}
@@ -224,14 +233,28 @@
}
}
+ /*
+ * Returns the archive that contains the given location.
+ */
Archive findArchive(Location t) {
+ // local in this archive
if (archive.getClasses().contains(t))
return archive;
- return locationToArchive.computeIfAbsent(t, _k -> NOT_FOUND);
+ Archive target;
+ if (locationToArchive.containsKey(t)) {
+ target = locationToArchive.get(t);
+ } else {
+ // special case JDK removed API
+ target = configuration.findClass(t)
+ .orElseGet(() -> REMOVED_JDK_INTERNALS.contains(t)
+ ? REMOVED_JDK_INTERNALS
+ : NOT_FOUND);
+ }
+ return locationToArchive.computeIfAbsent(t, _k -> target);
}
- // return classname or package name depedning on the level
+ // return classname or package name depending on the level
private String getLocationName(Location o) {
if (level == Type.CLASS || level == Type.VERBOSE) {
return o.getClassName();
@@ -345,4 +368,66 @@
target, targetArchive.getName());
}
}
+
+ private static final JdkInternals REMOVED_JDK_INTERNALS = new JdkInternals();
+
+ private static class JdkInternals extends Module {
+ private final String BUNDLE = "com.sun.tools.jdeps.resources.jdkinternals";
+
+ private final Set<String> jdkinternals;
+ private final Set<String> jdkUnsupportedClasses;
+ private JdkInternals() {
+ super("JDK removed internal API");
+
+ try {
+ ResourceBundle rb = ResourceBundle.getBundle(BUNDLE);
+ this.jdkinternals = rb.keySet();
+ } catch (MissingResourceException e) {
+ throw new InternalError("Cannot find jdkinternals resource bundle");
+ }
+
+ this.jdkUnsupportedClasses = getUnsupportedClasses();
+ }
+
+ public boolean contains(Location location) {
+ if (jdkUnsupportedClasses.contains(location.getName() + ".class")) {
+ return false;
+ }
+
+ String cn = location.getClassName();
+ int i = cn.lastIndexOf('.');
+ String pn = i > 0 ? cn.substring(0, i) : "";
+ return jdkinternals.contains(cn) || jdkinternals.contains(pn);
+ }
+
+ @Override
+ public String name() {
+ return getName();
+ }
+
+ @Override
+ public boolean isExported(String pn) {
+ return false;
+ }
+
+ private Set<String> getUnsupportedClasses() {
+ // jdk.unsupported may not be observable
+ Optional<Module> om = Profile.FULL_JRE.findModule(JDK_UNSUPPORTED);
+ if (om.isPresent()) {
+ return om.get().reader().entries();
+ }
+
+ // find from local run-time image
+ SystemModuleFinder system = new SystemModuleFinder();
+ if (system.find(JDK_UNSUPPORTED).isPresent()) {
+ try {
+ return system.getClassReader(JDK_UNSUPPORTED).entries();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ return Collections.emptySet();
+ }
+ }
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java Thu May 19 19:47:04 2016 +0000
@@ -38,6 +38,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
/**
* Represents the source of the class files.
@@ -86,6 +87,10 @@
return Module.UNNAMED_MODULE;
}
+ public boolean contains(String entry) {
+ return reader.entries().contains(entry);
+ }
+
public void addClass(Location origin) {
deps.computeIfAbsent(origin, _k -> new HashSet<>());
}
@@ -98,6 +103,15 @@
return deps.keySet();
}
+ public Stream<Location> getDependencies() {
+ return deps.values().stream()
+ .flatMap(Set::stream);
+ }
+
+ public boolean hasDependences() {
+ return getDependencies().count() > 0;
+ }
+
public void visitDependences(Visitor v) {
for (Map.Entry<Location,Set<Location>> e: deps.entrySet()) {
for (Location target : e.getValue()) {
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java Thu May 19 19:47:04 2016 +0000
@@ -173,7 +173,7 @@
static boolean isClass(Path file) {
String fn = file.getFileName().toString();
- return fn.endsWith(".class") && !fn.equals(MODULE_INFO);
+ return fn.endsWith(".class");
}
class FileIterator implements Iterator<ClassFile> {
@@ -306,7 +306,7 @@
protected Set<String> scan() {
try (JarFile jf = new JarFile(path.toFile())) {
return jf.stream().map(JarEntry::getName)
- .filter(n -> n.endsWith(".class") && !n.endsWith(MODULE_INFO))
+ .filter(n -> n.endsWith(".class"))
.collect(Collectors.toSet());
} catch (IOException e) {
throw new UncheckedIOException(e);
@@ -409,7 +409,7 @@
while (entries.hasMoreElements()) {
JarEntry e = entries.nextElement();
String name = e.getName();
- if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
+ if (name.endsWith(".class")) {
return e;
}
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DependencyFinder.java Thu May 19 19:47:04 2016 +0000
@@ -24,360 +24,285 @@
*/
package com.sun.tools.jdeps;
+import static com.sun.tools.jdeps.Module.*;
+import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
+import static java.util.stream.Collectors.*;
+
import com.sun.tools.classfile.AccessFlags;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Dependencies;
import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
import java.io.IOException;
-import java.nio.file.Path;
-import java.util.ArrayList;
+import java.io.UncheckedIOException;
import java.util.Deque;
import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque;
-import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
-import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static com.sun.tools.jdeps.Module.*;
-import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
+/**
+ * Parses class files and finds dependences
+ */
+class DependencyFinder {
+ private static Finder API_FINDER = new Finder(true);
+ private static Finder CLASS_FINDER = new Finder(false);
+
+ private final JdepsConfiguration configuration;
+ private final JdepsFilter filter;
-public class DependencyFinder {
- private final List<Archive> roots = new ArrayList<>();
- private final List<Archive> classpaths = new ArrayList<>();
- private final List<Module> modulepaths = new ArrayList<>();
- private final List<String> classes = new ArrayList<>();
- private final boolean compileTimeView;
+ private final Map<Finder, Deque<Archive>> parsedArchives = new ConcurrentHashMap<>();
+ private final Map<Location, Archive> parsedClasses = new ConcurrentHashMap<>();
+
+ private final ExecutorService pool = Executors.newFixedThreadPool(2);
+ private final Deque<FutureTask<Set<Location>>> tasks = new ConcurrentLinkedDeque<>();
- DependencyFinder(boolean compileTimeView) {
- this.compileTimeView = compileTimeView;
+ DependencyFinder(JdepsConfiguration configuration,
+ JdepsFilter filter) {
+ this.configuration = configuration;
+ this.filter = filter;
+ this.parsedArchives.put(API_FINDER, new ConcurrentLinkedDeque<>());
+ this.parsedArchives.put(CLASS_FINDER, new ConcurrentLinkedDeque<>());
}
- /*
- * Adds a class name to the root set
- */
- void addClassName(String cn) {
- classes.add(cn);
+ Map<Location, Archive> locationToArchive() {
+ return parsedClasses;
}
- /*
- * Adds the archive of the given path to the root set
+ /**
+ * Returns the modules of all dependencies found
*/
- void addRoot(Path path) {
- addRoot(Archive.getInstance(path));
- }
-
- /*
- * Adds the given archive to the root set
- */
- void addRoot(Archive archive) {
- Objects.requireNonNull(archive);
- if (!roots.contains(archive))
- roots.add(archive);
+ Stream<Archive> getDependences(Archive source) {
+ return source.getDependencies()
+ .map(this::locationToArchive)
+ .filter(a -> a != source);
}
/**
- * Add an archive specified in the classpath.
+ * Returns the location to archive map; or NOT_FOUND.
+ *
+ * Location represents a parsed class.
*/
- void addClassPathArchive(Path path) {
- addClassPathArchive(Archive.getInstance(path));
- }
-
- /**
- * Add an archive specified in the classpath.
- */
- void addClassPathArchive(Archive archive) {
- Objects.requireNonNull(archive);
- classpaths.add(archive);
+ Archive locationToArchive(Location location) {
+ return parsedClasses.containsKey(location)
+ ? parsedClasses.get(location)
+ : configuration.findClass(location).orElse(NOT_FOUND);
}
/**
- * Add an archive specified in the modulepath.
+ * Returns a map from an archive to its required archives
*/
- void addModule(Module m) {
- Objects.requireNonNull(m);
- modulepaths.add(m);
+ Map<Archive, Set<Archive>> dependences() {
+ Map<Archive, Set<Archive>> map = new HashMap<>();
+ parsedArchives.values().stream()
+ .flatMap(Deque::stream)
+ .filter(a -> !a.isEmpty())
+ .forEach(source -> {
+ Set<Archive> deps = getDependences(source).collect(toSet());
+ if (!deps.isEmpty()) {
+ map.put(source, deps);
+ }
+ });
+ return map;
+ }
+
+ boolean isParsed(Location location) {
+ return parsedClasses.containsKey(location);
}
/**
- * Returns the root set.
+ * Parses all class files from the given archive stream and returns
+ * all target locations.
*/
- List<Archive> roots() {
- return roots;
+ public Set<Location> parse(Stream<? extends Archive> archiveStream) {
+ archiveStream.forEach(archive -> parse(archive, CLASS_FINDER));
+ return waitForTasksCompleted();
}
/**
- * Returns a stream of all archives including the root set, module paths,
- * and classpath.
- *
- * This only returns the archives with classes parsed.
+ * Parses the exported API class files from the given archive stream and
+ * returns all target locations.
*/
- Stream<Archive> archives() {
- Stream<Archive> archives = Stream.concat(roots.stream(), modulepaths.stream());
- archives = Stream.concat(archives, classpaths.stream());
- return archives.filter(a -> !a.isEmpty())
- .distinct();
+ public Set<Location> parseExportedAPIs(Stream<? extends Archive> archiveStream) {
+ archiveStream.forEach(archive -> parse(archive, API_FINDER));
+ return waitForTasksCompleted();
+ }
+
+ /**
+ * Parses the named class from the given archive and
+ * returns all target locations the named class references.
+ */
+ public Set<Location> parse(Archive archive, String name) {
+ try {
+ return parse(archive, CLASS_FINDER, name);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
}
/**
- * Finds dependencies
- *
- * @param apiOnly API only
- * @param maxDepth depth of transitive dependency analysis; zero indicates
- * @throws IOException
+ * Parses the exported API of the named class from the given archive and
+ * returns all target locations the named class references.
*/
- void findDependencies(JdepsFilter filter, boolean apiOnly, int maxDepth)
- throws IOException
+ public Set<Location> parseExportedAPIs(Archive archive, String name)
{
- Dependency.Finder finder =
- apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
- : Dependencies.getClassDependencyFinder();
-
- // list of archives to be analyzed
- Set<Archive> roots = new LinkedHashSet<>(this.roots);
-
- // include java.base in root set
- roots.add(JAVA_BASE);
-
- // If -include pattern specified, classes may be in module path or class path.
- // To get compile time view analysis, all classes are analyzed.
- // add all modules except JDK modules to root set
- modulepaths.stream()
- .filter(filter::matches)
- .forEach(roots::add);
+ try {
+ return parse(archive, API_FINDER, name);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
- // add classpath to the root set
- classpaths.stream()
- .filter(filter::matches)
- .forEach(roots::add);
-
- // transitive dependency
- int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE;
+ private Optional<FutureTask<Set<Location>>> parse(Archive archive, Finder finder) {
+ if (parsedArchives.get(finder).contains(archive))
+ return Optional.empty();
- // Work queue of names of classfiles to be searched.
- // Entries will be unique, and for classes that do not yet have
- // dependencies in the results map.
- ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>();
- ConcurrentSkipListSet<String> doneClasses = new ConcurrentSkipListSet<>();
-
- TaskExecutor executor = new TaskExecutor(finder, filter, apiOnly, deque, doneClasses);
- try {
- // get the immediate dependencies of the input files
- for (Archive source : roots) {
- executor.task(source, deque);
- }
- executor.waitForTasksCompleted();
-
- List<Archive> archives = Stream.concat(Stream.concat(roots.stream(),
- modulepaths.stream()),
- classpaths.stream())
- .collect(Collectors.toList());
+ parsedArchives.get(finder).add(archive);
- // Additional pass to find archive where dependences are identified
- // and also any specified classes, if any.
- // If -R is specified, perform transitive dependency analysis.
- Deque<String> unresolved = new LinkedList<>(classes);
- do {
- String name;
- while ((name = unresolved.poll()) != null) {
- if (doneClasses.contains(name)) {
- continue;
+ trace("parsing %s %s%n", archive.getName(), archive.path());
+ FutureTask<Set<Location>> task = new FutureTask<>(new Callable<>() {
+ public Set<Location> call() throws Exception {
+ Set<Location> targets = new HashSet<>();
+ for (ClassFile cf : archive.reader().getClassFiles()) {
+ String classFileName;
+ try {
+ classFileName = cf.getName();
+ } catch (ConstantPoolException e) {
+ throw new Dependencies.ClassFileError(e);
}
- if (compileTimeView) {
- final String cn = name + ".class";
- // parse all classes in the source archive
- Optional<Archive> source = archives.stream()
- .filter(a -> a.reader().entries().contains(cn))
- .findFirst();
- trace("%s compile time view %s%n", name, source.map(Archive::getName).orElse(" not found"));
- if (source.isPresent()) {
- executor.runTask(source.get(), deque);
- }
- }
- ClassFile cf = null;
- for (Archive archive : archives) {
- cf = archive.reader().getClassFile(name);
- if (cf != null) {
- String classFileName;
- try {
- classFileName = cf.getName();
- } catch (ConstantPoolException e) {
- throw new Dependencies.ClassFileError(e);
- }
- if (!doneClasses.contains(classFileName)) {
- // if name is a fully-qualified class name specified
- // from command-line, this class might already be parsed
- doneClasses.add(classFileName);
- for (Dependency d : finder.findDependencies(cf)) {
- if (depth == 0) {
- // ignore the dependency
- archive.addClass(d.getOrigin());
- break;
- } else if (filter.accepts(d) && filter.accept(archive)) {
- // continue analysis on non-JDK classes
- archive.addClass(d.getOrigin(), d.getTarget());
- String cn = d.getTarget().getName();
- if (!doneClasses.contains(cn) && !deque.contains(cn)) {
- deque.add(cn);
- }
- } else {
- // ensure that the parsed class is added the archive
- archive.addClass(d.getOrigin());
- }
- }
- }
- break;
+ // filter source class/archive
+ String cn = classFileName.replace('/', '.');
+ if (!finder.accept(archive, cn, cf.access_flags))
+ continue;
+
+ // tests if this class matches the -include
+ if (!filter.matches(cn))
+ continue;
+
+ for (Dependency d : finder.findDependencies(cf)) {
+ if (filter.accepts(d)) {
+ archive.addClass(d.getOrigin(), d.getTarget());
+ targets.add(d.getTarget());
+ } else {
+ // ensure that the parsed class is added the archive
+ archive.addClass(d.getOrigin());
}
- }
- if (cf == null) {
- doneClasses.add(name);
+ parsedClasses.putIfAbsent(d.getOrigin(), archive);
}
}
- unresolved = deque;
- deque = new ConcurrentLinkedDeque<>();
- } while (!unresolved.isEmpty() && depth-- > 0);
- } finally {
- executor.shutdown();
- }
- }
+
+ return targets;
+ }
+ });
+ tasks.add(task);
+ pool.submit(task);
+ return Optional.of(task);
+ }
- /**
- * TaskExecutor creates FutureTask to analyze all classes in a given archive
- */
- private class TaskExecutor {
- final ExecutorService pool;
- final Dependency.Finder finder;
- final JdepsFilter filter;
- final boolean apiOnly;
- final Set<String> doneClasses;
- final Map<Archive, FutureTask<Void>> tasks = new HashMap<>();
+ private Set<Location> parse(Archive archive, Finder finder, String name)
+ throws IOException
+ {
+ ClassFile cf = archive.reader().getClassFile(name);
+ if (cf == null) {
+ throw new IllegalArgumentException(archive.getName() + " does not contain " + name);
+ }
- TaskExecutor(Dependency.Finder finder,
- JdepsFilter filter,
- boolean apiOnly,
- ConcurrentLinkedDeque<String> deque,
- Set<String> doneClasses) {
- this.pool = Executors.newFixedThreadPool(2);
- this.finder = finder;
- this.filter = filter;
- this.apiOnly = apiOnly;
- this.doneClasses = doneClasses;
+ Set<Location> targets = new HashSet<>();
+ String cn;
+ try {
+ cn = cf.getName().replace('/', '.');
+ } catch (ConstantPoolException e) {
+ throw new Dependencies.ClassFileError(e);
}
- /**
- * Creates a new task to analyze class files in the given archive.
- * The dependences are added to the given deque for analysis.
- */
- FutureTask<Void> task(Archive archive, final ConcurrentLinkedDeque<String> deque) {
- trace("parsing %s %s%n", archive.getName(), archive.path());
- FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
- public Void call() throws Exception {
- for (ClassFile cf : archive.reader().getClassFiles()) {
- String classFileName;
- try {
- classFileName = cf.getName();
- } catch (ConstantPoolException e) {
- throw new Dependencies.ClassFileError(e);
- }
+ if (!finder.accept(archive, cn, cf.access_flags))
+ return targets;
+
+ // tests if this class matches the -include
+ if (!filter.matches(cn))
+ return targets;
- // tests if this class matches the -include
- String cn = classFileName.replace('/', '.');
- if (!filter.matches(cn))
- continue;
+ // skip checking filter.matches
+ for (Dependency d : finder.findDependencies(cf)) {
+ if (filter.accepts(d)) {
+ targets.add(d.getTarget());
+ archive.addClass(d.getOrigin(), d.getTarget());
+ } else {
+ // ensure that the parsed class is added the archive
+ archive.addClass(d.getOrigin());
+ }
+ parsedClasses.putIfAbsent(d.getOrigin(), archive);
+ }
+ return targets;
+ }
- // if -apionly is specified, analyze only exported and public types
- if (apiOnly && !(isExported(archive, cn) && cf.access_flags.is(AccessFlags.ACC_PUBLIC)))
- continue;
-
- if (!doneClasses.contains(classFileName)) {
- doneClasses.add(classFileName);
- }
+ /*
+ * Waits until all submitted tasks are completed.
+ */
+ private Set<Location> waitForTasksCompleted() {
+ try {
+ Set<Location> targets = new HashSet<>();
+ FutureTask<Set<Location>> task;
+ while ((task = tasks.poll()) != null) {
+ // wait for completion
+ if (!task.isDone())
+ targets.addAll(task.get());
+ }
+ return targets;
+ } catch (InterruptedException|ExecutionException e) {
+ throw new Error(e);
+ }
+ }
- for (Dependency d : finder.findDependencies(cf)) {
- if (filter.accepts(d) && filter.accept(archive)) {
- String name = d.getTarget().getName();
- if (!doneClasses.contains(name) && !deque.contains(name)) {
- deque.add(name);
- }
- archive.addClass(d.getOrigin(), d.getTarget());
- } else {
- // ensure that the parsed class is added the archive
- archive.addClass(d.getOrigin());
- }
- }
- }
- return null;
- }
- });
- tasks.put(archive, task);
- pool.submit(task);
- return task;
+ /*
+ * Shutdown the executor service.
+ */
+ void shutdown() {
+ pool.shutdown();
+ }
+
+ private interface SourceFilter {
+ boolean accept(Archive archive, String cn, AccessFlags accessFlags);
+ }
+
+ private static class Finder implements Dependency.Finder, SourceFilter {
+ private final Dependency.Finder finder;
+ private final boolean apiOnly;
+ Finder(boolean apiOnly) {
+ this.apiOnly = apiOnly;
+ this.finder = apiOnly
+ ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
+ : Dependencies.getClassDependencyFinder();
+
}
- /*
- * This task will parse all class files of the given archive, if it's a new task.
- * This method waits until the task is completed.
- */
- void runTask(Archive archive, final ConcurrentLinkedDeque<String> deque) {
- if (tasks.containsKey(archive))
- return;
+ @Override
+ public boolean accept(Archive archive, String cn, AccessFlags accessFlags) {
+ int i = cn.lastIndexOf('.');
+ String pn = i > 0 ? cn.substring(0, i) : "";
- FutureTask<Void> task = task(archive, deque);
- try {
- // wait for completion
- task.get();
- } catch (InterruptedException|ExecutionException e) {
- throw new Error(e);
- }
+ // if -apionly is specified, analyze only exported and public types
+ // All packages are exported in unnamed module.
+ return apiOnly ? archive.getModule().isExported(pn) &&
+ accessFlags.is(AccessFlags.ACC_PUBLIC)
+ : true;
}
- /*
- * Waits until all submitted tasks are completed.
- */
- void waitForTasksCompleted() {
- try {
- for (FutureTask<Void> t : tasks.values()) {
- if (t.isDone())
- continue;
-
- // wait for completion
- t.get();
- }
- } catch (InterruptedException|ExecutionException e) {
- throw new Error(e);
- }
- }
-
- /*
- * Shutdown the executor service.
- */
- void shutdown() {
- pool.shutdown();
- }
-
- /**
- * Tests if the given class name is exported by the given archive.
- *
- * All packages are exported in unnamed module.
- */
- private boolean isExported(Archive archive, String classname) {
- int i = classname.lastIndexOf('.');
- String pn = i > 0 ? classname.substring(0, i) : "";
- return archive.getModule().isExported(pn);
+ @Override
+ public Iterable<? extends Dependency> findDependencies(ClassFile classfile) {
+ return finder.findDependencies(classfile);
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeps;
+
+import com.sun.tools.classfile.Dependency.Location;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.sun.tools.jdeps.Analyzer.Type.CLASS;
+import static com.sun.tools.jdeps.Analyzer.Type.VERBOSE;
+import static com.sun.tools.jdeps.Module.trace;
+import static java.util.stream.Collectors.*;
+
+/**
+ * Dependency Analyzer.
+ *
+ * Type of filters:
+ * source filter: -include <pattern>
+ * target filter: -package, -regex, -requires
+ *
+ * The initial archive set for analysis includes
+ * 1. archives specified in the command line arguments
+ * 2. observable modules matching the source filter
+ * 3. classpath archives matching the source filter or target filter
+ * 4. -addmods and -m root modules
+ */
+public class DepsAnalyzer {
+ final JdepsConfiguration configuration;
+ final JdepsFilter filter;
+ final JdepsWriter writer;
+ final Analyzer.Type verbose;
+ final boolean apiOnly;
+
+ final DependencyFinder finder;
+ final Analyzer analyzer;
+ final List<Archive> rootArchives = new ArrayList<>();
+
+ // parsed archives
+ final Set<Archive> archives = new LinkedHashSet<>();
+
+ public DepsAnalyzer(JdepsConfiguration config,
+ JdepsFilter filter,
+ JdepsWriter writer,
+ Analyzer.Type verbose,
+ boolean apiOnly) {
+ this.configuration = config;
+ this.filter = filter;
+ this.writer = writer;
+ this.verbose = verbose;
+ this.apiOnly = apiOnly;
+
+ this.finder = new DependencyFinder(config, filter);
+ this.analyzer = new Analyzer(configuration, verbose, filter);
+
+ // determine initial archives to be analyzed
+ this.rootArchives.addAll(configuration.initialArchives());
+
+ // if -include pattern is specified, add the matching archives on
+ // classpath to the root archives
+ if (filter.hasIncludePattern() || filter.hasTargetFilter()) {
+ configuration.getModules().values().stream()
+ .filter(source -> filter.include(source) && filter.matches(source))
+ .forEach(this.rootArchives::add);
+ }
+
+ // class path archives
+ configuration.classPathArchives().stream()
+ .filter(filter::matches)
+ .forEach(this.rootArchives::add);
+
+ // Include the root modules for analysis
+ this.rootArchives.addAll(configuration.rootModules());
+
+ trace("analyze root archives: %s%n", this.rootArchives);
+ }
+
+ /*
+ * Perform runtime dependency analysis
+ */
+ public boolean run() throws IOException {
+ return run(false, 1);
+ }
+
+ /**
+ * Perform compile-time view or run-time view dependency analysis.
+ *
+ * @param compileTimeView
+ * @param maxDepth depth of recursive analysis. depth == 0 if -R is set
+ */
+ public boolean run(boolean compileTimeView, int maxDepth) throws IOException {
+ try {
+ // parse each packaged module or classpath archive
+ if (apiOnly) {
+ finder.parseExportedAPIs(rootArchives.stream());
+ } else {
+ finder.parse(rootArchives.stream());
+ }
+ archives.addAll(rootArchives);
+
+ int depth = maxDepth > 0 ? maxDepth : Integer.MAX_VALUE;
+
+ // transitive analysis
+ if (depth > 1) {
+ if (compileTimeView)
+ transitiveArchiveDeps(depth-1);
+ else
+ transitiveDeps(depth-1);
+ }
+
+ Set<Archive> archives = archives();
+
+ // analyze the dependencies collected
+ analyzer.run(archives, finder.locationToArchive());
+
+ writer.generateOutput(archives, analyzer);
+ } finally {
+ finder.shutdown();
+ }
+ return true;
+ }
+
+ /**
+ * Returns the archives for reporting that has matching dependences.
+ *
+ * If -requires is set, they should be excluded.
+ */
+ Set<Archive> archives() {
+ if (filter.requiresFilter().isEmpty()) {
+ return archives.stream()
+ .filter(filter::include)
+ .filter(Archive::hasDependences)
+ .collect(Collectors.toSet());
+ } else {
+ // use the archives that have dependences and not specified in -requires
+ return archives.stream()
+ .filter(filter::include)
+ .filter(source -> !filter.requiresFilter().contains(source))
+ .filter(source ->
+ source.getDependencies()
+ .map(finder::locationToArchive)
+ .anyMatch(a -> a != source))
+ .collect(Collectors.toSet());
+ }
+ }
+
+ /**
+ * Returns the dependences, either class name or package name
+ * as specified in the given verbose level.
+ */
+ Stream<String> dependences() {
+ return analyzer.archives().stream()
+ .map(analyzer::dependences)
+ .flatMap(Set::stream)
+ .distinct();
+ }
+
+ /**
+ * Returns the archives that contains the given locations and
+ * not parsed and analyzed.
+ */
+ private Set<Archive> unresolvedArchives(Stream<Location> locations) {
+ return locations.filter(l -> !finder.isParsed(l))
+ .distinct()
+ .map(configuration::findClass)
+ .flatMap(Optional::stream)
+ .filter(filter::include)
+ .collect(toSet());
+ }
+
+ /*
+ * Recursively analyzes entire module/archives.
+ */
+ private void transitiveArchiveDeps(int depth) throws IOException {
+ Stream<Location> deps = archives.stream()
+ .flatMap(Archive::getDependencies);
+
+ // start with the unresolved archives
+ Set<Archive> unresolved = unresolvedArchives(deps);
+ do {
+ // parse all unresolved archives
+ Set<Location> targets = apiOnly
+ ? finder.parseExportedAPIs(unresolved.stream())
+ : finder.parse(unresolved.stream());
+ archives.addAll(unresolved);
+
+ // Add dependencies to the next batch for analysis
+ unresolved = unresolvedArchives(targets.stream());
+ } while (!unresolved.isEmpty() && depth-- > 0);
+ }
+
+ /*
+ * Recursively analyze the class dependences
+ */
+ private void transitiveDeps(int depth) throws IOException {
+ Stream<Location> deps = archives.stream()
+ .flatMap(Archive::getDependencies);
+
+ Deque<Location> unresolved = deps.collect(Collectors.toCollection(LinkedList::new));
+ ConcurrentLinkedDeque<Location> deque = new ConcurrentLinkedDeque<>();
+ do {
+ Location target;
+ while ((target = unresolved.poll()) != null) {
+ if (finder.isParsed(target))
+ continue;
+
+ Archive archive = configuration.findClass(target).orElse(null);
+ if (archive != null && filter.include(archive)) {
+ archives.add(archive);
+
+ String name = target.getName();
+ Set<Location> targets = apiOnly
+ ? finder.parseExportedAPIs(archive, name)
+ : finder.parse(archive, name);
+
+ // build unresolved dependencies
+ targets.stream()
+ .filter(t -> !finder.isParsed(t))
+ .forEach(deque::add);
+ }
+ }
+ unresolved = deque;
+ deque = new ConcurrentLinkedDeque<>();
+ } while (!unresolved.isEmpty() && depth-- > 0);
+ }
+
+ // ----- for testing purpose -----
+
+ public static enum Info {
+ REQUIRES,
+ REQUIRES_PUBLIC,
+ EXPORTED_API,
+ MODULE_PRIVATE,
+ QUALIFIED_EXPORTED_API,
+ INTERNAL_API,
+ JDK_INTERNAL_API
+ }
+
+ public static class Node {
+ public final String name;
+ public final String source;
+ public final Info info;
+ Node(String name, Info info) {
+ this(name, name, info);
+ }
+ Node(String name, String source, Info info) {
+ this.name = name;
+ this.source = source;
+ this.info = info;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (info != Info.REQUIRES && info != Info.REQUIRES_PUBLIC)
+ sb.append(source).append("/");
+
+ sb.append(name);
+ if (info == Info.QUALIFIED_EXPORTED_API)
+ sb.append(" (qualified)");
+ else if (info == Info.JDK_INTERNAL_API)
+ sb.append(" (JDK internal)");
+ else if (info == Info.INTERNAL_API)
+ sb.append(" (internal)");
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Node))
+ return false;
+
+ Node other = (Node)o;
+ return this.name.equals(other.name) &&
+ this.source.equals(other.source) &&
+ this.info.equals(other.info);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name.hashCode();
+ result = 31 * result + source.hashCode();
+ result = 31 * result + info.hashCode();
+ return result;
+ }
+ }
+
+ /**
+ * Returns a graph of module dependences.
+ *
+ * Each Node represents a module and each edge is a dependence.
+ * No analysis on "requires public".
+ */
+ public Graph<Node> moduleGraph() {
+ Graph.Builder<Node> builder = new Graph.Builder<>();
+
+ archives().stream()
+ .forEach(m -> {
+ Node u = new Node(m.getName(), Info.REQUIRES);
+ builder.addNode(u);
+ analyzer.requires(m)
+ .map(req -> new Node(req.getName(), Info.REQUIRES))
+ .forEach(v -> builder.addEdge(u, v));
+ });
+ return builder.build();
+ }
+
+ /**
+ * Returns a graph of dependences.
+ *
+ * Each Node represents a class or package per the specified verbose level.
+ * Each edge indicates
+ */
+ public Graph<Node> dependenceGraph() {
+ Graph.Builder<Node> builder = new Graph.Builder<>();
+
+ archives().stream()
+ .map(analyzer.results::get)
+ .filter(deps -> !deps.dependencies().isEmpty())
+ .flatMap(deps -> deps.dependencies().stream())
+ .forEach(d -> addEdge(builder, d));
+ return builder.build();
+ }
+
+ private void addEdge(Graph.Builder<Node> builder, Analyzer.Dep dep) {
+ Archive source = dep.originArchive();
+ Archive target = dep.targetArchive();
+ String pn = dep.target();
+ if ((verbose == CLASS || verbose == VERBOSE)) {
+ int i = dep.target().lastIndexOf('.');
+ pn = i > 0 ? dep.target().substring(0, i) : "";
+ }
+ final Info info;
+ if (source == target) {
+ info = Info.MODULE_PRIVATE;
+ } else if (!target.getModule().isNamed()) {
+ info = Info.EXPORTED_API;
+ } else if (target.getModule().isExported(pn)) {
+ info = Info.EXPORTED_API;
+ } else {
+ Module module = target.getModule();
+
+ if (!source.getModule().isJDK() && module.isJDK())
+ info = Info.JDK_INTERNAL_API;
+ // qualified exports or inaccessible
+ else if (module.isExported(pn, source.getModule().name()))
+ info = Info.QUALIFIED_EXPORTED_API;
+ else
+ info = Info.INTERNAL_API;
+ }
+
+ Node u = new Node(dep.origin(), source.getName(), info);
+ Node v = new Node(dep.target(), target.getName(), info);
+ builder.addEdge(u, v);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Graph.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.tools.jdeps;
+
+import java.io.PrintWriter;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public final class Graph<T> {
+ private final Set<T> nodes;
+ private final Map<T, Set<T>> edges;
+
+ public Graph(Set<T> nodes, Map<T, Set<T>> edges) {
+ this.nodes = Collections.unmodifiableSet(nodes);
+ this.edges = Collections.unmodifiableMap(edges);
+ }
+
+ public Set<T> nodes() {
+ return nodes;
+ }
+
+ public Map<T, Set<T>> edges() {
+ return edges;
+ }
+
+ public Set<T> adjacentNodes(T u) {
+ return edges.get(u);
+ }
+
+ public boolean contains(T u) {
+ return nodes.contains(u);
+ }
+
+ public Set<Edge<T>> edgesFrom(T u) {
+ return edges.get(u).stream()
+ .map(v -> new Edge<T>(u, v))
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Returns a new Graph after transitive reduction
+ */
+ public Graph<T> reduce() {
+ Builder<T> builder = new Builder<>();
+ nodes.stream()
+ .forEach(u -> {
+ builder.addNode(u);
+ edges.get(u).stream()
+ .filter(v -> !pathExists(u, v, false))
+ .forEach(v -> builder.addEdge(u, v));
+ });
+ return builder.build();
+ }
+
+ /**
+ * Returns a new Graph after transitive reduction. All edges in
+ * the given g takes precedence over this graph.
+ *
+ * @throw IllegalArgumentException g must be a subgraph this graph
+ */
+ public Graph<T> reduce(Graph<T> g) {
+ boolean subgraph = nodes.containsAll(g.nodes) &&
+ g.edges.keySet().stream()
+ .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u)));
+ if (!subgraph) {
+ throw new IllegalArgumentException(g + " is not a subgraph of " + this);
+ }
+
+ Builder<T> builder = new Builder<>();
+ nodes.stream()
+ .forEach(u -> {
+ builder.addNode(u);
+ // filter the edge if there exists a path from u to v in the given g
+ // or there exists another path from u to v in this graph
+ edges.get(u).stream()
+ .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false))
+ .forEach(v -> builder.addEdge(u, v));
+ });
+
+ // add the overlapped edges from this graph and the given g
+ g.edges().keySet().stream()
+ .forEach(u -> g.adjacentNodes(u).stream()
+ .filter(v -> isAdjacent(u, v))
+ .forEach(v -> builder.addEdge(u, v)));
+ return builder.build();
+ }
+
+ /**
+ * Returns nodes sorted in topological order.
+ */
+ public Stream<T> orderedNodes() {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ return sorter.result.stream();
+ }
+
+ /**
+ * Traverse this graph and performs the given action in topological order
+ */
+ public void ordered(Consumer<T> action) {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ sorter.ordered(action);
+ }
+
+ /**
+ * Traverses this graph and performs the given action in reverse topological order
+ */
+ public void reverse(Consumer<T> action) {
+ TopoSorter<T> sorter = new TopoSorter<>(this);
+ sorter.reverse(action);
+ }
+
+ /**
+ * Returns a transposed graph from this graph
+ */
+ public Graph<T> transpose() {
+ Builder<T> builder = new Builder<>();
+ builder.addNodes(nodes);
+ // reverse edges
+ edges.keySet().forEach(u -> {
+ edges.get(u).stream()
+ .forEach(v -> builder.addEdge(v, u));
+ });
+ return builder.build();
+ }
+
+ /**
+ * Returns all nodes reachable from the given set of roots.
+ */
+ public Set<T> dfs(Set<T> roots) {
+ Deque<T> deque = new LinkedList<>(roots);
+ Set<T> visited = new HashSet<>();
+ while (!deque.isEmpty()) {
+ T u = deque.pop();
+ if (!visited.contains(u)) {
+ visited.add(u);
+ if (contains(u)) {
+ adjacentNodes(u).stream()
+ .filter(v -> !visited.contains(v))
+ .forEach(deque::push);
+ }
+ }
+ }
+ return visited;
+ }
+
+ private boolean isAdjacent(T u, T v) {
+ return edges.containsKey(u) && edges.get(u).contains(v);
+ }
+
+ private boolean pathExists(T u, T v) {
+ return pathExists(u, v, true);
+ }
+
+ /**
+ * Returns true if there exists a path from u to v in this graph.
+ * If includeAdjacent is false, it returns true if there exists
+ * another path from u to v of distance > 1
+ */
+ private boolean pathExists(T u, T v, boolean includeAdjacent) {
+ if (!nodes.contains(u) || !nodes.contains(v)) {
+ return false;
+ }
+ if (includeAdjacent && isAdjacent(u, v)) {
+ return true;
+ }
+ Deque<T> stack = new LinkedList<>();
+ Set<T> visited = new HashSet<>();
+ stack.push(u);
+ while (!stack.isEmpty()) {
+ T node = stack.pop();
+ if (node.equals(v)) {
+ return true;
+ }
+ if (!visited.contains(node)) {
+ visited.add(node);
+ edges.get(node).stream()
+ .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v))
+ .forEach(e -> stack.push(e));
+ }
+ }
+ assert !visited.contains(v);
+ return false;
+ }
+
+ public void printGraph(PrintWriter out) {
+ out.println("graph for " + nodes);
+ nodes.stream()
+ .forEach(u -> adjacentNodes(u).stream()
+ .forEach(v -> out.format(" %s -> %s%n", u, v)));
+ }
+
+ @Override
+ public String toString() {
+ return nodes.toString();
+ }
+
+ static class Edge<T> {
+ final T u;
+ final T v;
+ Edge(T u, T v) {
+ this.u = u;
+ this.v = v;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s -> %s", u, v);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !(o instanceof Edge))
+ return false;
+
+ @SuppressWarnings("unchecked")
+ Edge<T> edge = (Edge<T>) o;
+
+ return u.equals(edge.u) && v.equals(edge.v);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = u.hashCode();
+ result = 31 * result + v.hashCode();
+ return result;
+ }
+ }
+
+ static class Builder<T> {
+ final Set<T> nodes = new HashSet<>();
+ final Map<T, Set<T>> edges = new HashMap<>();
+
+ public void addNode(T node) {
+ if (nodes.contains(node)) {
+ return;
+ }
+ nodes.add(node);
+ edges.computeIfAbsent(node, _e -> new HashSet<>());
+ }
+
+ public void addNodes(Set<T> nodes) {
+ nodes.addAll(nodes);
+ }
+
+ public void addEdge(T u, T v) {
+ addNode(u);
+ addNode(v);
+ edges.get(u).add(v);
+ }
+
+ public Graph<T> build() {
+ return new Graph<T>(nodes, edges);
+ }
+ }
+
+ /**
+ * Topological sort
+ */
+ static class TopoSorter<T> {
+ final Deque<T> result = new LinkedList<>();
+ final Deque<T> nodes;
+ final Graph<T> graph;
+ TopoSorter(Graph<T> graph) {
+ this.graph = graph;
+ this.nodes = new LinkedList<>(graph.nodes);
+ sort();
+ }
+
+ public void ordered(Consumer<T> action) {
+ result.iterator().forEachRemaining(action);
+ }
+
+ public void reverse(Consumer<T> action) {
+ result.descendingIterator().forEachRemaining(action);
+ }
+
+ private void sort() {
+ Deque<T> visited = new LinkedList<>();
+ Deque<T> done = new LinkedList<>();
+ T node;
+ while ((node = nodes.poll()) != null) {
+ if (!visited.contains(node)) {
+ visit(node, visited, done);
+ }
+ }
+ }
+
+ private void visit(T node, Deque<T> visited, Deque<T> done) {
+ if (visited.contains(node)) {
+ if (!done.contains(node)) {
+ throw new IllegalArgumentException("Cyclic detected: " +
+ node + " " + graph.edges().get(node));
+ }
+ return;
+ }
+ visited.add(node);
+ graph.edges().get(node).stream()
+ .forEach(x -> visit(x, visited, done));
+ done.add(node);
+ result.addLast(node);
+ }
+ }
+
+ public static class DotGraph {
+ static final String ORANGE = "#e76f00";
+ static final String BLUE = "#437291";
+ static final String GRAY = "#dddddd";
+
+ static final String REEXPORTS = "";
+ static final String REQUIRES = "style=\"dashed\"";
+ static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
+
+ static final Set<String> javaModules = modules(name ->
+ (name.startsWith("java.") && !name.equals("java.smartcardio")));
+ static final Set<String> jdkModules = modules(name ->
+ (name.startsWith("java.") ||
+ name.startsWith("jdk.") ||
+ name.startsWith("javafx.")) && !javaModules.contains(name));
+
+ private static Set<String> modules(Predicate<String> predicate) {
+ return ModuleFinder.ofSystem().findAll()
+ .stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .filter(predicate)
+ .collect(Collectors.toSet());
+ }
+
+ static void printAttributes(PrintWriter out) {
+ out.format(" size=\"25,25\";%n");
+ out.format(" nodesep=.5;%n");
+ out.format(" ranksep=1.5;%n");
+ out.format(" pencolor=transparent;%n");
+ out.format(" node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n");
+ out.format(" edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n");
+ }
+
+ static void printNodes(PrintWriter out, Graph<String> graph) {
+ out.format(" subgraph se {%n");
+ graph.nodes().stream()
+ .filter(javaModules::contains)
+ .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
+ mn, ORANGE, "java"));
+ out.format(" }%n");
+ graph.nodes().stream()
+ .filter(jdkModules::contains)
+ .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
+ mn, BLUE, "jdk"));
+
+ graph.nodes().stream()
+ .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn))
+ .forEach(mn -> out.format(" \"%s\";%n", mn));
+ }
+
+ static void printEdges(PrintWriter out, Graph<String> graph,
+ String node, Set<String> requiresPublic) {
+ graph.adjacentNodes(node).forEach(dn -> {
+ String attr = dn.equals("java.base") ? REQUIRES_BASE
+ : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
+ out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
+ });
+ }
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/InverseDepsAnalyzer.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeps;
+
+import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER;
+import static com.sun.tools.jdeps.Module.trace;
+import static com.sun.tools.jdeps.Graph.*;
+
+import java.lang.module.ModuleDescriptor.Requires;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Inverse transitive dependency analysis (compile-time view)
+ */
+public class InverseDepsAnalyzer extends DepsAnalyzer {
+ // the end points for the resulting paths to be reported
+ private final Map<Archive, Set<Archive>> endPoints = new HashMap<>();
+ // target archives for inverse transitive dependence analysis
+ private final Set<Archive> targets = new HashSet<>();
+
+ public InverseDepsAnalyzer(JdepsConfiguration config,
+ JdepsFilter filter,
+ JdepsWriter writer,
+ Analyzer.Type verbose,
+ boolean apiOnly) {
+ super(config, filter, writer, verbose, apiOnly);
+ }
+
+ public boolean run() throws IOException {
+ try {
+ if (apiOnly) {
+ finder.parseExportedAPIs(rootArchives.stream());
+ } else {
+ finder.parse(rootArchives.stream());
+ }
+ archives.addAll(rootArchives);
+
+ Set<Archive> archives = archives();
+
+ // If -package or -regex is specified, the archives that reference
+ // the matching types are used as the targets for inverse
+ // transitive analysis. If -requires is specified, the
+ // specified modules are the targets.
+
+ if (filter.requiresFilter().isEmpty()) {
+ targets.addAll(archives);
+ } else {
+ filter.requiresFilter().stream()
+ .map(configuration::findModule)
+ .flatMap(Optional::stream)
+ .forEach(targets::add);
+ }
+
+ // If -package or -regex is specified, the end points are
+ // the matching archives. If -requires is specified,
+ // the end points are the modules specified in -requires.
+ if (filter.requiresFilter().isEmpty()) {
+ Map<Archive, Set<Archive>> dependences = finder.dependences();
+ targets.forEach(source -> endPoints.put(source, dependences.get(source)));
+ } else {
+ targets.forEach(t -> endPoints.put(t, Collections.emptySet()));
+ }
+
+ analyzer.run(archives, finder.locationToArchive());
+
+ // print the first-level of dependencies
+ if (writer != null) {
+ writer.generateOutput(archives, analyzer);
+ }
+
+ } finally {
+ finder.shutdown();
+ }
+ return true;
+ }
+
+ /**
+ * Returns the target archives determined from the dependency analysis.
+ *
+ * Inverse transitive dependency will find all nodes that depend
+ * upon the returned set of archives directly and indirectly.
+ */
+ public Set<Archive> targets() {
+ return Collections.unmodifiableSet(targets);
+ }
+
+ /**
+ * Finds all inverse transitive dependencies using the given requires set
+ * as the targets, if non-empty. If the given requires set is empty,
+ * use the archives depending the packages specified in -regex or -p options.
+ */
+ public Set<Deque<Archive>> inverseDependences() throws IOException {
+ // create a new dependency finder to do the analysis
+ DependencyFinder dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER);
+ try {
+ // parse all archives in unnamed module to get compile-time dependences
+ Stream<Archive> archives =
+ Stream.concat(configuration.initialArchives().stream(),
+ configuration.classPathArchives().stream());
+ if (apiOnly) {
+ dependencyFinder.parseExportedAPIs(archives);
+ } else {
+ dependencyFinder.parse(archives);
+ }
+
+ Graph.Builder<Archive> builder = new Graph.Builder<>();
+ // include all target nodes
+ targets().forEach(builder::addNode);
+
+ // transpose the module graph - may filter JDK module
+ configuration.getModules().values().stream()
+ .filter(filter::include)
+ .forEach(m -> {
+ builder.addNode(m);
+ m.descriptor().requires().stream()
+ .map(Requires::name)
+ .map(configuration::findModule) // must be present
+ .forEach(v -> builder.addEdge(v.get(), m));
+ });
+
+ // add the dependences from the analysis
+ Map<Archive, Set<Archive>> dependences = dependencyFinder.dependences();
+ dependences.entrySet().stream()
+ .forEach(e -> {
+ Archive u = e.getKey();
+ builder.addNode(u);
+ e.getValue().forEach(v -> builder.addEdge(v, u));
+ });
+
+ // transposed dependence graph.
+ Graph<Archive> graph = builder.build();
+ trace("targets: %s%n", targets());
+
+ // Traverse from the targets and find all paths
+ // rebuild a graph with all nodes that depends on targets
+ // targets directly and indirectly
+ return targets().stream()
+ .map(t -> findPaths(graph, t))
+ .flatMap(Set::stream)
+ .collect(Collectors.toSet());
+ } finally {
+ dependencyFinder.shutdown();
+ }
+ }
+
+ /**
+ * Returns all paths reachable from the given targets.
+ */
+ private Set<Deque<Archive>> findPaths(Graph<Archive> graph, Archive target) {
+
+ // path is in reversed order
+ Deque<Archive> path = new LinkedList<>();
+ path.push(target);
+
+ Set<Edge<Archive>> visited = new HashSet<>();
+
+ Deque<Edge<Archive>> deque = new LinkedList<>();
+ deque.addAll(graph.edgesFrom(target));
+ if (deque.isEmpty()) {
+ return makePaths(path).collect(Collectors.toSet());
+ }
+
+ Set<Deque<Archive>> allPaths = new HashSet<>();
+ while (!deque.isEmpty()) {
+ Edge<Archive> edge = deque.pop();
+
+ if (visited.contains(edge))
+ continue;
+
+ Archive node = edge.v;
+ path.addLast(node);
+ visited.add(edge);
+
+ Set<Edge<Archive>> unvisitedDeps = graph.edgesFrom(node)
+ .stream()
+ .filter(e -> !visited.contains(e))
+ .collect(Collectors.toSet());
+
+ trace("visiting %s %s (%s)%n", edge, path, unvisitedDeps);
+ if (unvisitedDeps.isEmpty()) {
+ makePaths(path).forEach(allPaths::add);
+ path.removeLast();
+ }
+
+ // push unvisited adjacent edges
+ unvisitedDeps.stream().forEach(deque::push);
+
+
+ // when the adjacent edges of a node are visited, pop it from the path
+ while (!path.isEmpty()) {
+ if (visited.containsAll(graph.edgesFrom(path.peekLast())))
+ path.removeLast();
+ else
+ break;
+ }
+ }
+
+ return allPaths;
+ }
+
+ /**
+ * Prepend end point to the path
+ */
+ private Stream<Deque<Archive>> makePaths(Deque<Archive> path) {
+ Set<Archive> nodes = endPoints.get(path.peekFirst());
+ if (nodes == null || nodes.isEmpty()) {
+ return Stream.of(new LinkedList<>(path));
+ } else {
+ return nodes.stream().map(n -> {
+ Deque<Archive> newPath = new LinkedList<>();
+ newPath.addFirst(n);
+ newPath.addAll(path);
+ return newPath;
+ });
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.jdeps;
+
+import static com.sun.tools.jdeps.Module.trace;
+import static java.util.stream.Collectors.*;
+
+import com.sun.tools.classfile.Dependency;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReader;
+import java.lang.module.ModuleReference;
+import java.lang.module.ResolvedModule;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+public class JdepsConfiguration {
+ // the token for "all modules on the module path"
+ public static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
+ public static final String ALL_DEFAULT = "ALL-DEFAULT";
+ public static final String MODULE_INFO = "module-info.class";
+
+ private final SystemModuleFinder system;
+ private final ModuleFinder finder;
+
+ private final Map<String, Module> nameToModule = new LinkedHashMap<>();
+ private final Map<String, Module> packageToModule = new HashMap<>();
+ private final Map<String, List<Archive>> packageToUnnamedModule = new HashMap<>();
+
+ private final List<Archive> classpathArchives = new ArrayList<>();
+ private final List<Archive> initialArchives = new ArrayList<>();
+ private final Set<Module> rootModules = new HashSet<>();
+ private final Configuration configuration;
+
+ private JdepsConfiguration(SystemModuleFinder systemModulePath,
+ ModuleFinder finder,
+ Set<String> roots,
+ List<Path> classpaths,
+ List<Archive> initialArchives,
+ boolean allDefaultModules)
+ throws IOException
+ {
+ trace("root: %s%n", roots);
+
+ this.system = systemModulePath;
+ this.finder = finder;
+
+ // build root set for resolution
+ Set<String> mods = new HashSet<>(roots);
+
+ // add default modules to the root set
+ // unnamed module
+ if (!initialArchives.isEmpty() || !classpaths.isEmpty() ||
+ roots.isEmpty() || allDefaultModules) {
+ mods.addAll(systemModulePath.defaultSystemRoots());
+ }
+
+ this.configuration = Configuration.empty()
+ .resolveRequires(finder, ModuleFinder.of(), mods);
+
+ this.configuration.modules().stream()
+ .map(ResolvedModule::reference)
+ .forEach(this::addModuleReference);
+
+ // packages in unnamed module
+ initialArchives.forEach(archive -> {
+ addPackagesInUnnamedModule(archive);
+ this.initialArchives.add(archive);
+ });
+
+ // classpath archives
+ for (Path p : classpaths) {
+ if (Files.exists(p)) {
+ Archive archive = Archive.getInstance(p);
+ addPackagesInUnnamedModule(archive);
+ classpathArchives.add(archive);
+ }
+ }
+
+ // all roots specified in -addmods or -m are included
+ // as the initial set for analysis.
+ roots.stream()
+ .map(nameToModule::get)
+ .forEach(this.rootModules::add);
+
+ initProfiles();
+
+ trace("resolved modules: %s%n", nameToModule.keySet().stream()
+ .sorted().collect(joining("\n", "\n", "")));
+ }
+
+ private void initProfiles() {
+ // other system modules are not observed and not added in nameToModule map
+ Map<String, Module> systemModules =
+ system.moduleNames()
+ .collect(toMap(Function.identity(), (mn) -> {
+ Module m = nameToModule.get(mn);
+ if (m == null) {
+ ModuleReference mref = finder.find(mn).get();
+ m = toModule(mref);
+ }
+ return m;
+ }));
+ Profile.init(systemModules);
+ }
+
+ private void addModuleReference(ModuleReference mref) {
+ Module module = toModule(mref);
+ nameToModule.put(mref.descriptor().name(), module);
+ mref.descriptor().packages()
+ .forEach(pn -> packageToModule.putIfAbsent(pn, module));
+ }
+
+ private void addPackagesInUnnamedModule(Archive archive) {
+ archive.reader().entries().stream()
+ .filter(e -> e.endsWith(".class") && !e.equals(MODULE_INFO))
+ .map(this::toPackageName)
+ .distinct()
+ .forEach(pn -> packageToUnnamedModule
+ .computeIfAbsent(pn, _n -> new ArrayList<>()).add(archive));
+ }
+
+ private String toPackageName(String name) {
+ int i = name.lastIndexOf('/');
+ return i > 0 ? name.replace('/', '.').substring(0, i) : "";
+ }
+
+ public Optional<Module> findModule(String name) {
+ Objects.requireNonNull(name);
+ Module m = nameToModule.get(name);
+ return m!= null ? Optional.of(m) : Optional.empty();
+
+ }
+
+ public Optional<ModuleDescriptor> findModuleDescriptor(String name) {
+ Objects.requireNonNull(name);
+ Module m = nameToModule.get(name);
+ return m!= null ? Optional.of(m.descriptor()) : Optional.empty();
+ }
+
+ boolean isSystem(Module m) {
+ return system.find(m.name()).isPresent();
+ }
+
+ boolean isValidToken(String name) {
+ return ALL_MODULE_PATH.equals(name) || ALL_DEFAULT.equals(name);
+ }
+
+ /**
+ * Returns the modules that the given module can read
+ */
+ public Stream<Module> reads(Module module) {
+ return configuration.findModule(module.name()).get()
+ .reads().stream()
+ .map(ResolvedModule::name)
+ .map(nameToModule::get);
+ }
+
+ /**
+ * Returns the list of packages that split between resolved module and
+ * unnamed module
+ */
+ public Map<String, Set<String>> splitPackages() {
+ Set<String> splitPkgs = packageToModule.keySet().stream()
+ .filter(packageToUnnamedModule::containsKey)
+ .collect(toSet());
+ if (splitPkgs.isEmpty())
+ return Collections.emptyMap();
+
+ return splitPkgs.stream().collect(toMap(Function.identity(), (pn) -> {
+ Set<String> sources = new LinkedHashSet<>();
+ sources.add(packageToModule.get(pn).getModule().location().toString());
+ packageToUnnamedModule.get(pn).stream()
+ .map(Archive::getPathName)
+ .forEach(sources::add);
+ return sources;
+ }));
+ }
+
+ /**
+ * Returns an optional archive containing the given Location
+ */
+ public Optional<Archive> findClass(Dependency.Location location) {
+ String name = location.getName();
+ int i = name.lastIndexOf('/');
+ String pn = i > 0 ? name.substring(0, i).replace('/', '.') : "";
+ Archive archive = packageToModule.get(pn);
+ if (archive != null) {
+ return archive.contains(name + ".class")
+ ? Optional.of(archive)
+ : Optional.empty();
+ }
+
+ if (packageToUnnamedModule.containsKey(pn)) {
+ return packageToUnnamedModule.get(pn).stream()
+ .filter(a -> a.contains(name + ".class"))
+ .findFirst();
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Returns the list of Modules that can be found in the specified
+ * module paths.
+ */
+ public Map<String, Module> getModules() {
+ return nameToModule;
+ }
+
+ public Stream<Module> resolve(Set<String> roots) {
+ if (roots.isEmpty()) {
+ return nameToModule.values().stream();
+ } else {
+ return Configuration.empty()
+ .resolveRequires(finder, ModuleFinder.of(), roots)
+ .modules().stream()
+ .map(ResolvedModule::name)
+ .map(nameToModule::get);
+ }
+ }
+
+ public List<Archive> classPathArchives() {
+ return classpathArchives;
+ }
+
+ public List<Archive> initialArchives() {
+ return initialArchives;
+ }
+
+ public Set<Module> rootModules() {
+ return rootModules;
+ }
+
+ public Module toModule(ModuleReference mref) {
+ try {
+ String mn = mref.descriptor().name();
+ URI location = mref.location().orElseThrow(FileNotFoundException::new);
+ ModuleDescriptor md = mref.descriptor();
+ Module.Builder builder = new Module.Builder(md, system.find(mn).isPresent());
+
+ final ClassFileReader reader;
+ if (location.getScheme().equals("jrt")) {
+ reader = system.getClassReader(mn);
+ } else {
+ reader = ClassFileReader.newInstance(Paths.get(location));
+ }
+
+ builder.classes(reader);
+ builder.location(location);
+
+ return builder.build();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ static class SystemModuleFinder implements ModuleFinder {
+ private static final String JAVA_HOME = System.getProperty("java.home");
+ private static final String JAVA_SE = "java.se";
+
+ private final FileSystem fileSystem;
+ private final Path root;
+ private final Map<String, ModuleReference> systemModules;
+
+ SystemModuleFinder() {
+ if (Files.isRegularFile(Paths.get(JAVA_HOME, "lib", "modules"))) {
+ // jrt file system
+ this.fileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
+ this.root = fileSystem.getPath("/modules");
+ this.systemModules = walk(root);
+ } else {
+ // exploded image
+ this.fileSystem = FileSystems.getDefault();
+ root = Paths.get(JAVA_HOME, "modules");
+ this.systemModules = ModuleFinder.ofSystem().findAll().stream()
+ .collect(toMap(mref -> mref.descriptor().name(), Function.identity()));
+ }
+ }
+
+ SystemModuleFinder(String javaHome) throws IOException {
+ if (javaHome == null) {
+ // -system none
+ this.fileSystem = null;
+ this.root = null;
+ this.systemModules = Collections.emptyMap();
+ } else {
+ if (Files.isRegularFile(Paths.get(javaHome, "lib", "modules")))
+ throw new IllegalArgumentException("Invalid java.home: " + javaHome);
+
+ // alternate java.home
+ Map<String, String> env = new HashMap<>();
+ env.put("java.home", javaHome);
+ // a remote run-time image
+ this.fileSystem = FileSystems.newFileSystem(URI.create("jrt:/"), env);
+ this.root = fileSystem.getPath("/modules");
+ this.systemModules = walk(root);
+ }
+ }
+
+ private Map<String, ModuleReference> walk(Path root) {
+ try {
+ return Files.walk(root, 1)
+ .filter(path -> !path.equals(root))
+ .map(this::toModuleReference)
+ .collect(toMap(mref -> mref.descriptor().name(),
+ Function.identity()));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private ModuleReference toModuleReference(Path path) {
+ Path minfo = path.resolve(MODULE_INFO);
+ try (InputStream in = Files.newInputStream(minfo);
+ BufferedInputStream bin = new BufferedInputStream(in)) {
+
+ ModuleDescriptor descriptor = dropHashes(ModuleDescriptor.read(bin));
+ String mn = descriptor.name();
+ URI uri = URI.create("jrt:/" + path.getFileName().toString());
+ Supplier<ModuleReader> readerSupplier = new Supplier<>() {
+ @Override
+ public ModuleReader get() {
+ return new ModuleReader() {
+ @Override
+ public Optional<URI> find(String name) throws IOException {
+ return name.equals(mn)
+ ? Optional.of(uri) : Optional.empty();
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ };
+ }
+ };
+
+ return new ModuleReference(descriptor, uri, readerSupplier);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private ModuleDescriptor dropHashes(ModuleDescriptor md) {
+ ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(md.name());
+ md.requires().forEach(builder::requires);
+ md.exports().forEach(builder::exports);
+ md.provides().values().stream().forEach(builder::provides);
+ md.uses().stream().forEach(builder::uses);
+ builder.conceals(md.conceals());
+ return builder.build();
+ }
+
+ @Override
+ public Set<ModuleReference> findAll() {
+ return systemModules.values().stream().collect(toSet());
+ }
+
+ @Override
+ public Optional<ModuleReference> find(String mn) {
+ return systemModules.containsKey(mn)
+ ? Optional.of(systemModules.get(mn)) : Optional.empty();
+ }
+
+ public Stream<String> moduleNames() {
+ return systemModules.values().stream()
+ .map(mref -> mref.descriptor().name());
+ }
+
+ public ClassFileReader getClassReader(String modulename) throws IOException {
+ Path mp = root.resolve(modulename);
+ if (Files.exists(mp) && Files.isDirectory(mp)) {
+ return ClassFileReader.newInstance(fileSystem, mp);
+ } else {
+ throw new FileNotFoundException(mp.toString());
+ }
+ }
+
+ public Set<String> defaultSystemRoots() {
+ Set<String> roots = new HashSet<>();
+ boolean hasJava = false;
+ if (systemModules.containsKey(JAVA_SE)) {
+ // java.se is a system module
+ hasJava = true;
+ roots.add(JAVA_SE);
+ }
+
+ for (ModuleReference mref : systemModules.values()) {
+ String mn = mref.descriptor().name();
+ if (hasJava && mn.startsWith("java."))
+ continue;
+
+ // add as root if observable and exports at least one package
+ ModuleDescriptor descriptor = mref.descriptor();
+ for (ModuleDescriptor.Exports e : descriptor.exports()) {
+ if (!e.isQualified()) {
+ roots.add(mn);
+ break;
+ }
+ }
+ }
+ return roots;
+ }
+ }
+
+ public static class Builder {
+
+ final SystemModuleFinder systemModulePath;
+ final Set<String> rootModules = new HashSet<>();
+ final List<Archive> initialArchives = new ArrayList<>();
+ final List<Path> paths = new ArrayList<>();
+ final List<Path> classPaths = new ArrayList<>();
+
+ ModuleFinder upgradeModulePath;
+ ModuleFinder appModulePath;
+ boolean addAllApplicationModules;
+ boolean addAllDefaultModules;
+
+ public Builder() {
+ this.systemModulePath = new SystemModuleFinder();
+ }
+
+ public Builder(String javaHome) throws IOException {
+ this.systemModulePath = SystemModuleFinder.JAVA_HOME.equals(javaHome)
+ ? new SystemModuleFinder()
+ : new SystemModuleFinder(javaHome);
+ }
+
+ public Builder upgradeModulePath(String upgradeModulePath) {
+ this.upgradeModulePath = createModulePathFinder(upgradeModulePath);
+ return this;
+ }
+
+ public Builder appModulePath(String modulePath) {
+ this.appModulePath = createModulePathFinder(modulePath);
+ return this;
+ }
+
+ public Builder addmods(Set<String> addmods) {
+ for (String mn : addmods) {
+ switch (mn) {
+ case ALL_MODULE_PATH:
+ this.addAllApplicationModules = true;
+ break;
+ case ALL_DEFAULT:
+ this.addAllDefaultModules = true;
+ break;
+ default:
+ this.rootModules.add(mn);
+ }
+ }
+ return this;
+ }
+
+ /*
+ * This method is for -check option to find all target modules specified
+ * in qualified exports.
+ *
+ * Include all system modules and modules found on modulepath
+ */
+ public Builder allModules() {
+ systemModulePath.moduleNames()
+ .forEach(this.rootModules::add);
+ this.addAllApplicationModules = true;
+ return this;
+ }
+
+ public Builder addRoot(Path path) {
+ Archive archive = Archive.getInstance(path);
+ if (archive.contains(MODULE_INFO)) {
+ paths.add(path);
+ } else {
+ initialArchives.add(archive);
+ }
+ return this;
+ }
+
+ public Builder addClassPath(String classPath) {
+ this.classPaths.addAll(getClassPaths(classPath));
+ return this;
+ }
+
+ public JdepsConfiguration build() throws IOException {
+ ModuleFinder finder = systemModulePath;
+ if (upgradeModulePath != null) {
+ finder = ModuleFinder.compose(upgradeModulePath, systemModulePath);
+ }
+ if (appModulePath != null) {
+ finder = ModuleFinder.compose(finder, appModulePath);
+ }
+ if (!paths.isEmpty()) {
+ ModuleFinder otherModulePath = ModuleFinder.of(paths.toArray(new Path[0]));
+
+ finder = ModuleFinder.compose(finder, otherModulePath);
+ // add modules specified on command-line (convenience) as root set
+ otherModulePath.findAll().stream()
+ .map(mref -> mref.descriptor().name())
+ .forEach(rootModules::add);
+ }
+ if (addAllApplicationModules && appModulePath != null) {
+ appModulePath.findAll().stream()
+ .map(mref -> mref.descriptor().name())
+ .forEach(rootModules::add);
+ }
+
+ return new JdepsConfiguration(systemModulePath,
+ finder,
+ rootModules,
+ classPaths,
+ initialArchives,
+ addAllDefaultModules);
+ }
+
+ private static ModuleFinder createModulePathFinder(String mpaths) {
+ if (mpaths == null) {
+ return null;
+ } else {
+ String[] dirs = mpaths.split(File.pathSeparator);
+ Path[] paths = new Path[dirs.length];
+ int i = 0;
+ for (String dir : dirs) {
+ paths[i++] = Paths.get(dir);
+ }
+ return ModuleFinder.of(paths);
+ }
+ }
+
+ /*
+ * Returns the list of Archive specified in cpaths and not included
+ * initialArchives
+ */
+ private List<Path> getClassPaths(String cpaths) {
+ if (cpaths.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<Path> paths = new ArrayList<>();
+ for (String p : cpaths.split(File.pathSeparator)) {
+ if (p.length() > 0) {
+ // wildcard to parse all JAR files e.g. -classpath dir/*
+ int i = p.lastIndexOf(".*");
+ if (i > 0) {
+ Path dir = Paths.get(p.substring(0, i));
+ try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.jar")) {
+ for (Path entry : stream) {
+ paths.add(entry);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ } else {
+ paths.add(Paths.get(p));
+ }
+ }
+ }
+ return paths;
+ }
+ }
+
+}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java Thu May 19 19:47:04 2016 +0000
@@ -41,22 +41,27 @@
* 2. -filter:package to filter out same-package dependencies
* This filter is applied when jdeps parses the class files
* and filtered dependencies are not stored in the Analyzer.
- * 3. -module specifies to match target dependencies from the given module
+ * 3. -requires specifies to match target dependence from the given module
* This gets expanded into package lists to be filtered.
* 4. -filter:archive to filter out same-archive dependencies
* This filter is applied later in the Analyzer as the
* containing archive of a target class may not be known until
* the entire archive
*/
-class JdepsFilter implements Dependency.Filter, Analyzer.Filter {
+public class JdepsFilter implements Dependency.Filter, Analyzer.Filter {
+
+ public static final JdepsFilter DEFAULT_FILTER =
+ new JdepsFilter.Builder().filter(true, true).build();
+
private final Dependency.Filter filter;
private final Pattern filterPattern;
private final boolean filterSamePackage;
private final boolean filterSameArchive;
private final boolean findJDKInternals;
private final Pattern includePattern;
- private final Set<String> includePackages;
- private final Set<String> excludeModules;
+ private final Pattern includeSystemModules;
+
+ private final Set<String> requires;
private JdepsFilter(Dependency.Filter filter,
Pattern filterPattern,
@@ -64,16 +69,16 @@
boolean filterSameArchive,
boolean findJDKInternals,
Pattern includePattern,
- Set<String> includePackages,
- Set<String> excludeModules) {
+ Pattern includeSystemModules,
+ Set<String> requires) {
this.filter = filter;
this.filterPattern = filterPattern;
this.filterSamePackage = filterSamePackage;
this.filterSameArchive = filterSameArchive;
this.findJDKInternals = findJDKInternals;
this.includePattern = includePattern;
- this.includePackages = includePackages;
- this.excludeModules = excludeModules;
+ this.includeSystemModules = includeSystemModules;
+ this.requires = requires;
}
/**
@@ -82,12 +87,7 @@
* @param cn fully-qualified name
*/
public boolean matches(String cn) {
- if (includePackages.isEmpty() && includePattern == null)
- return true;
-
- int i = cn.lastIndexOf('.');
- String pn = i > 0 ? cn.substring(0, i) : "";
- if (includePackages.contains(pn))
+ if (includePattern == null)
return true;
if (includePattern != null)
@@ -97,29 +97,39 @@
}
/**
- * Tests if the given source includes classes specified in includePattern
- * or includePackages filters.
+ * Tests if the given source includes classes specified in -include option
*
* This method can be used to determine if the given source should eagerly
* be processed.
*/
public boolean matches(Archive source) {
- if (!includePackages.isEmpty() && source.getModule().isNamed()) {
- boolean found = source.getModule().packages()
- .stream()
- .filter(pn -> includePackages.contains(pn))
- .findAny().isPresent();
- if (found)
- return true;
+ if (includePattern != null) {
+ return source.reader().entries().stream()
+ .map(name -> name.replace('/', '.'))
+ .filter(name -> !name.equals("module-info.class"))
+ .anyMatch(this::matches);
}
- if (!includePackages.isEmpty() || includePattern != null) {
- return source.reader().entries()
- .stream()
- .map(name -> name.replace('/', '.'))
- .filter(this::matches)
- .findAny().isPresent();
- }
- return false;
+ return hasTargetFilter();
+ }
+
+ public boolean include(Archive source) {
+ Module module = source.getModule();
+ // skip system module by default; or if includeSystemModules is set
+ // only include the ones matching the pattern
+ return !module.isSystem() || (includeSystemModules != null &&
+ includeSystemModules.matcher(module.name()).matches());
+ }
+
+ public boolean hasIncludePattern() {
+ return includePattern != null || includeSystemModules != null;
+ }
+
+ public boolean hasTargetFilter() {
+ return filter != null;
+ }
+
+ public Set<String> requiresFilter() {
+ return requires;
}
// ----- Dependency.Filter -----
@@ -164,42 +174,35 @@
return true;
}
- /**
- * Returns true if dependency should be recorded for the given source.
- */
- public boolean accept(Archive source) {
- return !excludeModules.contains(source.getName());
- }
-
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("exclude modules: ")
- .append(excludeModules.stream().sorted().collect(Collectors.joining(",")))
- .append("\n");
+ sb.append("include pattern: ").append(includePattern).append("\n");
sb.append("filter same archive: ").append(filterSameArchive).append("\n");
sb.append("filter same package: ").append(filterSamePackage).append("\n");
+ sb.append("requires: ").append(requires).append("\n");
return sb.toString();
}
- static class Builder {
- Dependency.Filter filter;
+ public static class Builder {
+ static Pattern SYSTEM_MODULE_PATTERN = Pattern.compile("java\\..*|jdk\\..*|javafx\\..*");
Pattern filterPattern;
+ Pattern regex;
boolean filterSamePackage;
boolean filterSameArchive;
boolean findJDKInterals;
// source filters
Pattern includePattern;
- Set<String> includePackages = new HashSet<>();
- Set<String> includeModules = new HashSet<>();
- Set<String> excludeModules = new HashSet<>();
+ Pattern includeSystemModules;
+ Set<String> requires = new HashSet<>();
+ Set<String> targetPackages = new HashSet<>();
public Builder packages(Set<String> packageNames) {
- this.filter = Dependencies.getPackageFilter(packageNames, false);
+ this.targetPackages.addAll(packageNames);
return this;
}
public Builder regex(Pattern regex) {
- this.filter = Dependencies.getRegexFilter(regex);
+ this.regex = regex;
return this;
}
public Builder filter(Pattern regex) {
@@ -211,6 +214,13 @@
this.filterSameArchive = sameArchive;
return this;
}
+ public Builder requires(String name, Set<String> packageNames) {
+ this.requires.add(name);
+ this.targetPackages.addAll(packageNames);
+
+ includeIfSystemModule(name);
+ return this;
+ }
public Builder findJDKInternals(boolean value) {
this.findJDKInterals = value;
return this;
@@ -219,30 +229,33 @@
this.includePattern = regex;
return this;
}
- public Builder includePackage(String pn) {
- this.includePackages.add(pn);
+ public Builder includeSystemModules(Pattern regex) {
+ this.includeSystemModules = regex;
return this;
}
- public Builder includeModules(Set<String> includes) {
- this.includeModules.addAll(includes);
- return this;
- }
- public Builder excludeModules(Set<String> excludes) {
- this.excludeModules.addAll(excludes);
+ public Builder includeIfSystemModule(String name) {
+ if (includeSystemModules == null &&
+ SYSTEM_MODULE_PATTERN.matcher(name).matches()) {
+ this.includeSystemModules = SYSTEM_MODULE_PATTERN;
+ }
return this;
}
- JdepsFilter build() {
+ public JdepsFilter build() {
+ Dependency.Filter filter = null;
+ if (regex != null)
+ filter = Dependencies.getRegexFilter(regex);
+ else if (!targetPackages.isEmpty()) {
+ filter = Dependencies.getPackageFilter(targetPackages, false);
+ }
return new JdepsFilter(filter,
filterPattern,
filterSamePackage,
filterSameArchive,
findJDKInterals,
includePattern,
- includePackages,
- excludeModules.stream()
- .filter(mn -> !includeModules.contains(mn))
- .collect(Collectors.toSet()));
+ includeSystemModules,
+ requires);
}
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Thu May 19 19:47:04 2016 +0000
@@ -25,31 +25,29 @@
package com.sun.tools.jdeps;
+import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
import static com.sun.tools.jdeps.Analyzer.Type.*;
import static com.sun.tools.jdeps.JdepsWriter.*;
-import static com.sun.tools.jdeps.ModuleAnalyzer.Graph;
+import static com.sun.tools.jdeps.JdepsConfiguration.ALL_MODULE_PATH;
-import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.module.ResolutionException;
-import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
-import java.util.Optional;
import java.util.ResourceBundle;
import java.util.Set;
-import java.util.TreeMap;
+import java.util.function.Function;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -58,7 +56,12 @@
* Implementation for the jdeps tool for static class dependency analysis.
*/
class JdepsTask {
- static class BadArgs extends Exception {
+ static interface BadArguments {
+ String getKey();
+ Object[] getArgs();
+ boolean showUsage();
+ }
+ static class BadArgs extends Exception implements BadArguments {
static final long serialVersionUID = 8765093759964640721L;
BadArgs(String key, Object... args) {
super(JdepsTask.getMessage(key, args));
@@ -73,6 +76,44 @@
final String key;
final Object[] args;
boolean showUsage;
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public Object[] getArgs() {
+ return args;
+ }
+
+ @Override
+ public boolean showUsage() {
+ return showUsage;
+ }
+ }
+
+ static class UncheckedBadArgs extends RuntimeException implements BadArguments {
+ static final long serialVersionUID = -1L;
+ final BadArgs cause;
+ UncheckedBadArgs(BadArgs cause) {
+ super(cause);
+ this.cause = cause;
+ }
+ @Override
+ public String getKey() {
+ return cause.key;
+ }
+
+ @Override
+ public Object[] getArgs() {
+ return cause.args;
+ }
+
+ @Override
+ public boolean showUsage() {
+ return cause.showUsage;
+ }
}
static abstract class Option {
@@ -126,7 +167,7 @@
if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
throw new BadArgs("err.invalid.path", arg);
}
- task.options.dotOutputDir = arg;
+ task.options.dotOutputDir = Paths.get(arg);;
}
},
new Option(false, "-s", "-summary") {
@@ -136,8 +177,9 @@
}
},
new Option(false, "-v", "-verbose",
- "-verbose:package",
- "-verbose:class") {
+ "-verbose:module",
+ "-verbose:package",
+ "-verbose:class") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
switch (opt) {
case "-v":
@@ -146,6 +188,9 @@
task.options.filterSameArchive = false;
task.options.filterSamePackage = false;
break;
+ case "-verbose:module":
+ task.options.verbose = MODULE;
+ break;
case "-verbose:package":
task.options.verbose = PACKAGE;
break;
@@ -157,6 +202,80 @@
}
}
},
+ new Option(false, "-apionly") {
+ void process(JdepsTask task, String opt, String arg) {
+ task.options.apiOnly = true;
+ }
+ },
+ new Option(true, "-check") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ Set<String> mods = Set.of(arg.split(","));
+ task.options.checkModuleDeps = mods;
+ task.options.addmods.addAll(mods);
+ }
+ },
+ new Option(true, "-genmoduleinfo") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ Path p = Paths.get(arg);
+ if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
+ throw new BadArgs("err.invalid.path", arg);
+ }
+ task.options.genModuleInfo = Paths.get(arg);
+ }
+ },
+ new Option(false, "-jdkinternals") {
+ void process(JdepsTask task, String opt, String arg) {
+ task.options.findJDKInternals = true;
+ task.options.verbose = CLASS;
+ if (task.options.includePattern == null) {
+ task.options.includePattern = Pattern.compile(".*");
+ }
+ }
+ },
+
+ // ---- paths option ----
+ new Option(true, "-cp", "-classpath") {
+ void process(JdepsTask task, String opt, String arg) {
+ task.options.classpath = arg;
+ }
+ },
+ new Option(true, "-mp", "-modulepath") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ task.options.modulePath = arg;
+ }
+ },
+ new Option(true, "-upgrademodulepath") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ task.options.upgradeModulePath = arg;
+ }
+ },
+ new Option(true, "-system") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ if (arg.equals("none")) {
+ task.options.systemModulePath = null;
+ } else {
+ Path path = Paths.get(arg);
+ if (Files.isRegularFile(path.resolve("lib").resolve("modules")))
+ task.options.systemModulePath = arg;
+ else
+ throw new BadArgs("err.invalid.path", arg);
+ }
+ }
+ },
+ new Option(true, "-addmods") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ Set<String> mods = Set.of(arg.split(","));
+ task.options.addmods.addAll(mods);
+ }
+ },
+ new Option(true, "-m") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ task.options.rootModule = arg;
+ task.options.addmods.add(arg);
+ }
+ },
+
+ // ---- Target filtering options ----
new Option(true, "-p", "-package") {
void process(JdepsTask task, String opt, String arg) {
task.options.packageNames.add(arg);
@@ -167,7 +286,7 @@
task.options.regex = Pattern.compile(arg);
}
},
- new Option(true, "-module") {
+ new Option(true, "-requires") {
void process(JdepsTask task, String opt, String arg) {
task.options.requires.add(arg);
}
@@ -198,28 +317,27 @@
}
}
},
+
+ // ---- Source filtering options ----
new Option(true, "-include") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
task.options.includePattern = Pattern.compile(arg);
}
},
+
+ // Another alternative to list modules in -addmods option
+ new HiddenOption(true, "-include-system-modules") {
+ void process(JdepsTask task, String opt, String arg) throws BadArgs {
+ task.options.includeSystemModulePattern = Pattern.compile(arg);
+ }
+ },
+
new Option(false, "-P", "-profile") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
task.options.showProfile = true;
- task.options.showModule = false;
}
},
- new Option(false, "-M") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- task.options.showModule = true;
- task.options.showProfile = false;
- }
- },
- new Option(false, "-apionly") {
- void process(JdepsTask task, String opt, String arg) {
- task.options.apiOnly = true;
- }
- },
+
new Option(false, "-R", "-recursive") {
void process(JdepsTask task, String opt, String arg) {
task.options.depth = 0;
@@ -228,15 +346,17 @@
task.options.filterSamePackage = false;
}
},
- new Option(true, "-genmoduleinfo") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- Path p = Paths.get(arg);
- if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
- throw new BadArgs("err.invalid.path", arg);
- }
- task.options.genModuleInfo = arg;
+
+ new Option(false, "-I", "-inverse") {
+ void process(JdepsTask task, String opt, String arg) {
+ task.options.inverse = true;
+ // equivalent to the inverse of compile-time view analysis
+ task.options.compileTimeView = true;
+ task.options.filterSamePackage = true;
+ task.options.filterSameArchive = true;
}
},
+
new Option(false, "-ct", "-compile-time") {
void process(JdepsTask task, String opt, String arg) {
task.options.compileTimeView = true;
@@ -245,62 +365,11 @@
task.options.depth = 0;
}
},
- new Option(false, "-jdkinternals") {
- void process(JdepsTask task, String opt, String arg) {
- task.options.findJDKInternals = true;
- task.options.verbose = CLASS;
- if (task.options.includePattern == null) {
- task.options.includePattern = Pattern.compile(".*");
- }
- }
- },
- new Option(true, "-cp", "-classpath") {
- void process(JdepsTask task, String opt, String arg) {
- task.options.classpath = arg;
- }
- },
- new Option(true, "-mp", "-modulepath") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- task.options.modulePath = arg;
- task.options.showModule = true;
- }
- },
- new Option(true, "-upgrademodulepath") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- task.options.upgradeModulePath = arg;
- task.options.showModule = true;
- }
- },
- new Option(true, "-m") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- task.options.rootModule = arg;
- task.options.includes.add(arg);
- task.options.showModule = true;
- }
- },
- new Option(false, "-check") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- task.options.checkModuleDeps = true;
- }
- },
- new HiddenOption(true, "-include-modules") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- Arrays.stream(arg.split(","))
- .forEach(task.options.includes::add);
- task.options.showModule = true;
- }
- },
- new HiddenOption(true, "-exclude-modules") {
- void process(JdepsTask task, String opt, String arg) throws BadArgs {
- Arrays.stream(arg.split(","))
- .forEach(task.options.excludes::add);
- task.options.showModule = true;
- }
- },
+
new Option(false, "-q", "-quiet") {
void process(JdepsTask task, String opt, String arg) {
- task.options.nowarning = true;
- }
+ task.options.nowarning = true;
+ }
},
new Option(false, "-version") {
@@ -318,7 +387,11 @@
task.options.showLabel = true;
}
},
-
+ new HiddenOption(false, "-hide-module") {
+ void process(JdepsTask task, String opt, String arg) {
+ task.options.showModule = false;
+ }
+ },
new HiddenOption(true, "-depth") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
try {
@@ -332,7 +405,7 @@
private static final String PROGNAME = "jdeps";
private final Options options = new Options();
- private final List<String> classes = new ArrayList<>();
+ private final List<String> inputArgs = new ArrayList<>();
private PrintWriter log;
void setLog(PrintWriter out) {
@@ -342,13 +415,13 @@
/**
* Result codes.
*/
- static final int EXIT_OK = 0, // Completed with no errors.
- EXIT_ERROR = 1, // Completed but reported errors.
- EXIT_CMDERR = 2, // Bad command-line arguments
- EXIT_SYSERR = 3, // System error or resource exhaustion.
- EXIT_ABNORMAL = 4;// terminated abnormally
+ static final int EXIT_OK = 0, // Completed with no errors.
+ EXIT_ERROR = 1, // Completed but reported errors.
+ EXIT_CMDERR = 2, // Bad command-line arguments
+ EXIT_SYSERR = 3, // System error or resource exhaustion.
+ EXIT_ABNORMAL = 4; // terminated abnormally
- int run(String[] args) {
+ int run(String... args) {
if (log == null) {
log = new PrintWriter(System.out);
}
@@ -360,15 +433,11 @@
if (options.version || options.fullVersion) {
showVersion(options.fullVersion);
}
- if (options.rootModule != null && !classes.isEmpty()) {
- reportError("err.invalid.module.option", options.rootModule, classes);
- return EXIT_CMDERR;
+ if (!inputArgs.isEmpty() && options.rootModule != null) {
+ reportError("err.invalid.arg.for.option", "-m");
}
- if (options.checkModuleDeps && options.rootModule == null) {
- reportError("err.root.module.not.set");
- return EXIT_CMDERR;
- }
- if (classes.isEmpty() && options.rootModule == null && options.includePattern == null) {
+ if (inputArgs.isEmpty() && options.addmods.isEmpty() && options.includePattern == null
+ && options.includeSystemModulePattern == null && options.checkModuleDeps == null) {
if (options.help || options.version || options.fullVersion) {
return EXIT_OK;
} else {
@@ -377,19 +446,10 @@
}
}
if (options.genModuleInfo != null) {
- if (options.dotOutputDir != null || !options.classpath.isEmpty() || options.hasFilter()) {
+ if (options.dotOutputDir != null || options.classpath != null || options.hasFilter()) {
showHelp();
return EXIT_CMDERR;
}
- // default to compile time view analysis
- options.compileTimeView = true;
- for (String fn : classes) {
- Path p = Paths.get(fn);
- if (!Files.exists(p) || !fn.endsWith(".jar")) {
- reportError("err.genmoduleinfo.not.jarfile", fn);
- return EXIT_CMDERR;
- }
- }
}
if (options.numFilters() > 1) {
@@ -397,6 +457,16 @@
return EXIT_CMDERR;
}
+ if (options.inverse && options.depth != 1) {
+ reportError("err.invalid.inverse.option", "-R");
+ return EXIT_CMDERR;
+ }
+
+ if (options.inverse && options.numFilters() == 0) {
+ reportError("err.invalid.filters");
+ return EXIT_CMDERR;
+ }
+
if ((options.findJDKInternals) && (options.hasFilter() || options.showSummary)) {
showHelp();
return EXIT_CMDERR;
@@ -405,12 +475,15 @@
showHelp();
return EXIT_CMDERR;
}
+ if (options.checkModuleDeps != null && !inputArgs.isEmpty()) {
+ reportError("err.invalid.module.option", inputArgs, "-check");
+ }
boolean ok = run();
return ok ? EXIT_OK : EXIT_ERROR;
- } catch (BadArgs e) {
- reportError(e.key, e.args);
- if (e.showUsage) {
+ } catch (BadArgs|UncheckedBadArgs e) {
+ reportError(e.getKey(), e.getArgs());
+ if (e.showUsage()) {
log.println(getMessage("main.usage.summary", PROGNAME));
}
return EXIT_CMDERR;
@@ -419,176 +492,217 @@
return EXIT_CMDERR;
} catch (IOException e) {
e.printStackTrace();
- return EXIT_ABNORMAL;
+ return EXIT_CMDERR;
} finally {
log.flush();
}
}
- private ModulePaths modulePaths;
- private boolean run() throws BadArgs, IOException {
- DependencyFinder dependencyFinder =
- new DependencyFinder(options.compileTimeView);
+ boolean run() throws IOException {
+ JdepsConfiguration config = buildConfig();
- buildArchive(dependencyFinder);
+ // detect split packages
+ config.splitPackages().entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> System.out.format("split package: %s %s%n", e.getKey(),
+ e.getValue().toString()));
- if (options.rootModule != null &&
- (options.checkModuleDeps || (options.dotOutputDir != null &&
- options.verbose == SUMMARY))) {
- // -dotfile -s prints the configuration of the given root
- // -checkModuleDeps prints the suggested module-info.java
- return analyzeModules(dependencyFinder);
+ // check if any module specified in -requires is missing
+ Stream.concat(options.addmods.stream(), options.requires.stream())
+ .filter(mn -> !config.isValidToken(mn))
+ .forEach(mn -> config.findModule(mn).orElseThrow(() ->
+ new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
+
+ // -genmoduleinfo
+ if (options.genModuleInfo != null) {
+ return genModuleInfo(config);
}
- // otherwise analyze the dependencies
- if (options.genModuleInfo != null) {
- return genModuleInfo(dependencyFinder);
+ // -check
+ if (options.checkModuleDeps != null) {
+ return new ModuleAnalyzer(config, log, options.checkModuleDeps).run();
+ }
+
+ if (options.dotOutputDir != null &&
+ (options.verbose == SUMMARY || options.verbose == MODULE) &&
+ !options.addmods.isEmpty() && inputArgs.isEmpty()) {
+ return new ModuleAnalyzer(config, log).genDotFiles(options.dotOutputDir);
+ }
+
+ if (options.inverse) {
+ return analyzeInverseDeps(config);
} else {
- return analyzeDeps(dependencyFinder);
+ return analyzeDeps(config);
}
}
- private void buildArchive(DependencyFinder dependencyFinder)
- throws BadArgs, IOException
- {
- // If -genmoduleinfo is specified, the input arguments must be JAR files
- // Treat them as automatic modules for analysis
- List<Path> jarfiles = options.genModuleInfo != null
- ? classes.stream().map(Paths::get)
- .collect(Collectors.toList())
- : Collections.emptyList();
- // Set module paths
- this.modulePaths = new ModulePaths(options.upgradeModulePath, options.modulePath, jarfiles);
+ private JdepsConfiguration buildConfig() throws IOException {
+ JdepsConfiguration.Builder builder =
+ new JdepsConfiguration.Builder(options.systemModulePath);
- // add modules to dependency finder for analysis
- Map<String, Module> modules = modulePaths.getModules();
- modules.values().stream()
- .forEach(dependencyFinder::addModule);
+ builder.upgradeModulePath(options.upgradeModulePath)
+ .appModulePath(options.modulePath)
+ .addmods(options.addmods);
- // If -m option is set, add the specified module and its transitive dependences
- // to the root set
- if (options.rootModule != null) {
- modulePaths.dependences(options.rootModule)
- .forEach(dependencyFinder::addRoot);
+ if (options.checkModuleDeps != null) {
+ // check all system modules in the image
+ builder.allModules();
}
- // check if any module specified in -requires is missing
- Optional<String> req = options.requires.stream()
- .filter(mn -> !modules.containsKey(mn))
- .findFirst();
- if (req.isPresent()) {
- throw new BadArgs("err.module.not.found", req.get());
- }
+ if (options.classpath != null)
+ builder.addClassPath(options.classpath);
- // classpath
- for (Path p : getClassPaths(options.classpath)) {
+ // build the root set of archives to be analyzed
+ for (String s : inputArgs) {
+ Path p = Paths.get(s);
if (Files.exists(p)) {
- dependencyFinder.addClassPathArchive(p);
+ builder.addRoot(p);
}
}
- // if -genmoduleinfo is not set, the input arguments are considered as
- // unnamed module. Add them to the root set
- if (options.genModuleInfo == null) {
- // add root set
- for (String s : classes) {
- Path p = Paths.get(s);
- if (Files.exists(p)) {
- // add to the initial root set
- dependencyFinder.addRoot(p);
- } else {
- if (isValidClassName(s)) {
- dependencyFinder.addClassName(s);
- } else {
- warning("warn.invalid.arg", s);
- }
- }
- }
- }
+ return builder.build();
}
- private boolean analyzeDeps(DependencyFinder dependencyFinder) throws IOException {
- JdepsFilter filter = dependencyFilter();
-
- // parse classfiles and find all dependencies
- findDependencies(dependencyFinder, filter, options.apiOnly);
-
- // analyze the dependencies collected
- Analyzer analyzer = new Analyzer(options.verbose, filter);
- analyzer.run(dependencyFinder.archives());
-
+ private boolean analyzeDeps(JdepsConfiguration config) throws IOException {
// output result
final JdepsWriter writer;
if (options.dotOutputDir != null) {
- Path dir = Paths.get(options.dotOutputDir);
- Files.createDirectories(dir);
- writer = new DotFileWriter(dir, options.verbose,
+ writer = new DotFileWriter(options.dotOutputDir,
+ options.verbose,
options.showProfile,
options.showModule,
options.showLabel);
} else {
- writer = new SimpleWriter(log, options.verbose,
+ writer = new SimpleWriter(log,
+ options.verbose,
options.showProfile,
options.showModule);
}
- // Targets for reporting - include the root sets and other analyzed archives
- final List<Archive> targets;
- if (options.rootModule == null) {
- // no module as the root set
- targets = dependencyFinder.archives()
- .filter(filter::accept)
- .filter(a -> !a.getModule().isNamed())
- .collect(Collectors.toList());
- } else {
- // named modules in topological order
- Stream<Module> modules = dependencyFinder.archives()
- .filter(a -> a.getModule().isNamed())
- .map(Archive::getModule);
- Graph<Module> graph = ModuleAnalyzer.graph(modulePaths, modules.toArray(Module[]::new));
- // then add unnamed module
- targets = graph.orderedNodes()
- .filter(filter::accept)
- .collect(Collectors.toList());
+ // analyze the dependencies
+ DepsAnalyzer analyzer = new DepsAnalyzer(config,
+ dependencyFilter(config),
+ writer,
+ options.verbose,
+ options.apiOnly);
+
+ boolean ok = analyzer.run(options.compileTimeView, options.depth);
+
+ // print skipped entries, if any
+ analyzer.archives()
+ .forEach(archive -> archive.reader()
+ .skippedEntries().stream()
+ .forEach(name -> warning("warn.skipped.entry",
+ name, archive.getPathName())));
- // in case any reference not found
- dependencyFinder.archives()
- .filter(a -> !a.getModule().isNamed())
- .forEach(targets::add);
- }
+ if (options.findJDKInternals && !options.nowarning) {
+ Map<String, String> jdkInternals = analyzer.dependences()
+ .collect(Collectors.toMap(Function.identity(), this::replacementFor));
+
+ if (!jdkInternals.isEmpty()) {
+ log.println();
+ warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
- writer.generateOutput(targets, analyzer);
- if (options.findJDKInternals && !options.nowarning) {
- showReplacements(targets, analyzer);
+ if (jdkInternals.values().stream().anyMatch(repl -> repl != null)) {
+ log.println();
+ log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement");
+ log.format("%-40s %s%n", "----------------", "---------------------");
+ jdkInternals.entrySet().stream()
+ .filter(e -> e.getValue() != null)
+ .sorted(Map.Entry.comparingByKey())
+ .forEach(e -> log.format("%-40s %s%n", e.getKey(), e.getValue()));
+ }
+ }
+
}
- return true;
+ return ok;
}
- private JdepsFilter dependencyFilter() {
- // Filter specified by -filter, -package, -regex, and -module options
- JdepsFilter.Builder builder = new JdepsFilter.Builder();
+ private boolean analyzeInverseDeps(JdepsConfiguration config) throws IOException {
+ JdepsWriter writer = new SimpleWriter(log,
+ options.verbose,
+ options.showProfile,
+ options.showModule);
+
+ InverseDepsAnalyzer analyzer = new InverseDepsAnalyzer(config,
+ dependencyFilter(config),
+ writer,
+ options.verbose,
+ options.apiOnly);
+ boolean ok = analyzer.run();
+
+ log.println();
+ if (!options.requires.isEmpty())
+ log.format("Inverse transitive dependences on %s%n", options.requires);
+ else
+ log.format("Inverse transitive dependences matching %s%n",
+ options.regex != null
+ ? options.regex.toString()
+ : "packages " + options.packageNames);
+
+ analyzer.inverseDependences().stream()
+ .sorted(Comparator.comparing(this::sortPath))
+ .forEach(path -> log.println(path.stream()
+ .map(Archive::getName)
+ .collect(Collectors.joining(" <- "))));
+ return ok;
+ }
+
+ private String sortPath(Deque<Archive> path) {
+ return path.peekFirst().getName();
+ }
- // Exclude JDK modules from analysis and reporting if -m specified.
- modulePaths.getModules().values().stream()
- .filter(m -> m.isJDK())
- .map(Module::name)
- .forEach(options.excludes::add);
+ private boolean genModuleInfo(JdepsConfiguration config) throws IOException {
+ ModuleInfoBuilder builder
+ = new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo);
+ boolean ok = builder.run();
+
+ builder.modules().forEach(module -> {
+ if (module.packages().contains("")) {
+ reportError("ERROR: %s contains unnamed package. " +
+ "module-info.java not generated%n", module.getPathName());
+ }
+ });
+
+ if (!ok && !options.nowarning) {
+ log.println("Missing dependencies");
+ builder.visitMissingDeps(
+ new Analyzer.Visitor() {
+ @Override
+ public void visitDependence(String origin, Archive originArchive,
+ String target, Archive targetArchive) {
+ if (targetArchive == NOT_FOUND)
+ log.format(" %-50s -> %-50s %s%n",
+ origin, target, targetArchive.getName());
+ }
+ });
+
+ log.println("ERROR: missing dependencies (check \"requires NOT_FOUND;\")");
+ }
+ return ok;
+ }
+
+ /**
+ * Returns a filter used during dependency analysis
+ */
+ private JdepsFilter dependencyFilter(JdepsConfiguration config) {
+ // Filter specified by -filter, -package, -regex, and -requires options
+ JdepsFilter.Builder builder = new JdepsFilter.Builder();
// source filters
builder.includePattern(options.includePattern);
- builder.includeModules(options.includes);
- builder.excludeModules(options.excludes);
+ builder.includeSystemModules(options.includeSystemModulePattern);
builder.filter(options.filterSamePackage, options.filterSameArchive);
builder.findJDKInternals(options.findJDKInternals);
- // -module
+ // -requires
if (!options.requires.isEmpty()) {
- Map<String, Module> modules = modulePaths.getModules();
- builder.packages(options.requires.stream()
- .map(modules::get)
- .flatMap(m -> m.packages().stream())
- .collect(Collectors.toSet()));
+ options.requires.stream()
+ .forEach(mn -> {
+ Module m = config.findModule(mn).get();
+ builder.requires(mn, m.packages());
+ });
}
// -regex
if (options.regex != null)
@@ -600,60 +714,12 @@
if (options.filterRegex != null)
builder.filter(options.filterRegex);
- return builder.build();
- }
-
- private void findDependencies(DependencyFinder dependencyFinder,
- JdepsFilter filter,
- boolean apiOnly)
- throws IOException
- {
- dependencyFinder.findDependencies(filter, apiOnly, options.depth);
-
- // print skipped entries, if any
- for (Archive a : dependencyFinder.roots()) {
- for (String name : a.reader().skippedEntries()) {
- warning("warn.skipped.entry", name, a.getPathName());
- }
- }
- }
-
- private boolean genModuleInfo(DependencyFinder dependencyFinder) throws IOException {
- ModuleInfoBuilder builder = new ModuleInfoBuilder(modulePaths, dependencyFinder);
- boolean result = builder.run(options.verbose, options.nowarning);
- builder.build(Paths.get(options.genModuleInfo));
- return result;
- }
+ // check if system module is set
+ config.rootModules().stream()
+ .map(Module::name)
+ .forEach(builder::includeIfSystemModule);
- private boolean analyzeModules(DependencyFinder dependencyFinder)
- throws IOException
- {
- ModuleAnalyzer analyzer = new ModuleAnalyzer(modulePaths,
- dependencyFinder,
- options.rootModule);
- if (options.checkModuleDeps) {
- return analyzer.run();
- }
- if (options.dotOutputDir != null && options.verbose == SUMMARY) {
- Path dir = Paths.get(options.dotOutputDir);
- Files.createDirectories(dir);
- analyzer.genDotFile(dir);
- return true;
- }
- return false;
- }
-
- private boolean isValidClassName(String name) {
- if (!Character.isJavaIdentifierStart(name.charAt(0))) {
- return false;
- }
- for (int i=1; i < name.length(); i++) {
- char c = name.charAt(i);
- if (c != '.' && !Character.isJavaIdentifierPart(c)) {
- return false;
- }
- }
- return true;
+ return builder.build();
}
public void handleOptions(String[] args) throws BadArgs {
@@ -684,7 +750,7 @@
if (name.charAt(0) == '-') {
throw new BadArgs("err.option.after.class", name).showUsage(true);
}
- classes.add(name);
+ inputArgs.add(name);
}
}
}
@@ -703,7 +769,7 @@
log.println(getMessage("error.prefix") + " " + getMessage(key, args));
}
- private void warning(String key, Object... args) {
+ void warning(String key, Object... args) {
log.println(getMessage("warn.prefix") + " " + getMessage(key, args));
}
@@ -749,7 +815,7 @@
boolean version;
boolean fullVersion;
boolean showProfile;
- boolean showModule;
+ boolean showModule = true;
boolean showSummary;
boolean apiOnly;
boolean showLabel;
@@ -761,22 +827,23 @@
boolean filterSamePackage = true;
boolean filterSameArchive = false;
Pattern filterRegex;
- String dotOutputDir;
- String genModuleInfo;
- String classpath = "";
+ Path dotOutputDir;
+ Path genModuleInfo;
+ String classpath;
int depth = 1;
Set<String> requires = new HashSet<>();
Set<String> packageNames = new HashSet<>();
Pattern regex; // apply to the dependences
- Pattern includePattern; // apply to classes
+ Pattern includePattern;
+ Pattern includeSystemModulePattern;
+ boolean inverse = false;
boolean compileTimeView = false;
- boolean checkModuleDeps = false;
+ Set<String> checkModuleDeps;
+ String systemModulePath = System.getProperty("java.home");
String upgradeModulePath;
String modulePath;
String rootModule;
- // modules to be included or excluded
- Set<String> includes = new HashSet<>();
- Set<String> excludes = new HashSet<>();
+ Set<String> addmods = new HashSet<>();
boolean hasFilter() {
return numFilters() > 0;
@@ -789,11 +856,8 @@
if (packageNames.size() > 0) count++;
return count;
}
+ }
- boolean isRootModule() {
- return rootModule != null;
- }
- }
private static class ResourceBundleHelper {
static final ResourceBundle versionRB;
static final ResourceBundle bundle;
@@ -819,35 +883,6 @@
}
}
- /*
- * Returns the list of Archive specified in cpaths and not included
- * initialArchives
- */
- private List<Path> getClassPaths(String cpaths) throws IOException
- {
- if (cpaths.isEmpty()) {
- return Collections.emptyList();
- }
- List<Path> paths = new ArrayList<>();
- for (String p : cpaths.split(File.pathSeparator)) {
- if (p.length() > 0) {
- // wildcard to parse all JAR files e.g. -classpath dir/*
- int i = p.lastIndexOf(".*");
- if (i > 0) {
- Path dir = Paths.get(p.substring(0, i));
- try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.jar")) {
- for (Path entry : stream) {
- paths.add(entry);
- }
- }
- } else {
- paths.add(Paths.get(p));
- }
- }
- }
- return paths;
- }
-
/**
* Returns the recommended replacement API for the given classname;
* or return null if replacement API is not known.
@@ -865,32 +900,5 @@
}
}
return value;
- };
-
- private void showReplacements(List<Archive> archives, Analyzer analyzer) {
- Map<String,String> jdkinternals = new TreeMap<>();
- boolean useInternals = false;
- for (Archive source : archives) {
- useInternals = useInternals || analyzer.hasDependences(source);
- for (String cn : analyzer.dependences(source)) {
- String repl = replacementFor(cn);
- if (repl != null) {
- jdkinternals.putIfAbsent(cn, repl);
- }
- }
- }
- if (useInternals) {
- log.println();
- warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
- }
- if (!jdkinternals.isEmpty()) {
- log.println();
- log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement");
- log.format("%-40s %s%n", "----------------", "---------------------");
- for (Map.Entry<String,String> e : jdkinternals.entrySet()) {
- log.format("%-40s %s%n", e.getKey(), e.getValue());
- }
- }
}
-
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java Thu May 19 19:47:04 2016 +0000
@@ -24,23 +24,33 @@
*/
package com.sun.tools.jdeps;
+import static com.sun.tools.jdeps.Analyzer.Type.*;
+
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor.Requires;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
-import static com.sun.tools.jdeps.Analyzer.Type.*;
+public abstract class JdepsWriter {
+ public static JdepsWriter newDotWriter(Path outputdir, Analyzer.Type type) {
+ return new DotFileWriter(outputdir, type, false, true, false);
+ }
-public abstract class JdepsWriter {
+ public static JdepsWriter newSimpleWriter(PrintWriter writer, Analyzer.Type type) {
+ return new SimpleWriter(writer, type, false, true);
+ }
+
final Analyzer.Type type;
final boolean showProfile;
final boolean showModule;
- JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
+ private JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
this.type = type;
this.showProfile = showProfile;
this.showModule = showModule;
@@ -48,7 +58,7 @@
abstract void generateOutput(Collection<Archive> archives, Analyzer analyzer) throws IOException;
- public static class DotFileWriter extends JdepsWriter {
+ static class DotFileWriter extends JdepsWriter {
final boolean showLabel;
final Path outputDir;
DotFileWriter(Path dir, Analyzer.Type type,
@@ -62,8 +72,10 @@
void generateOutput(Collection<Archive> archives, Analyzer analyzer)
throws IOException
{
+ Files.createDirectories(outputDir);
+
// output individual .dot file for each archive
- if (type != SUMMARY) {
+ if (type != SUMMARY && type != MODULE) {
archives.stream()
.filter(analyzer::hasDependences)
.forEach(archive -> {
@@ -85,13 +97,13 @@
{
// If verbose mode (-v or -verbose option),
// the summary.dot file shows package-level dependencies.
- Analyzer.Type summaryType =
- (type == PACKAGE || type == SUMMARY) ? SUMMARY : PACKAGE;
+ boolean isSummary = type == PACKAGE || type == SUMMARY || type == MODULE;
+ Analyzer.Type summaryType = isSummary ? SUMMARY : PACKAGE;
Path summary = outputDir.resolve("summary.dot");
try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
for (Archive archive : archives) {
- if (type == PACKAGE || type == SUMMARY) {
+ if (isSummary) {
if (showLabel) {
// build labels listing package-level dependencies
analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
@@ -208,19 +220,22 @@
void generateOutput(Collection<Archive> archives, Analyzer analyzer) {
RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
- for (Archive archive : archives) {
- // print summary
- if (showModule && archive.getModule().isNamed()) {
- summaryFormatter.showModuleRequires(archive.getModule());
- } else {
+ archives.stream()
+ .filter(analyzer::hasDependences)
+ .sorted(Comparator.comparing(Archive::getName))
+ .forEach(archive -> {
+ if (showModule && archive.getModule().isNamed() && type != SUMMARY) {
+ // print module-info except -summary
+ summaryFormatter.printModuleDescriptor(archive.getModule());
+ }
+ // print summary
analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
- }
- if (analyzer.hasDependences(archive) && type != SUMMARY) {
- // print the class-level or package-level dependences
- analyzer.visitDependences(archive, depFormatter);
- }
- }
+ if (analyzer.hasDependences(archive) && type != SUMMARY) {
+ // print the class-level or package-level dependences
+ analyzer.visitDependences(archive, depFormatter);
+ }
+ });
}
class RawOutputFormatter implements Analyzer.Visitor {
@@ -269,20 +284,16 @@
writer.format("%n");
}
- public void showModuleRequires(Module module) {
+ public void printModuleDescriptor(Module module) {
if (!module.isNamed())
return;
- writer.format("module %s", module.name());
- if (module.isAutomatic())
- writer.format(" (automatic)");
- writer.println();
- module.requires().keySet()
+ writer.format("%s%s%n", module.name(), module.isAutomatic() ? " automatic" : "");
+ writer.format(" [%s]%n", module.location());
+ module.descriptor().requires()
.stream()
- .sorted()
- .forEach(req -> writer.format(" requires %s%s%n",
- module.requires.get(req) ? "public " : "",
- req));
+ .sorted(Comparator.comparing(Requires::name))
+ .forEach(req -> writer.format(" requires %s%n", req));
}
}
}
@@ -307,7 +318,7 @@
}
// exported API
- boolean jdkunsupported = Module.isJDKUnsupported(module, pn);
+ boolean jdkunsupported = Module.JDK_UNSUPPORTED.equals(module.name());
if (module.isExported(pn) && !jdkunsupported) {
return showProfileOrModule(module);
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java Thu May 19 19:47:04 2016 +0000
@@ -25,67 +25,56 @@
package com.sun.tools.jdeps;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.UncheckedIOException;
import java.lang.module.ModuleDescriptor;
import java.net.URI;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.stream.Collectors;
/**
- * JDeps internal representation of module for dependency analysis.
+ * Jdeps internal representation of module for dependency analysis.
*/
class Module extends Archive {
- static final boolean traceOn = Boolean.getBoolean("jdeps.debug");
+ static final Module UNNAMED_MODULE = new UnnamedModule();
+ static final String JDK_UNSUPPORTED = "jdk.unsupported";
+
+ static final boolean DEBUG = Boolean.getBoolean("jdeps.debug");
static void trace(String fmt, Object... args) {
+ trace(DEBUG, fmt, args);
+ }
+
+ static void trace(boolean traceOn, String fmt, Object... args) {
if (traceOn) {
System.err.format(fmt, args);
}
}
- /*
- * Returns true if the given package name is JDK critical internal API
- * in jdk.unsupported module
- */
- static boolean isJDKUnsupported(Module m, String pn) {
- return JDK_UNSUPPORTED.equals(m.name()) || unsupported.contains(pn);
- };
+ private final ModuleDescriptor descriptor;
+ private final Map<String, Set<String>> exports;
+ private final boolean isSystem;
+ private final URI location;
- protected final ModuleDescriptor descriptor;
- protected final Map<String, Boolean> requires;
- protected final Map<String, Set<String>> exports;
- protected final Set<String> packages;
- protected final boolean isJDK;
- protected final URI location;
+ protected Module(String name) {
+ super(name);
+ this.descriptor = null;
+ this.location = null;
+ this.exports = Collections.emptyMap();
+ this.isSystem = true;
+ }
private Module(String name,
URI location,
ModuleDescriptor descriptor,
- Map<String, Boolean> requires,
Map<String, Set<String>> exports,
- Set<String> packages,
- boolean isJDK,
+ boolean isSystem,
ClassFileReader reader) {
super(name, location, reader);
this.descriptor = descriptor;
this.location = location;
- this.requires = Collections.unmodifiableMap(requires);
this.exports = Collections.unmodifiableMap(exports);
- this.packages = Collections.unmodifiableSet(packages);
- this.isJDK = isJDK;
+ this.isSystem = isSystem;
}
/**
@@ -111,31 +100,35 @@
return descriptor;
}
- public boolean isJDK() {
- return isJDK;
+ public URI location() {
+ return location;
}
- public Map<String, Boolean> requires() {
- return requires;
+ public boolean isJDK() {
+ String mn = name();
+ return isSystem &&
+ (mn.startsWith("java.") || mn.startsWith("jdk.") || mn.startsWith("javafx."));
+ }
+
+ public boolean isSystem() {
+ return isSystem;
}
public Map<String, Set<String>> exports() {
return exports;
}
- public Map<String, Set<String>> provides() {
- return descriptor.provides().entrySet().stream()
- .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().providers()));
- }
-
public Set<String> packages() {
- return packages;
+ return descriptor.packages();
}
/**
* Tests if the package of the given name is exported.
*/
public boolean isExported(String pn) {
+ if (JDK_UNSUPPORTED.equals(this.name())) {
+ return false;
+ }
return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false;
}
@@ -159,11 +152,6 @@
return isExported(pn) || exports.containsKey(pn) && exports.get(pn).contains(target);
}
- private final static String JDK_UNSUPPORTED = "jdk.unsupported";
-
- // temporary until jdk.unsupported module
- private final static List<String> unsupported = Arrays.asList("sun.misc", "sun.reflect");
-
@Override
public String toString() {
return name();
@@ -171,21 +159,19 @@
public final static class Builder {
final String name;
- final Map<String, Boolean> requires = new HashMap<>();
- final Map<String, Set<String>> exports = new HashMap<>();
- final Set<String> packages = new HashSet<>();
- final boolean isJDK;
+ final ModuleDescriptor descriptor;
+ final boolean isSystem;
ClassFileReader reader;
- ModuleDescriptor descriptor;
URI location;
- public Builder(String name) {
- this(name, false);
+ public Builder(ModuleDescriptor md) {
+ this(md, false);
}
- public Builder(String name, boolean isJDK) {
- this.name = name;
- this.isJDK = isJDK;
+ public Builder(ModuleDescriptor md, boolean isSystem) {
+ this.name = md.name();
+ this.descriptor = md;
+ this.isSystem = isSystem;
}
public Builder location(URI location) {
@@ -193,48 +179,30 @@
return this;
}
- public Builder descriptor(ModuleDescriptor md) {
- this.descriptor = md;
- return this;
- }
-
- public Builder require(String d, boolean reexport) {
- requires.put(d, reexport);
- return this;
- }
-
- public Builder packages(Set<String> pkgs) {
- packages.addAll(pkgs);
- return this;
- }
-
- public Builder export(String p, Set<String> ms) {
- Objects.requireNonNull(p);
- Objects.requireNonNull(ms);
- exports.put(p, new HashSet<>(ms));
- return this;
- }
public Builder classes(ClassFileReader reader) {
this.reader = reader;
return this;
}
public Module build() {
- if (descriptor.isAutomatic() && isJDK) {
+ if (descriptor.isAutomatic() && isSystem) {
throw new InternalError("JDK module: " + name + " can't be automatic module");
}
- return new Module(name, location, descriptor, requires, exports, packages, isJDK, reader);
+ Map<String, Set<String>> exports = new HashMap<>();
+
+ descriptor.exports().stream()
+ .forEach(exp -> exports.computeIfAbsent(exp.source(), _k -> new HashSet<>())
+ .addAll(exp.targets()));
+
+ return new Module(name, location, descriptor, exports, isSystem, reader);
}
}
- final static Module UNNAMED_MODULE = new UnnamedModule();
private static class UnnamedModule extends Module {
private UnnamedModule() {
super("unnamed", null, null,
Collections.emptyMap(),
- Collections.emptyMap(),
- Collections.emptySet(),
false, null);
}
@@ -260,10 +228,7 @@
}
private static class StrictModule extends Module {
- private static final String SERVICES_PREFIX = "META-INF/services/";
- private final Map<String, Set<String>> provides;
- private final Module module;
- private final JarFile jarfile;
+ private final ModuleDescriptor md;
/**
* Converts the given automatic module to a strict module.
@@ -272,114 +237,26 @@
* declare service providers, if specified in META-INF/services configuration file
*/
private StrictModule(Module m, Map<String, Boolean> requires) {
- super(m.name(), m.location, m.descriptor, requires, m.exports, m.packages, m.isJDK, m.reader());
- this.module = m;
- try {
- this.jarfile = new JarFile(m.path().toFile(), false);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- this.provides = providers(jarfile);
+ super(m.name(), m.location, m.descriptor, m.exports, m.isSystem, m.reader());
+
+ ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(m.name());
+ requires.keySet().forEach(mn -> {
+ if (requires.get(mn).equals(Boolean.TRUE)) {
+ builder.requires(ModuleDescriptor.Requires.Modifier.PUBLIC, mn);
+ } else {
+ builder.requires(mn);
+ }
+ });
+ m.descriptor.exports().forEach(e -> builder.exports(e));
+ m.descriptor.uses().forEach(s -> builder.uses(s));
+ m.descriptor.provides().values().forEach(p -> builder.provides(p));
+ builder.conceals(m.descriptor.conceals());
+ this.md = builder.build();
}
@Override
- public Map<String, Set<String>> provides() {
- return provides;
- }
-
- private Map<String, Set<String>> providers(JarFile jf) {
- Map<String, Set<String>> provides = new HashMap<>();
- // map names of service configuration files to service names
- Set<String> serviceNames = jf.stream()
- .map(e -> e.getName())
- .filter(e -> e.startsWith(SERVICES_PREFIX))
- .distinct()
- .map(this::toServiceName)
- .filter(Optional::isPresent)
- .map(Optional::get)
- .collect(Collectors.toSet());
-
- // parse each service configuration file
- for (String sn : serviceNames) {
- JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn);
- Set<String> providerClasses = new HashSet<>();
- try (InputStream in = jf.getInputStream(entry)) {
- BufferedReader reader
- = new BufferedReader(new InputStreamReader(in, "UTF-8"));
- String cn;
- while ((cn = nextLine(reader)) != null) {
- if (isJavaIdentifier(cn)) {
- providerClasses.add(cn);
- }
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- if (!providerClasses.isEmpty())
- provides.put(sn, providerClasses);
- }
-
- return provides;
- }
-
- /**
- * Returns a container with the service type corresponding to the name of
- * a services configuration file.
- *
- * For example, if called with "META-INF/services/p.S" then this method
- * returns a container with the value "p.S".
- */
- private Optional<String> toServiceName(String cf) {
- assert cf.startsWith(SERVICES_PREFIX);
- int index = cf.lastIndexOf("/") + 1;
- if (index < cf.length()) {
- String prefix = cf.substring(0, index);
- if (prefix.equals(SERVICES_PREFIX)) {
- String sn = cf.substring(index);
- if (isJavaIdentifier(sn))
- return Optional.of(sn);
- }
- }
- return Optional.empty();
- }
-
- /**
- * Reads the next line from the given reader and trims it of comments and
- * leading/trailing white space.
- *
- * Returns null if the reader is at EOF.
- */
- private String nextLine(BufferedReader reader) throws IOException {
- String ln = reader.readLine();
- if (ln != null) {
- int ci = ln.indexOf('#');
- if (ci >= 0)
- ln = ln.substring(0, ci);
- ln = ln.trim();
- }
- return ln;
- }
-
- /**
- * Returns {@code true} if the given identifier is a legal Java identifier.
- */
- private static boolean isJavaIdentifier(String id) {
- int n = id.length();
- if (n == 0)
- return false;
- if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
- return false;
- int cp = id.codePointAt(0);
- int i = Character.charCount(cp);
- for (; i < n; i += Character.charCount(cp)) {
- cp = id.codePointAt(i);
- if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
- return false;
- }
- if (cp == '.')
- return false;
-
- return true;
+ public ModuleDescriptor descriptor() {
+ return md;
}
}
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java Thu May 19 19:47:04 2016 +0000
@@ -24,277 +24,364 @@
*/
package com.sun.tools.jdeps;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.UncheckedIOException;
-
+import static com.sun.tools.jdeps.Graph.*;
+import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER;
+import static com.sun.tools.jdeps.Module.*;
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+import static java.util.stream.Collectors.*;
-import java.lang.module.Configuration;
+import com.sun.tools.classfile.Dependency;
+import com.sun.tools.jdeps.JdepsTask.BadArgs;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleFinder;
-import java.lang.module.ModuleReference;
-import java.lang.module.ResolvedModule;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
-import java.util.function.Consumer;
import java.util.function.Function;
-import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static com.sun.tools.jdeps.Module.*;
-import static com.sun.tools.jdeps.ModulePaths.SystemModulePath.JAVA_BASE;
-
/**
* Analyze module dependences and compare with module descriptor.
* Also identify any qualified exports not used by the target module.
*/
-class ModuleAnalyzer {
- private final ModulePaths modulePaths;
+public class ModuleAnalyzer {
+ private static final String JAVA_BASE = "java.base";
+
+ private final JdepsConfiguration configuration;
+ private final PrintWriter log;
+
private final DependencyFinder dependencyFinder;
- private final Module root;
- private final Set<Module> modules;
- private final Set<String> requiresPublic = new HashSet<>();
- private final Set<String> requires = new HashSet<>();
- private final Set<Module> exportTargets = new HashSet<>();
- private final JdepsFilter filter;
- private Graph<Module> graph;
- ModuleAnalyzer(ModulePaths modulePaths, DependencyFinder finder,
- String moduleName) {
- this.modulePaths = modulePaths;
- this.dependencyFinder = finder;
- this.root = modulePaths.getModules().get(moduleName);
- this.modules = modulePaths.dependences(moduleName);
+ private final Map<Module, ModuleDeps> modules;
+
+ public ModuleAnalyzer(JdepsConfiguration config,
+ PrintWriter log) {
+ this(config, log, Collections.emptySet());
+ }
+ public ModuleAnalyzer(JdepsConfiguration config,
+ PrintWriter log,
+ Set<String> names) {
- root.exports().values().stream()
- .flatMap(Set::stream)
- .map(target -> modulePaths.getModules().get(target))
- .forEach(this.exportTargets::add);
+ if (!config.initialArchives().isEmpty()) {
+ String list = config.initialArchives().stream()
+ .map(Archive::getPathName).collect(joining(" "));
+ throw new JdepsTask.UncheckedBadArgs(new BadArgs("err.invalid.module.option",
+ list, "-check"));
+ }
+
+ this.configuration = config;
+ this.log = log;
- this.filter = new JdepsFilter.Builder().filter(true, true).build();
+ this.dependencyFinder = new DependencyFinder(config, DEFAULT_FILTER);
+ if (names.isEmpty()) {
+ this.modules = configuration.rootModules().stream()
+ .collect(toMap(Function.identity(), ModuleDeps::new));
+ } else {
+ this.modules = names.stream()
+ .map(configuration::findModule)
+ .flatMap(Optional::stream)
+ .collect(toMap(Function.identity(), ModuleDeps::new));
+ }
}
- /**
- * Returns a graph of transitive closure of the given modules.
- *
- * This method does not add the implicit read edges and is intended to
- * get all transitive closures in (reverse) topological sort.
- */
- public static Graph<Module> graph(ModulePaths modulePaths, Module... modules) {
- Graph.Builder<Module> gb = new Graph.Builder<>();
- for (Module module : modules) {
- module.descriptor().requires().stream()
- .map(ModuleDescriptor.Requires::name)
- .map(mn -> modulePaths.getModules().get(mn))
- .forEach(m -> {
- gb.addNode(m);
- gb.addEdge(module, m);
- });
- }
- return gb.build();
- }
+ public boolean run() throws IOException {
+ try {
+ // compute "requires public" dependences
+ modules.values().forEach(ModuleDeps::computeRequiresPublic);
- /**
- * Do the analysis
- */
- public boolean run() {
- try {
- computeRequiresPublic();
- computeRequires();
- // apply transitive reduction and reports recommended requires.
- analyzeDeps();
- // detect any qualiifed exports not used by the target module
- checkQualifiedExports();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
+ modules.values().forEach(md -> {
+ // compute "requires" dependences
+ md.computeRequires();
+ // apply transitive reduction and reports recommended requires.
+ md.analyzeDeps();
+ });
+ } finally {
+ dependencyFinder.shutdown();
}
return true;
}
- /**
- * Compute 'requires public' dependences by analyzing API dependencies
- */
- private void computeRequiresPublic() throws IOException {
- JdepsFilter.Builder builder = new JdepsFilter.Builder();
- // only analyze exported API
- root.descriptor.exports().stream()
- .filter(exp -> !exp.isQualified())
- .map(ModuleDescriptor.Exports::source)
- .forEach(builder::includePackage);
+ class ModuleDeps {
+ final Module root;
+ Set<Module> requiresPublic;
+ Set<Module> requires;
+ Map<String, Set<String>> unusedQualifiedExports;
+
+ ModuleDeps(Module root) {
+ this.root = root;
+ }
+
+ /**
+ * Compute 'requires public' dependences by analyzing API dependencies
+ */
+ private void computeRequiresPublic() {
+ // record requires public
+ this.requiresPublic = computeRequires(true)
+ .filter(m -> !m.name().equals(JAVA_BASE))
+ .collect(toSet());
+
+ trace("requires public: %s%n", requiresPublic);
+ }
+
+ private void computeRequires() {
+ this.requires = computeRequires(false).collect(toSet());
+ trace("requires: %s%n", requires);
+ }
+
+ private Stream<Module> computeRequires(boolean apionly) {
+ // analyze all classes
+
+ if (apionly) {
+ dependencyFinder.parseExportedAPIs(Stream.of(root));
+ } else {
+ dependencyFinder.parse(Stream.of(root));
+ }
+
+ // find the modules of all the dependencies found
+ return dependencyFinder.getDependences(root)
+ .map(Archive::getModule);
+ }
+
+ ModuleDescriptor descriptor() {
+ return descriptor(requiresPublic, requires);
+ }
+
+ private ModuleDescriptor descriptor(Set<Module> requiresPublic,
+ Set<Module> requires) {
+
+ ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(root.name());
+
+ if (!root.name().equals(JAVA_BASE))
+ builder.requires(MANDATED, JAVA_BASE);
+
+ requiresPublic.stream()
+ .filter(m -> !m.name().equals(JAVA_BASE))
+ .map(Module::name)
+ .forEach(mn -> builder.requires(PUBLIC, mn));
- JdepsFilter filter = builder.filter(true, true).build();
+ requires.stream()
+ .filter(m -> !requiresPublic.contains(m))
+ .filter(m -> !m.name().equals(JAVA_BASE))
+ .map(Module::name)
+ .forEach(mn -> builder.requires(mn));
+
+ return builder.build();
+ }
+
+ ModuleDescriptor reduced() {
+ Graph.Builder<Module> bd = new Graph.Builder<>();
+ requiresPublic.stream()
+ .forEach(m -> {
+ bd.addNode(m);
+ bd.addEdge(root, m);
+ });
+
+ // requires public graph
+ Graph<Module> rbg = bd.build().reduce();
+
+ // transitive reduction
+ Graph<Module> newGraph = buildGraph(requires).reduce(rbg);
+ if (DEBUG) {
+ System.err.println("after transitive reduction: ");
+ newGraph.printGraph(log);
+ }
+
+ return descriptor(requiresPublic, newGraph.adjacentNodes(root));
+ }
+
- // analyze dependences for exported packages
- dependencyFinder.findDependencies(filter, true /* api only */, 1);
- Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
- analyzer.run(modules);
+ /**
+ * Apply transitive reduction on the resulting graph and reports
+ * recommended requires.
+ */
+ private void analyzeDeps() {
+ Graph.Builder<Module> builder = new Graph.Builder<>();
+ requiresPublic.stream()
+ .forEach(m -> {
+ builder.addNode(m);
+ builder.addEdge(root, m);
+ });
+
+ // requires public graph
+ Graph<Module> rbg = buildGraph(requiresPublic).reduce();
+
+ // transitive reduction
+ Graph<Module> newGraph = buildGraph(requires).reduce(builder.build().reduce());
+ if (DEBUG) {
+ System.err.println("after transitive reduction: ");
+ newGraph.printGraph(log);
+ }
+
+ printModuleDescriptor(log, root);
+
+ ModuleDescriptor analyzedDescriptor = descriptor();
+ if (!matches(root.descriptor(), analyzedDescriptor)) {
+ log.format(" [Suggested module descriptor for %s]%n", root.name());
+ analyzedDescriptor.requires()
+ .stream()
+ .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
+ .forEach(req -> log.format(" requires %s;%n", req));
+ }
- // record requires public
- analyzer.requires(root)
- .filter(m -> m != JAVA_BASE && m != root)
- .map(Archive::getName)
- .forEach(requiresPublic::add);
- trace("requires public: %s%n", requiresPublic);
- }
+ ModuleDescriptor reduced = reduced();
+ if (!matches(root.descriptor(), reduced)) {
+ log.format(" [Transitive reduced graph for %s]%n", root.name());
+ reduced.requires()
+ .stream()
+ .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
+ .forEach(req -> log.format(" requires %s;%n", req));
+ }
+
+ checkQualifiedExports();
+ log.println();
+ }
+
+ private void checkQualifiedExports() {
+ // detect any qualified exports not used by the target module
+ unusedQualifiedExports = unusedQualifiedExports();
+ if (!unusedQualifiedExports.isEmpty())
+ log.format(" [Unused qualified exports in %s]%n", root.name());
+
+ unusedQualifiedExports.keySet().stream()
+ .sorted()
+ .forEach(pn -> log.format(" exports %s to %s%n", pn,
+ unusedQualifiedExports.get(pn).stream()
+ .sorted()
+ .collect(joining(","))));
+ }
- private void computeRequires() throws IOException {
- // add the exportTargets of the qualified exports to the root set
- exportTargets.stream()
- .peek(target -> trace("add root: %s%n", target))
- .forEach(dependencyFinder::addRoot);
+ private void printModuleDescriptor(PrintWriter out, Module module) {
+ ModuleDescriptor descriptor = module.descriptor();
+ out.format("%s (%s)%n", descriptor.name(), module.location());
+
+ if (descriptor.name().equals(JAVA_BASE))
+ return;
+
+ out.println(" [Module descriptor]");
+ descriptor.requires()
+ .stream()
+ .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
+ .forEach(req -> out.format(" requires %s;%n", req));
+ }
+
+
+ /**
+ * Returns a graph of modules required by the specified module.
+ *
+ * Requires public edges of the dependences are added to the graph.
+ */
+ private Graph<Module> buildGraph(Set<Module> deps) {
+ Graph.Builder<Module> builder = new Graph.Builder<>();
+ builder.addNode(root);
+ Set<Module> visited = new HashSet<>();
+ visited.add(root);
+ Deque<Module> deque = new LinkedList<>();
+ deps.stream()
+ .forEach(m -> {
+ deque.add(m);
+ builder.addEdge(root, m);
+ });
- // analyze all classes
- dependencyFinder.findDependencies(filter, false /* all classes */, 1);
- Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
- analyzer.run(modules);
+ // read requires public from ModuleDescription
+ Module source;
+ while ((source = deque.poll()) != null) {
+ if (visited.contains(source))
+ continue;
+
+ visited.add(source);
+ builder.addNode(source);
+ Module from = source;
+ source.descriptor().requires().stream()
+ .filter(req -> req.modifiers().contains(PUBLIC))
+ .map(ModuleDescriptor.Requires::name)
+ .map(configuration::findModule)
+ .flatMap(Optional::stream)
+ .forEach(m -> {
+ deque.add(m);
+ builder.addEdge(from, m);
+ });
+ }
+ return builder.build();
+ }
+
+ /**
+ * Detects any qualified exports not used by the target module.
+ */
+ private Map<String, Set<String>> unusedQualifiedExports() {
+ Map<String, Set<String>> unused = new HashMap<>();
- // record requires
- analyzer.requires(root)
- .filter(m -> m != JAVA_BASE && m != root)
- .map(Archive::getName)
- .forEach(requires::add);
+ // build the qualified exports map
+ Map<String, Set<String>> qualifiedExports =
+ root.exports().entrySet().stream()
+ .filter(e -> !e.getValue().isEmpty())
+ .map(Map.Entry::getKey)
+ .collect(toMap(Function.identity(), _k -> new HashSet<>()));
+
+ Set<Module> mods = new HashSet<>();
+ root.exports().values()
+ .stream()
+ .flatMap(Set::stream)
+ .forEach(target -> configuration.findModule(target)
+ .ifPresentOrElse(mods::add,
+ () -> log.format("Warning: %s not found%n", target))
+ );
+
+ // parse all target modules
+ dependencyFinder.parse(mods.stream());
- this.graph = buildGraph(analyzer, root);
- if (traceOn) {
- trace("dependences: %s%n", graph.nodes());
- graph.printGraph(System.out);
+ // adds to the qualified exports map if a module references it
+ mods.stream().forEach(m ->
+ m.getDependencies()
+ .map(Dependency.Location::getPackageName)
+ .filter(qualifiedExports::containsKey)
+ .forEach(pn -> qualifiedExports.get(pn).add(m.name())));
+
+ // compare with the exports from ModuleDescriptor
+ Set<String> staleQualifiedExports =
+ qualifiedExports.keySet().stream()
+ .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn)))
+ .collect(toSet());
+
+ if (!staleQualifiedExports.isEmpty()) {
+ for (String pn : staleQualifiedExports) {
+ Set<String> targets = new HashSet<>(root.exports().get(pn));
+ targets.removeAll(qualifiedExports.get(pn));
+ unused.put(pn, targets);
+ }
+ }
+ return unused;
}
}
- /**
- * Apply transitive reduction on the resulting graph and reports
- * recommended requires.
- */
- private void analyzeDeps() {
- String moduleName = root.name();
-
- Graph.Builder<String> builder = new Graph.Builder<>();
- requiresPublic.stream()
- .forEach(mn -> {
- builder.addNode(mn);
- builder.addEdge(moduleName, mn);
- });
- // requires public graph
- Graph<String> rbg = builder.build().reduce();
-
- // convert the dependence graph from Module to name
- Set<String> nodes = this.graph.nodes().stream()
- .map(Module::name)
- .collect(Collectors.toSet());
- Map<String, Set<String>> edges = new HashMap<>();
- this.graph.edges().keySet().stream()
- .forEach(m -> {
- String mn = m.name();
- Set<String> es = edges.computeIfAbsent(mn, _k -> new HashSet<String>());
- this.graph.edges().get(m).stream()
- .map(Module::name)
- .forEach(es::add);
- });
-
- // transitive reduction
- Graph<String> newGraph = new Graph<>(nodes, edges).reduce(rbg);
- if (traceOn) {
- System.out.println("after transitive reduction");
- newGraph.printGraph(System.out);
- };
+ private boolean matches(ModuleDescriptor md, ModuleDescriptor other) {
+ // build requires public from ModuleDescriptor
+ Set<ModuleDescriptor.Requires> reqPublic = md.requires().stream()
+ .filter(req -> req.modifiers().contains(PUBLIC))
+ .collect(toSet());
+ Set<ModuleDescriptor.Requires> otherReqPublic = other.requires().stream()
+ .filter(req -> req.modifiers().contains(PUBLIC))
+ .collect(toSet());
- Set<String> reducedRequires = newGraph.adjacentNodes(moduleName);
- if (matches(root.descriptor(), requires, requiresPublic) &&
- matches(root.descriptor(), reducedRequires, requiresPublic)) {
- System.out.println("--- Analysis result: no change for " + root.name());
- } else {
- System.out.println("--- Analysis result: suggested requires for " + root.name());
- System.out.format("module %s%n", root.name());
- requires.stream()
- .sorted()
- .forEach(dn -> System.out.format(" requires %s%s;%n",
- requiresPublic.contains(dn) ? "public " : "", dn));
- if (!requires.equals(reducedRequires) && !reducedRequires.isEmpty()) {
- System.out.format("%nmodule %s (reduced)%n", root.name());
- newGraph.adjacentNodes(moduleName)
- .stream()
- .sorted()
- .forEach(dn -> System.out.format(" requires %s%s;%n",
- requiresPublic.contains(dn) ? "public " : "", dn));
- }
- System.out.println("\n--- Module descriptor");
- Graph<Module> mdGraph = graph(modulePaths, root);
- mdGraph.reverse(m -> printModuleDescriptor(System.out, m.descriptor()));
- }
- }
-
- /**
- * Detects any qualified exports not used by the target module.
- */
- private void checkQualifiedExports() throws IOException {
- Analyzer analyzer = new Analyzer(Analyzer.Type.CLASS, filter);
- analyzer.run(dependencyFinder.roots());
-
- // build the qualified exports map
- Map<String, Set<String>> qualifiedExports =
- root.exports().entrySet().stream()
- .filter(e -> !e.getValue().isEmpty())
- .map(Map.Entry::getKey)
- .collect(Collectors.toMap(Function.identity(), _k -> new HashSet<>()));
-
- // adds to the qualified exports map if a module references it
- for (Module m : exportTargets) {
- analyzer.dependences(m).stream()
- .map(this::toPackageName)
- .filter(qualifiedExports::containsKey)
- .forEach(pn -> qualifiedExports.get(pn).add(m.name()));
- }
-
- // compare with the exports from ModuleDescriptor
- Set<String> staleQualifiedExports =
- qualifiedExports.keySet().stream()
- .filter(pn -> !qualifiedExports.get(pn).equals(root.exports().get(pn)))
- .collect(Collectors.toSet());
-
- if (!staleQualifiedExports.isEmpty()) {
- System.out.println("--- Unused qualified exports in " + root.name());
- for (String pn : staleQualifiedExports) {
- Set<String> unused = new HashSet<>(root.exports().get(pn));
- unused.removeAll(qualifiedExports.get(pn));
- System.out.format(" exports %s to %s%n", pn,
- unused.stream().collect(Collectors.joining(",")));
- }
- }
- }
-
- private String toPackageName(String cn) {
- int i = cn.lastIndexOf('.');
- return i > 0 ? cn.substring(0, i) : "";
- }
-
- private boolean matches(ModuleDescriptor md, Set<String> requires, Set<String> requiresPublic) {
- Set<String> reqPublic = md.requires().stream()
- .filter(req -> req.modifiers().contains(PUBLIC))
- .map(ModuleDescriptor.Requires::name)
- .collect(Collectors.toSet());
- if (!requiresPublic.equals(reqPublic)) {
+ if (!reqPublic.equals(otherReqPublic)) {
trace("mismatch requires public: %s%n", reqPublic);
return false;
}
- // java.base is not in requires
- int javaBase = md.name().equals(JAVA_BASE.name()) ? 0 : 1;
- if (requires.size()+javaBase != md.requires().size()) {
- trace("mismatch requires: %d != %d%n", requires.size()+1, md.requires().size());
- return false;
- }
- Set<String> unused = md.requires().stream()
- .map(ModuleDescriptor.Requires::name)
- .filter(req -> !requires.contains(req) && !req.equals(JAVA_BASE.name()))
- .collect(Collectors.toSet());
+ Set<ModuleDescriptor.Requires> unused = md.requires().stream()
+ .filter(req -> !other.requires().contains(req))
+ .collect(Collectors.toSet());
+
if (!unused.isEmpty()) {
trace("mismatch requires: %s%n", unused);
return false;
@@ -302,371 +389,50 @@
return true;
}
- private void printModuleDescriptor(PrintStream out, ModuleDescriptor descriptor) {
- if (descriptor.name().equals("java.base"))
- return;
-
- out.format("module %s%n", descriptor.name());
- descriptor.requires()
- .stream()
- .sorted(Comparator.comparing(ModuleDescriptor.Requires::name))
- .forEach(req -> out.format(" requires %s;%n", req));
- }
-
/**
- * Returns a graph of modules required by the specified module.
+ * Generate dotfile from module descriptor
*
- * Requires public edges of the dependences are added to the graph.
+ * @param dir output directory
*/
- private Graph<Module> buildGraph(Analyzer analyzer, Module module) {
- Graph.Builder<Module> builder = new Graph.Builder<>();
- builder.addNode(module);
- Set<Module> visited = new HashSet<>();
- visited.add(module);
- Deque<Module> deque = new LinkedList<>();
- analyzer.requires(module)
- .map(Archive::getModule)
- .filter(m -> m != JAVA_BASE)
- .forEach(m -> {
- deque.add(m);
- builder.addEdge(module, m);
- });
-
- // read requires public from ModuleDescription
- Module source;
- while ((source = deque.poll()) != null) {
- if (visited.contains(source))
- continue;
- visited.add(source);
- builder.addNode(source);
- Module from = source;
- source.descriptor().requires().stream()
- .filter(req -> req.modifiers().contains(PUBLIC))
- .map(ModuleDescriptor.Requires::name)
- .map(req -> modulePaths.getModules().get(req))
- .filter(m -> m != JAVA_BASE)
- .forEach(m -> {
- deque.add(m);
- builder.addEdge(from, m);
- });
+ public boolean genDotFiles(Path dir) throws IOException {
+ Files.createDirectories(dir);
+ for (Module m : modules.keySet()) {
+ genDotFile(dir, m.name());
}
- return builder.build();
+ return true;
}
- static class Graph<T> {
- private final Set<T> nodes;
- private final Map<T, Set<T>> edges;
- private Graph(Set<T> nodes, Map<T, Set<T>> edges) {
- this.nodes = nodes;
- this.edges = edges;
- }
-
- public Set<T> nodes() {
- return nodes;
- }
-
- public Map<T, Set<T>> edges() {
- return edges;
- }
-
- public Set<T> adjacentNodes(T u) {
- return edges.get(u);
- }
-
- /**
- * Returns a new Graph after transitive reduction
- */
- public Graph<T> reduce() {
- Graph.Builder<T> builder = new Builder<>();
- nodes.stream()
- .forEach(u -> {
- builder.addNode(u);
- edges.get(u).stream()
- .filter(v -> !pathExists(u, v, false))
- .forEach(v -> builder.addEdge(u, v));
- });
- return builder.build();
- }
-
- /**
- * Returns a new Graph after transitive reduction. All edges in
- * the given g takes precedence over this graph.
- *
- * @throw IllegalArgumentException g must be a subgraph this graph
- */
- public Graph<T> reduce(Graph<T> g) {
- boolean subgraph = nodes.containsAll(g.nodes) && g.edges.keySet().stream()
- .allMatch(u -> adjacentNodes(u).containsAll(g.adjacentNodes(u)));
- if (!subgraph) {
- throw new IllegalArgumentException(g + " is not a subgraph of " + this);
- }
-
- Graph.Builder<T> builder = new Builder<>();
- nodes.stream()
- .forEach(u -> {
- builder.addNode(u);
- // filter the edge if there exists a path from u to v in the given g
- // or there exists another path from u to v in this graph
- edges.get(u).stream()
- .filter(v -> !g.pathExists(u, v) && !pathExists(u, v, false))
- .forEach(v -> builder.addEdge(u, v));
- });
-
- // add the overlapped edges from this graph and the given g
- g.edges().keySet().stream()
- .forEach(u -> g.adjacentNodes(u).stream()
- .filter(v -> isAdjacent(u, v))
- .forEach(v -> builder.addEdge(u, v)));
- return builder.build();
- }
-
- /**
- * Returns nodes sorted in topological order.
- */
- public Stream<T> orderedNodes() {
- TopoSorter<T> sorter = new TopoSorter<>(this);
- return sorter.result.stream();
- }
-
- /**
- * Iterates the nodes sorted in topological order and performs the
- * given action.
- */
- public void ordered(Consumer<T> action) {
- TopoSorter<T> sorter = new TopoSorter<>(this);
- sorter.ordered(action);
- }
-
- /**
- * Iterates the nodes sorted in reverse topological order and
- * performs the given action.
- */
- public void reverse(Consumer<T> action) {
- TopoSorter<T> sorter = new TopoSorter<>(this);
- sorter.reverse(action);
- }
-
- private boolean isAdjacent(T u, T v) {
- return edges.containsKey(u) && edges.get(u).contains(v);
- }
-
- private boolean pathExists(T u, T v) {
- return pathExists(u, v, true);
- }
-
- /**
- * Returns true if there exists a path from u to v in this graph.
- * If includeAdjacent is false, it returns true if there exists
- * another path from u to v of distance > 1
- */
- private boolean pathExists(T u, T v, boolean includeAdjacent) {
- if (!nodes.contains(u) || !nodes.contains(v)) {
- return false;
- }
- if (includeAdjacent && isAdjacent(u, v)) {
- return true;
- }
- Deque<T> stack = new LinkedList<>();
- Set<T> visited = new HashSet<>();
- stack.push(u);
- while (!stack.isEmpty()) {
- T node = stack.pop();
- if (node.equals(v)) {
- return true;
- }
- if (!visited.contains(node)) {
- visited.add(node);
- edges.get(node).stream()
- .filter(e -> includeAdjacent || !node.equals(u) || !e.equals(v))
- .forEach(e -> stack.push(e));
- }
- }
- assert !visited.contains(v);
- return false;
- }
-
- void printGraph(PrintStream out) {
- out.println("graph for " + nodes);
- nodes.stream()
- .forEach(u -> adjacentNodes(u).stream()
- .forEach(v -> out.format("%s -> %s%n", u, v)));
- }
-
- @Override
- public String toString() {
- return nodes.toString();
- }
-
- static class Builder<T> {
- final Set<T> nodes = new HashSet<>();
- final Map<T, Set<T>> edges = new HashMap<>();
-
- public void addNode(T node) {
- if (nodes.contains(node)) {
- return;
- }
- nodes.add(node);
- edges.computeIfAbsent(node, _e -> new HashSet<>());
- }
-
- public void addEdge(T u, T v) {
- addNode(u);
- addNode(v);
- edges.get(u).add(v);
- }
-
- public Graph<T> build() {
- return new Graph<>(nodes, edges);
- }
-
- void print(PrintStream out) {
- out.println(nodes);
- nodes.stream()
- .forEach(u -> edges.get(u).stream()
- .forEach(v -> out.format("%s -> %s%n", u, v)));
- }
- }
- }
-
- static class TopoSorter<T> {
- final Deque<T> result = new LinkedList<>();
- final Deque<T> nodes;
- final Graph<T> graph;
- TopoSorter(Graph<T> graph) {
- this.graph = graph;
- this.nodes = new LinkedList<>(graph.nodes);
- sort();
- }
-
- public void ordered(Consumer<T> action) {
- result.iterator().forEachRemaining(action);
- }
-
- public void reverse(Consumer<T> action) {
- result.descendingIterator().forEachRemaining(action);
- }
-
- private void sort() {
- Deque<T> visited = new LinkedList<>();
- Deque<T> done = new LinkedList<>();
- T node;
- while ((node = nodes.poll()) != null) {
- if (!visited.contains(node)) {
- visit(node, visited, done);
- }
- }
- }
-
- private void visit(T node, Deque<T> visited, Deque<T> done) {
- if (visited.contains(node)) {
- if (!done.contains(node)) {
- throw new IllegalArgumentException("Cyclic detected: " +
- node + " " + graph.edges().get(node));
- }
- return;
- }
- visited.add(node);
- graph.edges().get(node).stream()
- .forEach(x -> visit(x, visited, done));
- done.add(node);
- result.addLast(node);
- }
- }
-
- static class DotGraph {
- static final String ORANGE = "#e76f00";
- static final String BLUE = "#437291";
- static final String GRAY = "#dddddd";
-
- static final String REEXPORTS = "";
- static final String REQUIRES = "style=\"dashed\"";
- static final String REQUIRES_BASE = "color=\"" + GRAY + "\"";
-
- static final Set<String> javaModules = modules(name ->
- (name.startsWith("java.") && !name.equals("java.smartcardio")));
- static final Set<String> jdkModules = modules(name ->
- (name.startsWith("java.") ||
- name.startsWith("jdk.") ||
- name.startsWith("javafx.")) && !javaModules.contains(name));
-
- private static Set<String> modules(Predicate<String> predicate) {
- return ModuleFinder.ofSystem().findAll()
- .stream()
- .map(ModuleReference::descriptor)
- .map(ModuleDescriptor::name)
- .filter(predicate)
- .collect(Collectors.toSet());
- }
-
- static void printAttributes(PrintStream out) {
- out.format(" size=\"25,25\";%n");
- out.format(" nodesep=.5;%n");
- out.format(" ranksep=1.5;%n");
- out.format(" pencolor=transparent;%n");
- out.format(" node [shape=plaintext, fontname=\"DejaVuSans\", fontsize=36, margin=\".2,.2\"];%n");
- out.format(" edge [penwidth=4, color=\"#999999\", arrowhead=open, arrowsize=2];%n");
- }
-
- static void printNodes(PrintStream out, Graph<String> graph) {
- out.format(" subgraph se {%n");
- graph.nodes().stream()
- .filter(javaModules::contains)
- .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
- mn, ORANGE, "java"));
- out.format(" }%n");
- graph.nodes().stream()
- .filter(jdkModules::contains)
- .forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
- mn, BLUE, "jdk"));
-
- graph.nodes().stream()
- .filter(mn -> !javaModules.contains(mn) && !jdkModules.contains(mn))
- .forEach(mn -> out.format(" \"%s\";%n", mn));
- }
-
- static void printEdges(PrintStream out, Graph<String> graph,
- String node, Set<String> requiresPublic) {
- graph.adjacentNodes(node).forEach(dn -> {
- String attr = dn.equals("java.base") ? REQUIRES_BASE
- : (requiresPublic.contains(dn) ? REEXPORTS : REQUIRES);
- out.format(" \"%s\" -> \"%s\" [%s];%n", node, dn, attr);
- });
- }
- }
-
- public void genDotFile(Path dir) throws IOException {
- String name = root.name();
- try (PrintStream out
- = new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
- Configuration cf = modulePaths.configuration(name);
+ private void genDotFile(Path dir, String name) throws IOException {
+ try (OutputStream os = Files.newOutputStream(dir.resolve(name + ".dot"));
+ PrintWriter out = new PrintWriter(os)) {
+ Set<Module> modules = configuration.resolve(Set.of(name))
+ .collect(Collectors.toSet());
// transitive reduction
- Graph<String> graph = gengraph(cf);
+ Graph<String> graph = gengraph(modules);
out.format("digraph \"%s\" {%n", name);
DotGraph.printAttributes(out);
DotGraph.printNodes(out, graph);
- cf.modules().stream()
- .map(ResolvedModule::reference)
- .map(ModuleReference::descriptor)
- .sorted(Comparator.comparing(ModuleDescriptor::name))
- .forEach(md -> {
- String mn = md.name();
- Set<String> requiresPublic = md.requires().stream()
+ modules.stream()
+ .map(Module::descriptor)
+ .sorted(Comparator.comparing(ModuleDescriptor::name))
+ .forEach(md -> {
+ String mn = md.name();
+ Set<String> requiresPublic = md.requires().stream()
.filter(d -> d.modifiers().contains(PUBLIC))
.map(d -> d.name())
- .collect(Collectors.toSet());
+ .collect(toSet());
- DotGraph.printEdges(out, graph, mn, requiresPublic);
- });
+ DotGraph.printEdges(out, graph, mn, requiresPublic);
+ });
out.println("}");
}
}
-
/**
* Returns a Graph of the given Configuration after transitive reduction.
*
@@ -675,12 +441,12 @@
* (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
* in which V would not be re-exported from U.
*/
- private Graph<String> gengraph(Configuration cf) {
+ private Graph<String> gengraph(Set<Module> modules) {
// build a Graph containing only requires public edges
// with transitive reduction.
Graph.Builder<String> rpgbuilder = new Graph.Builder<>();
- for (ResolvedModule resolvedModule : cf.modules()) {
- ModuleDescriptor md = resolvedModule.reference().descriptor();
+ for (Module module : modules) {
+ ModuleDescriptor md = module.descriptor();
String mn = md.name();
md.requires().stream()
.filter(d -> d.modifiers().contains(PUBLIC))
@@ -692,12 +458,12 @@
// build the readability graph
Graph.Builder<String> builder = new Graph.Builder<>();
- for (ResolvedModule resolvedModule : cf.modules()) {
- ModuleDescriptor md = resolvedModule.reference().descriptor();
+ for (Module module : modules) {
+ ModuleDescriptor md = module.descriptor();
String mn = md.name();
builder.addNode(mn);
- resolvedModule.reads().stream()
- .map(ResolvedModule::name)
+ configuration.reads(module)
+ .map(Module::name)
.forEach(d -> builder.addEdge(mn, d));
}
@@ -705,4 +471,25 @@
return builder.build().reduce(rpg);
}
+ // ---- for testing purpose
+ public ModuleDescriptor[] descriptors(String name) {
+ ModuleDeps moduleDeps = modules.keySet().stream()
+ .filter(m -> m.name().equals(name))
+ .map(modules::get)
+ .findFirst().get();
+
+ ModuleDescriptor[] descriptors = new ModuleDescriptor[3];
+ descriptors[0] = moduleDeps.root.descriptor();
+ descriptors[1] = moduleDeps.descriptor();
+ descriptors[2] = moduleDeps.reduced();
+ return descriptors;
+ }
+
+ public Map<String, Set<String>> unusedQualifiedExports(String name) {
+ ModuleDeps moduleDeps = modules.keySet().stream()
+ .filter(m -> m.name().equals(name))
+ .map(modules::get)
+ .findFirst().get();
+ return moduleDeps.unusedQualifiedExports;
+ }
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleInfoBuilder.java Thu May 19 19:47:04 2016 +0000
@@ -24,15 +24,24 @@
*/
package com.sun.tools.jdeps;
-import static com.sun.tools.jdeps.Analyzer.Type.CLASS;
+import static com.sun.tools.jdeps.JdepsTask.*;
import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
-import static com.sun.tools.jdeps.Module.trace;
+import static com.sun.tools.jdeps.JdepsFilter.DEFAULT_FILTER;
import java.io.IOException;
import java.io.PrintWriter;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleDescriptor.Exports;
+import java.lang.module.ModuleDescriptor.Provides;
+import java.lang.module.ModuleDescriptor.Requires;
+import java.lang.module.ModuleFinder;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Comparator;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -40,168 +49,159 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
+
public class ModuleInfoBuilder {
- final ModulePaths modulePaths;
+ final JdepsConfiguration configuration;
+ final Path outputdir;
+
final DependencyFinder dependencyFinder;
- final JdepsFilter filter;
final Analyzer analyzer;
- final Map<Module, Module> strictModules = new HashMap<>();
- ModuleInfoBuilder(ModulePaths modulePaths, DependencyFinder finder) {
- this.modulePaths = modulePaths;
- this.dependencyFinder = finder;
- this.filter = new JdepsFilter.Builder().filter(true, true).build();
- this.analyzer = new Analyzer(CLASS, filter);
+ final Map<Module, Module> strictModules;
+ public ModuleInfoBuilder(JdepsConfiguration configuration,
+ List<String> args,
+ Path outputdir) {
+ this.configuration = configuration;
+ this.outputdir = outputdir;
+
+ this.dependencyFinder = new DependencyFinder(configuration, DEFAULT_FILTER);
+ this.analyzer = new Analyzer(configuration, Analyzer.Type.CLASS, DEFAULT_FILTER);
+
+ // add targets to modulepath if it has module-info.class
+ List<Path> paths = args.stream()
+ .map(fn -> Paths.get(fn))
+ .collect(Collectors.toList());
+
+ // automatic module to convert to strict module
+ this.strictModules = ModuleFinder.of(paths.toArray(new Path[0]))
+ .findAll().stream()
+ .map(configuration::toModule)
+ .collect(Collectors.toMap(Function.identity(), Function.identity()));
+
+ Optional<Module> om = strictModules.keySet().stream()
+ .filter(m -> !m.descriptor().isAutomatic())
+ .findAny();
+ if (om.isPresent()) {
+ throw new UncheckedBadArgs(new BadArgs("err.genmoduleinfo.not.jarfile",
+ om.get().getPathName()));
+ }
+ if (strictModules.isEmpty()) {
+ throw new UncheckedBadArgs(new BadArgs("err.invalid.path", args));
+ }
}
- private Stream<Module> automaticModules() {
- return modulePaths.getModules().values()
- .stream()
- .filter(Module::isAutomatic);
+ public boolean run() throws IOException {
+ try {
+ // pass 1: find API dependencies
+ Map<Archive, Set<Archive>> requiresPublic = computeRequiresPublic();
+
+ // pass 2: analyze all class dependences
+ dependencyFinder.parse(automaticModules().stream());
+
+ analyzer.run(automaticModules(), dependencyFinder.locationToArchive());
+
+ // computes requires and requires public
+ automaticModules().forEach(m -> {
+ Map<String, Boolean> requires;
+ if (requiresPublic.containsKey(m)) {
+ requires = requiresPublic.get(m).stream()
+ .map(Archive::getModule)
+ .collect(Collectors.toMap(Module::name, (v) -> Boolean.TRUE));
+ } else {
+ requires = new HashMap<>();
+ }
+ analyzer.requires(m)
+ .map(Archive::getModule)
+ .forEach(d -> requires.putIfAbsent(d.name(), Boolean.FALSE));
+
+ strictModules.put(m, m.toStrictModule(requires));
+ });
+
+ // generate module-info.java
+ descriptors().forEach(md -> writeModuleInfo(outputdir, md));
+
+ // find any missing dependences
+ return automaticModules().stream()
+ .flatMap(analyzer::requires)
+ .allMatch(m -> !m.equals(NOT_FOUND));
+ } finally {
+ dependencyFinder.shutdown();
+ }
+ }
+
+ /**
+ * Returns the stream of resulting modules
+ */
+ Stream<Module> modules() {
+ return strictModules.values().stream();
+ }
+
+ /**
+ * Returns the stream of resulting ModuleDescriptors
+ */
+ public Stream<ModuleDescriptor> descriptors() {
+ return strictModules.values().stream().map(Module::descriptor);
+ }
+
+ void visitMissingDeps(Analyzer.Visitor visitor) {
+ automaticModules().stream()
+ .filter(m -> analyzer.requires(m).anyMatch(d -> d.equals(NOT_FOUND)))
+ .forEach(m -> {
+ analyzer.visitDependences(m, visitor, Analyzer.Type.VERBOSE);
+ });
+ }
+ void writeModuleInfo(Path dir, ModuleDescriptor descriptor) {
+ String mn = descriptor.name();
+ Path srcFile = dir.resolve(mn).resolve("module-info.java");
+ try {
+ Files.createDirectories(srcFile.getParent());
+ System.out.println("writing to " + srcFile);
+ try (PrintWriter pw = new PrintWriter(Files.newOutputStream(srcFile))) {
+ printModuleInfo(pw, descriptor);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private void printModuleInfo(PrintWriter writer, ModuleDescriptor descriptor) {
+ writer.format("module %s {%n", descriptor.name());
+
+ Map<String, Module> modules = configuration.getModules();
+ // first print the JDK modules
+ descriptor.requires().stream()
+ .filter(req -> !req.name().equals("java.base")) // implicit requires
+ .sorted(Comparator.comparing(Requires::name))
+ .forEach(req -> writer.format(" requires %s;%n", req));
+
+ descriptor.exports().stream()
+ .peek(exp -> {
+ if (exp.targets().size() > 0)
+ throw new InternalError(descriptor.name() + " qualified exports: " + exp);
+ })
+ .sorted(Comparator.comparing(Exports::source))
+ .forEach(exp -> writer.format(" exports %s;%n", exp.source()));
+
+ descriptor.provides().values().stream()
+ .sorted(Comparator.comparing(Provides::service))
+ .forEach(p -> p.providers().stream()
+ .sorted()
+ .forEach(impl -> writer.format(" provides %s with %s;%n", p.service(), impl)));
+
+ writer.println("}");
+ }
+
+
+ private Set<Module> automaticModules() {
+ return strictModules.keySet();
}
/**
* Compute 'requires public' dependences by analyzing API dependencies
*/
- Map<Module, Set<Module>> computeRequiresPublic() throws IOException {
- dependencyFinder.findDependencies(filter, true /* api only */, 1);
- Analyzer pass1 = new Analyzer(Analyzer.Type.CLASS, filter);
-
- pass1.run(dependencyFinder.archives());
-
- return automaticModules().collect(Collectors.toMap(Function.identity(),
- source -> pass1.requires(source)
- .map(Archive::getModule)
- .collect(Collectors.toSet())));
- }
-
- boolean run(Analyzer.Type verbose, boolean quiet) throws IOException {
- // add all automatic modules to the root set
- automaticModules().forEach(dependencyFinder::addRoot);
-
- // pass 1: find API dependencies
- Map<Module, Set<Module>> requiresPublic = computeRequiresPublic();
-
- // pass 2: analyze all class dependences
- dependencyFinder.findDependencies(filter, false /* all classes */, 1);
- analyzer.run(dependencyFinder.archives());
-
- // computes requires and requires public
- automaticModules().forEach(m -> {
- Map<String, Boolean> requires;
- if (requiresPublic.containsKey(m)) {
- requires = requiresPublic.get(m)
- .stream()
- .collect(Collectors.toMap(Archive::getName, (v) -> Boolean.TRUE));
- } else {
- requires = new HashMap<>();
- }
- analyzer.requires(m)
- .forEach(d -> requires.putIfAbsent(d.getName(), Boolean.FALSE));
-
- trace("strict module %s requires %s%n", m.name(), requires);
- strictModules.put(m, m.toStrictModule(requires));
- });
-
- // find any missing dependences
- Optional<Module> missingDeps = automaticModules()
- .filter(this::missingDep)
- .findAny();
- if (missingDeps.isPresent()) {
- automaticModules()
- .filter(this::missingDep)
- .forEach(m -> {
- System.err.format("Missing dependencies from %s%n", m.name());
- analyzer.visitDependences(m,
- new Analyzer.Visitor() {
- @Override
- public void visitDependence(String origin, Archive originArchive,
- String target, Archive targetArchive) {
- if (targetArchive == NOT_FOUND)
- System.err.format(" %-50s -> %-50s %s%n",
- origin, target, targetArchive.getName());
- }
- }, verbose);
- System.err.println();
- });
-
- System.err.println("ERROR: missing dependencies (check \"requires NOT_FOUND;\")");
- }
- return missingDeps.isPresent() ? false : true;
- }
+ private Map<Archive, Set<Archive>> computeRequiresPublic() throws IOException {
+ // parse the input modules
+ dependencyFinder.parseExportedAPIs(automaticModules().stream());
- private boolean missingDep(Archive m) {
- return analyzer.requires(m).filter(a -> a.equals(NOT_FOUND))
- .findAny().isPresent();
- }
-
- void build(Path dir) throws IOException {
- ModuleInfoWriter writer = new ModuleInfoWriter(dir);
- writer.generateOutput(strictModules.values(), analyzer);
- }
-
- private class ModuleInfoWriter {
- private final Path outputDir;
- ModuleInfoWriter(Path dir) {
- this.outputDir = dir;
- }
-
- void generateOutput(Iterable<Module> modules, Analyzer analyzer) throws IOException {
- // generate module-info.java file for each archive
- for (Module m : modules) {
- if (m.packages().contains("")) {
- System.err.format("ERROR: %s contains unnamed package. " +
- "module-info.java not generated%n", m.getPathName());
- continue;
- }
-
- String mn = m.getName();
- Path srcFile = outputDir.resolve(mn).resolve("module-info.java");
- Files.createDirectories(srcFile.getParent());
- System.out.println("writing to " + srcFile);
- try (PrintWriter pw = new PrintWriter(Files.newOutputStream(srcFile))) {
- printModuleInfo(pw, m);
- }
- }
- }
-
- private void printModuleInfo(PrintWriter writer, Module m) {
- writer.format("module %s {%n", m.name());
-
- Map<String, Module> modules = modulePaths.getModules();
- Map<String, Boolean> requires = m.requires();
- // first print the JDK modules
- requires.keySet().stream()
- .filter(mn -> !mn.equals("java.base")) // implicit requires
- .filter(mn -> modules.containsKey(mn) && modules.get(mn).isJDK())
- .sorted()
- .forEach(mn -> {
- String modifier = requires.get(mn) ? "public " : "";
- writer.format(" requires %s%s;%n", modifier, mn);
- });
-
- // print requires non-JDK modules
- requires.keySet().stream()
- .filter(mn -> !modules.containsKey(mn) || !modules.get(mn).isJDK())
- .sorted()
- .forEach(mn -> {
- String modifier = requires.get(mn) ? "public " : "";
- writer.format(" requires %s%s;%n", modifier, mn);
- });
-
- m.packages().stream()
- .sorted()
- .forEach(pn -> writer.format(" exports %s;%n", pn));
-
- m.provides().entrySet().stream()
- .sorted(Map.Entry.comparingByKey())
- .forEach(e -> {
- String service = e.getKey();
- e.getValue().stream()
- .sorted()
- .forEach(impl -> writer.format(" provides %s with %s;%n", service, impl));
- });
-
- writer.println("}");
- }
+ return dependencyFinder.dependences();
}
}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulePaths.java Thu May 19 17:48:04 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.tools.jdeps;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.lang.module.Configuration;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleFinder;
-import java.lang.module.ModuleReference;
-import java.lang.module.ResolvedModule;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystemNotFoundException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.ProviderNotFoundException;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
-
-public class ModulePaths {
- final ModuleFinder finder;
- final Map<String, Module> modules = new LinkedHashMap<>();
-
- public ModulePaths(String upgradeModulePath, String modulePath) {
- this(upgradeModulePath, modulePath, Collections.emptyList());
- }
-
- public ModulePaths(String upgradeModulePath, String modulePath, List<Path> jars) {
- ModuleFinder finder = ModuleFinder.ofSystem();
- if (upgradeModulePath != null) {
- finder = ModuleFinder.compose(createModulePathFinder(upgradeModulePath), finder);
- }
- if (jars.size() > 0) {
- finder = ModuleFinder.compose(finder, ModuleFinder.of(jars.toArray(new Path[0])));
- }
- if (modulePath != null) {
- finder = ModuleFinder.compose(finder, createModulePathFinder(modulePath));
- }
- this.finder = finder;
-
- // add modules from modulepaths
- finder.findAll().stream().forEach(mref ->
- modules.computeIfAbsent(mref.descriptor().name(), mn -> toModule(mn, mref))
- );
- }
-
- /**
- * Returns the list of Modules that can be found in the specified
- * module paths.
- */
- Map<String, Module> getModules() {
- return modules;
- }
-
- Set<Module> dependences(String... roots) {
- Configuration cf = configuration(roots);
- return cf.modules().stream()
- .map(ResolvedModule::name)
- .map(modules::get)
- .collect(Collectors.toSet());
- }
-
- Configuration configuration(String... roots) {
- return Configuration.empty().resolveRequires(finder, ModuleFinder.empty(), Set.of(roots));
- }
-
- private static ModuleFinder createModulePathFinder(String mpaths) {
- if (mpaths == null) {
- return null;
- } else {
- String[] dirs = mpaths.split(File.pathSeparator);
- Path[] paths = new Path[dirs.length];
- int i = 0;
- for (String dir : dirs) {
- paths[i++] = Paths.get(dir);
- }
- return ModuleFinder.of(paths);
- }
- }
-
- private static Module toModule(String mn, ModuleReference mref) {
- return SystemModulePath.find(mn)
- .orElse(toModule(new Module.Builder(mn), mref));
- }
-
- private static Module toModule(Module.Builder builder, ModuleReference mref) {
- ModuleDescriptor md = mref.descriptor();
- builder.descriptor(md);
- for (ModuleDescriptor.Requires req : md.requires()) {
- builder.require(req.name(), req.modifiers().contains(PUBLIC));
- }
- for (ModuleDescriptor.Exports exp : md.exports()) {
- builder.export(exp.source(), exp.targets());
- }
- builder.packages(md.packages());
-
- try {
- URI location = mref.location()
- .orElseThrow(FileNotFoundException::new);
- builder.location(location);
- builder.classes(getClassReader(location, md.name()));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- return builder.build();
- }
-
- static class SystemModulePath {
- final static Module JAVA_BASE;
-
- private final static FileSystem fs;
- private final static Path root;
- private final static Map<String, Module> installed = new HashMap<>();
- static {
- if (isJrtAvailable()) {
- // jrt file system
- fs = FileSystems.getFileSystem(URI.create("jrt:/"));
- root = fs.getPath("/modules");
- } else {
- // exploded image
- String javahome = System.getProperty("java.home");
- fs = FileSystems.getDefault();
- root = Paths.get(javahome, "modules");
- }
-
- ModuleFinder.ofSystem().findAll().stream()
- .forEach(mref ->
- installed.computeIfAbsent(mref.descriptor().name(),
- mn -> toModule(new Module.Builder(mn, true), mref))
- );
- JAVA_BASE = installed.get("java.base");
-
- Profile.init(installed);
- }
-
- private static boolean isJrtAvailable() {
- try {
- FileSystems.getFileSystem(URI.create("jrt:/"));
- return true;
- } catch (ProviderNotFoundException | FileSystemNotFoundException e) {
- return false;
- }
- }
-
- public static Optional<Module> find(String mn) {
- return installed.containsKey(mn) ? Optional.of(installed.get(mn))
- : Optional.empty();
- }
-
- public static boolean contains(Module m) {
- return installed.containsValue(m);
- }
-
- public static ClassFileReader getClassReader(String modulename) throws IOException {
- Path mp = root.resolve(modulename);
- if (Files.exists(mp) && Files.isDirectory(mp)) {
- return ClassFileReader.newInstance(fs, mp);
- } else {
- throw new FileNotFoundException(mp.toString());
- }
- }
- }
-
- /**
- * Returns a ModuleClassReader that only reads classes for the given modulename.
- */
- public static ClassFileReader getClassReader(URI location, String modulename)
- throws IOException {
- if (location.getScheme().equals("jrt")) {
- return SystemModulePath.getClassReader(modulename);
- } else {
- Path path = Paths.get(location);
- return ClassFileReader.newInstance(path);
- }
- }
-}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Thu May 19 19:47:04 2016 +0000
@@ -26,9 +26,13 @@
package com.sun.tools.jdeps;
import java.io.IOException;
+import java.lang.module.ModuleDescriptor;
+import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
/**
@@ -44,17 +48,18 @@
// need a way to determine JRE modules
SE_JRE("Java SE JRE", 4, "java.se", "jdk.charsets",
"jdk.crypto.ec", "jdk.crypto.pkcs11",
- "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
+ "jdk.crypto.mscapi", "jdk.crypto.ucrypto",
"jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"),
FULL_JRE("Full JRE", 5, "java.se.ee", "jdk.charsets",
"jdk.crypto.ec", "jdk.crypto.pkcs11",
"jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat",
- "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs");
+ "jdk.localedata", "jdk.scripting.nashorn",
+ "jdk.unsupported", "jdk.zipfs");
final String name;
final int profile;
final String[] mnames;
- final Set<Module> modules = new HashSet<>();
+ final Map<String, Module> modules = new HashMap<>();
Profile(String name, int profile, String... mnames) {
this.name = name;
@@ -75,12 +80,18 @@
return JDK.isEmpty() ? 0 : Profile.values().length;
}
+ Optional<Module> findModule(String name) {
+ return modules.containsKey(name)
+ ? Optional.of(modules.get(name))
+ : Optional.empty();
+ }
+
/**
* Returns the Profile for the given package name; null if not found.
*/
public static Profile getProfile(String pn) {
for (Profile p : Profile.values()) {
- for (Module m : p.modules) {
+ for (Module m : p.modules.values()) {
if (m.packages().contains(pn)) {
return p;
}
@@ -94,7 +105,7 @@
*/
public static Profile getProfile(Module m) {
for (Profile p : Profile.values()) {
- if (p.modules.contains(m)) {
+ if (p.modules.containsValue(m)) {
return p;
}
}
@@ -102,34 +113,28 @@
}
private final static Set<Module> JDK = new HashSet<>();
- static synchronized void init(Map<String, Module> installed) {
- for (Profile p : Profile.values()) {
- for (String mn : p.mnames) {
- // this includes platform-dependent module that may not exist
- Module m = installed.get(mn);
- if (m != null) {
- p.addModule(installed, m);
- }
- }
- }
+ static synchronized void init(Map<String, Module> systemModules) {
+ Arrays.stream(Profile.values()).forEach(p ->
+ // this includes platform-dependent module that may not exist
+ Arrays.stream(p.mnames)
+ .filter(systemModules::containsKey)
+ .map(systemModules::get)
+ .forEach(m -> p.addModule(systemModules, m)));
// JDK modules should include full JRE plus other jdk.* modules
// Just include all installed modules. Assume jdeps is running
// in JDK image
- JDK.addAll(installed.values());
+ JDK.addAll(systemModules.values());
}
- private void addModule(Map<String, Module> installed, Module m) {
- modules.add(m);
- for (String n : m.requires().keySet()) {
- Module d = installed.get(n);
- if (d == null) {
- throw new InternalError("module " + n + " required by " +
- m.name() + " doesn't exist");
- }
- modules.add(d);
- }
+ private void addModule(Map<String, Module> systemModules, Module module) {
+ modules.put(module.name(), module);
+ module.descriptor().requires().stream()
+ .map(ModuleDescriptor.Requires::name)
+ .map(systemModules::get)
+ .forEach(m -> modules.put(m.name(), m));
}
+
// for debugging
public static void main(String[] args) throws IOException {
// find platform modules
@@ -139,14 +144,6 @@
for (Profile p : Profile.values()) {
String profileName = p.name;
System.out.format("%2d: %-10s %s%n", p.profile, profileName, p.modules);
- for (Module m: p.modules) {
- System.out.format("module %s%n", m.name());
- System.out.format(" requires %s%n", m.requires());
- for (Map.Entry<String,Set<String>> e: m.exports().entrySet()) {
- System.out.format(" exports %s %s%n", e.getKey(),
- e.getValue().isEmpty() ? "" : "to " + e.getValue());
- }
- }
}
System.out.println("All JDK modules:-");
JDK.stream().sorted(Comparator.comparing(Module::name))
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties Thu May 19 19:47:04 2016 +0000
@@ -1,12 +1,10 @@
main.usage.summary=\
-Usage: {0} <options> [-m <module-name> | <classes...>]\n\
+Usage: {0} <options> <path ...>]\n\
use -h, -? or -help for a list of possible options
main.usage=\
-Usage: {0} <options> [-m <module-name> | <classes...>]\n\
-If -m <module-name> is specified, the specified module will be analyzed\n\
-otherwise, <classes> can be a pathname to a .class file, a directory,\n\
-a JAR file, or a fully-qualified class name.\n\
+Usage: {0} <options> <path ...>]\n\
+<path> can be a pathname to a .class file, a directory, a JAR file.\n\
\n\
Possible options include:
@@ -14,134 +12,156 @@
warn.prefix=Warning:
main.opt.h=\
-\ -h -? -help Print this usage message
+\ -h -? -help Print this usage message
main.opt.version=\
-\ -version Version information
+\ -version Version information
main.opt.v=\
-\ -v -verbose Print all class level dependencies\n\
-\ Equivalent to -verbose:class -filter:none.\n\
-\ -verbose:package Print package-level dependencies excluding\n\
-\ dependencies within the same package by default\n\
-\ -verbose:class Print class-level dependencies excluding\n\
-\ dependencies within the same package by default
-
-main.opt.f=\
-\ -f <regex> -filter <regex> Filter dependences matching the given pattern\n\
-\ If given multiple times, the last one will be used.\n\
-\ -filter:package Filter dependences within the same package (default)\n\
-\ -filter:module Filter dependences within the same module\n\
-\ -filter:archive Filter dependences within the same archive\n\
-\ -filter:none No -filter:package and -filter:archive filtering\n\
-\ Filtering specified via the -filter option still applies.
+\ -v -verbose Print all class level dependencies\n\
+\ Equivalent to -verbose:class -filter:none.\n\
+\ -verbose:package Print package-level dependencies excluding\n\
+\ dependencies within the same package by default\n\
+\ -verbose:class Print class-level dependencies excluding\n\
+\ dependencies within the same package by default
main.opt.s=\
-\ -s -summary Print dependency summary only.\n\
-\ If -s option is used with -m, the module descriptor of\n\
-\ the given module will be read to generate the graph.
+\ -s -summary Print dependency summary only.
-main.opt.p=\
-\ -p <pkgname> Finds dependences matching the given package name\n\
-\ -package <pkgname> (may be given multiple times).
+main.opt.f=\
+\ -f <regex> -filter <regex> Filter dependences matching the given\n\
+\ pattern. If given multiple times, the last\n\
+\ one will be used.\n\
+\ -filter:package Filter dependences within the same package.\n\
+\ This is the default.\n\
+\ -filter:archive Filter dependences within the same archive.\n\
+\ -filter:module Filter dependences within the same module.\n\
+\ -filter:none No -filter:package and -filter:archive\n\
+\ filtering. Filtering specified via the\n\
+\ -filter option still applies.\n\
+
+main.opt.p=\n\
+\Options to filter dependencies:\n\
+\ -p <pkgname> -package <pkgname> Finds dependences matching the given package\n\
+\ name (may be given multiple times).
main.opt.e=\
-\ -e <regex>\n\
-\ -regex <regex> Finds dependences matching the given pattern.
+\ -e <regex> -regex <regex> Finds dependences matching the given pattern.
+
+main.opt.requires=\
+\ -requires <module-name> Finds dependences matching the given module\n\
+\ name (may be given multiple times).\n\
+\ -package, -regex, -requires are mutual exclusive.
-main.opt.module=\
-\ -module <module-name> Finds dependences matching the given module name\n\
-\ (may be given multiple times).\n\
-\ -package, -regex, -requires are mutual exclusive.
-
-main.opt.include=\
-\ -include <regex> Restrict analysis to classes matching pattern\n\
-\ This option filters the list of classes to\n\
-\ be analyzed. It can be used together with\n\
-\ -p and -e which apply pattern to the dependences
+main.opt.include=\n\
+ \Options to filter classes to be analyzed:\n\
+\ -include <regex> Restrict analysis to classes matching pattern\n\
+\ This option filters the list of classes to\n\
+\ be analyzed. It can be used together with\n\
+\ -p and -e which apply pattern to the dependences
main.opt.P=\
-\ -P -profile Show profile containing a package
-
-main.opt.M=\
-\ -M Show module containing a package
+\ -P -profile Show profile containing a package
main.opt.cp=\
-\ -cp <path> -classpath <path> Specify where to find class files
+\ -cp <path> -classpath <path> Specify where to find class files
main.opt.mp=\
\ -mp <module path>...\n\
-\ -modulepath <module path>... Specify module path
+\ -modulepath <module path>... Specify module path
main.opt.upgrademodulepath=\
\ -upgrademodulepath <module path>... Specify upgrade module path
+main.opt.system=\
+\ -system <java-home> Specify an alternate system module path
+
+main.opt.addmods=\
+\ -addmods <module-name>[,<module-name>...]\n\
+\ Adds modules to the root set for analysis
+
main.opt.m=\
-\ -m <module-name> Specify the name of the module and its transitive\n\
-\ dependences to be analyzed.
+\ -m <module-name> Specify the root module for analysis
main.opt.R=\
-\ -R -recursive Recursively traverse all run-time dependencies.\n\
-\ The -R option implies -filter:none. If -p, -e, -f\n\
-\ option is specified, only the matching dependences\n\
-\ are analyzed.
+\ -R -recursive Recursively traverse all run-time dependencies.\n\
+\ The -R option implies -filter:none. If -p,\n\
+\ -e, -foption is specified, only the matching\n\
+\ dependences are analyzed.
+
+main.opt.I=\
+\ -I -inverse Analyzes the dependences per other given options\n\
+\ and then find all artifacts that directly\n\
+\ and indirectly depend on the matching nodes.\n\
+\ This is equivalent to the inverse of\n\
+\ compile-time view analysis and print\n\
+\ dependency summary. This option must use\n\
+\ with -requires, -package or -regex option.
main.opt.ct=\
-\ -ct -compile-time Compile-time view of transitive dependencies\n\
-\ i.e. compile-time view of -R option. If a dependence\n\
-\ is found from a directory, a JAR file or a module,\n\
-\ all class files in that containing archive are analyzed.
+\ -ct -compile-time Compile-time view of transitive dependencies\n\
+\ i.e. compile-time view of -R option.\n\
+\ Analyzes the dependences per other given options\n\
+\ If a dependence is found from a directory,\n\
+\ a JAR file or a module, all classes in that \n\
+\ containing archive are analyzed.
main.opt.apionly=\
-\ -apionly Restrict analysis to APIs i.e. dependences\n\
-\ from the signature of public and protected\n\
-\ members of public classes including field\n\
-\ type, method parameter types, returned type,\n\
-\ checked exception types etc
+\ -apionly Restrict analysis to APIs i.e. dependences\n\
+\ from the signature of public and protected\n\
+\ members of public classes including field\n\
+\ type, method parameter types, returned type,\n\
+\ checked exception types etc.
main.opt.genmoduleinfo=\
-\ -genmoduleinfo <dir> Generate module-info.java under the specified directory.\n\
-\ The specified JAR files will be analyzed.\n\
-\ This option cannot be used with -dotoutput or -cp.
+\ -genmoduleinfo <dir> Generate module-info.java under the specified\n\
+\ directory. The specified JAR files will be\n\
+\ analyzed. This option cannot be used with\n\
+\ -dotoutput or -cp.
main.opt.check=\
-\ -check Analyze the dependence of a given module specified via\n\
-\ -m option. It prints out the resulting module dependency\n\
-\ graph after transition reduction and also identifies any\n\
-\ unused qualified exports.
+\ -check <module-name>[,<module-name>...\n\
+\ Analyze the dependence of the specified modules\n\
+\ It prints the module descriptor, the resulting\n\
+\ module dependences after analysis and the\n\
+\ graph after transition reduction. It also\n\
+\ identifies any unused qualified exports.
main.opt.dotoutput=\
-\ -dotoutput <dir> Destination directory for DOT file output
+\ -dotoutput <dir> Destination directory for DOT file output
main.opt.jdkinternals=\
-\ -jdkinternals Finds class-level dependences on JDK internal APIs.\n\
-\ By default, it analyzes all classes on -classpath\n\
-\ and input files unless -include option is specified.\n\
-\ This option cannot be used with -p, -e and -s options.\n\
-\ WARNING: JDK internal APIs may not be accessible in\n\
-\ the next release.
+\ -jdkinternals Finds class-level dependences on JDK internal\n\
+\ APIs. By default, it analyzes all classes\n\
+\ on -classpath and input files unless -include\n\
+\ option is specified. This option cannot be\n\
+\ used with -p, -e and -s options.\n\
+\ WARNING: JDK internal APIs are inaccessible.
main.opt.depth=\
-\ -depth=<depth> Specify the depth of the transitive\n\
-\ dependency analysis
+\ -depth=<depth> Specify the depth of the transitive\n\
+\ dependency analysis
main.opt.q=\
-\ -q -quiet Do not show missing dependencies from -genmoduleinfo output.
+\ -q -quiet Do not show missing dependencies from \n\
+\ -genmoduleinfo output.
err.unknown.option=unknown option: {0}
err.missing.arg=no value given for {0}
err.invalid.arg.for.option=invalid argument for option: {0}
err.option.after.class=option must be specified before classes: {0}
-err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be JAR file)
+err.genmoduleinfo.not.jarfile={0} not valid for -genmoduleinfo option (must be non-modular JAR file)
err.profiles.msg=No profile information
err.exception.message={0}
err.invalid.path=invalid path: {0}
-err.invalid.module.option=-m {0} is set but {1} is specified.
+err.invalid.module.option=Cannot set {0} with {1} option.
err.invalid.filters=Only one of -package (-p), -regex (-e), -requires option can be set
err.module.not.found=module not found: {0}
-err.root.module.not.set=-m is not set
-warn.invalid.arg=Invalid classname or pathname not exist: {0}
+err.root.module.not.set=root module set empty
+err.invalid.inverse.option={0} cannot be used with -inverse option
+err.inverse.filter.not.set={0} cannot be used with -inverse option
+warn.invalid.arg=Path not exist: {0}
warn.split.package=package {0} defined in {1} {2}
warn.replace.useJDKInternals=\
JDK internal APIs are unsupported and private to JDK implementation that are\n\
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties Thu May 19 19:47:04 2016 +0000
@@ -1,6 +1,5 @@
-// No translation needed
+# No translation needed
com.sun.crypto.provider.SunJCE=Use java.security.Security.getProvider(provider-name) @since 1.3
-com.sun.image.codec=Use javax.imageio @since 1.4
com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6
com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8
com.sun.org.apache.xml.internal.resolver=Use javax.xml.catalog @since 9
@@ -9,17 +8,34 @@
com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7
com.sun.tools.javac.tree=Use com.sun.source @since 1.6
com.sun.tools.javac=Use javax.tools and javax.lang.model @since 1.6
+java.awt.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739
+java.awt.dnd.peer=Should not use. See https://bugs.openjdk.java.net/browse/JDK-8037739
+jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
sun.awt.image.codec=Use javax.imageio @since 1.4
-sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
-sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
-sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
-sun.misc.Service=Use java.util.ServiceLoader @since 1.6
+sun.awt.CausedFocusEvent=Use java.awt.event.FocusEvent::getCause @since 9
+sun.font.FontUtilities=See java.awt.Font.textRequiresLayout @since 9
+sun.reflect.Reflection=See StackWalker API @since 9
+sun.reflect.ReflectionFactory=See http://openjdk.java.net/jeps/260
+sun.misc.Unsafe=See http://openjdk.java.net/jeps/260
+sun.misc.Signal=See http://openjdk.java.net/jeps/260
+sun.misc.SignalHandler=See http://openjdk.java.net/jeps/260
sun.security.action=Use java.security.PrivilegedAction @since 1.1
sun.security.krb5=Use com.sun.security.jgss
sun.security.provider.PolicyFile=Use java.security.Policy.getInstance("JavaPolicy", new URIParameter(uri)) @since 1.6
sun.security.provider.Sun=Use java.security.Security.getProvider(provider-name) @since 1.3
sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1
sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
-sun.tools.jar=Use java.util.jar or jar tool @since 1.2
-jdk.internal.ref.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
+sun.tools.jar=Use java.util.jar or jar tool @since 1.2\
+# Internal APIs removed in JDK 9
+com.apple.eawt=Use java.awt.desktop and JEP 272 @since 9
+com.apple.concurrent=Removed. See https://bugs.openjdk.java.net/browse/JDK-8148187
+com.sun.image.codec=Use javax.imageio @since 1.4
+sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
+sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
+sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2 or java.lang.ref.Cleaner @since 9
+sun.misc.Service=Use java.util.ServiceLoader @since 1.6
+sun.misc=Removed. See http://openjdk.java.net/jeps/260
+sun.reflect=Removed. See http://openjdk.java.net/jeps/260
+
+
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java Thu May 19 19:47:04 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -25,7 +25,6 @@
package jdk.internal.jshell.tool;
-import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
import jdk.jshell.SourceCodeAnalysis.Suggestion;
@@ -36,6 +35,7 @@
import java.io.UncheckedIOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -44,6 +44,9 @@
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
+import java.util.prefs.BackingStoreException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import jdk.internal.jline.NoInterruptUnixTerminal;
import jdk.internal.jline.Terminal;
@@ -54,10 +57,13 @@
import jdk.internal.jline.console.KeyMap;
import jdk.internal.jline.console.UserInterruptException;
import jdk.internal.jline.console.completer.Completer;
+import jdk.internal.jline.extra.EditingHistory;
import jdk.internal.jshell.tool.StopDetectingInputStream.State;
class ConsoleIOContext extends IOContext {
+ private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_";
+
final JShellTool repl;
final StopDetectingInputStream input;
final ConsoleReader in;
@@ -80,9 +86,14 @@
in = new ConsoleReader(cmdin, cmdout, term);
in.setExpandEvents(false);
in.setHandleUserInterrupt(true);
- in.setHistory(history = new EditingHistory(repl.prefs) {
- @Override protected CompletionInfo analyzeCompletion(String input) {
- return repl.analysis.analyzeCompletion(input);
+ List<String> persistenHistory = Stream.of(repl.prefs.keys())
+ .filter(key -> key.startsWith(HISTORY_LINE_PREFIX))
+ .sorted()
+ .map(key -> repl.prefs.get(key, null))
+ .collect(Collectors.toList());
+ in.setHistory(history = new EditingHistory(in, persistenHistory) {
+ @Override protected boolean isComplete(CharSequence input) {
+ return repl.analysis.analyzeCompletion(input.toString()).completeness.isComplete;
}
});
in.setBellEnabled(true);
@@ -150,8 +161,6 @@
}
});
bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl));
- bind(CTRL_UP, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::previousSnippet));
- bind(CTRL_DOWN, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::nextSnippet));
for (FixComputer computer : FIX_COMPUTERS) {
for (String shortcuts : SHORTCUT_FIXES) {
bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer));
@@ -181,7 +190,24 @@
@Override
public void close() throws IOException {
- history.save();
+ //save history:
+ try {
+ for (String key : repl.prefs.keys()) {
+ if (key.startsWith(HISTORY_LINE_PREFIX))
+ repl.prefs.remove(key);
+ }
+ Collection<? extends String> savedHistory = history.save();
+ if (!savedHistory.isEmpty()) {
+ int len = (int) Math.ceil(Math.log10(savedHistory.size()+1));
+ String format = HISTORY_LINE_PREFIX + "%0" + len + "d";
+ int index = 0;
+ for (String historyLine : savedHistory) {
+ repl.prefs.put(String.format(format, index++), historyLine);
+ }
+ }
+ } catch (BackingStoreException ex) {
+ throw new IllegalStateException(ex);
+ }
in.shutdown();
try {
in.getTerminal().restore();
@@ -190,30 +216,6 @@
}
}
- private void moveHistoryToSnippet(Supplier<Boolean> action) {
- if (!action.get()) {
- try {
- in.beep();
- } catch (IOException ex) {
- throw new IllegalStateException(ex);
- }
- } else {
- try {
- //could use:
- //in.resetPromptLine(in.getPrompt(), in.getHistory().current().toString(), -1);
- //but that would mean more re-writing on the screen, (and prints an additional
- //empty line), so using setBuffer directly:
- Method setBuffer = in.getClass().getDeclaredMethod("setBuffer", String.class);
-
- setBuffer.setAccessible(true);
- setBuffer.invoke(in, in.getHistory().current().toString());
- in.flush();
- } catch (ReflectiveOperationException | IOException ex) {
- throw new IllegalStateException(ex);
- }
- }
- }
-
private void bind(String shortcut, Object action) {
KeyMap km = in.getKeys();
for (int i = 0; i < shortcut.length(); i++) {
@@ -227,8 +229,6 @@
}
private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
- private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP
- private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN
private static final String[] SHORTCUT_FIXES = {
"\033\015", //Alt-Enter (Linux)
"\033\133\061\067\176", //F6/Alt-F1 (Mac)
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/EditingHistory.java Thu May 19 17:48:04 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,382 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.internal.jshell.tool;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-import java.util.prefs.BackingStoreException;
-import java.util.prefs.Preferences;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import jdk.internal.jline.console.history.History;
-import jdk.internal.jline.console.history.History.Entry;
-import jdk.internal.jline.console.history.MemoryHistory;
-import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
-
-/*Public for tests (HistoryTest).
- */
-public abstract class EditingHistory implements History {
-
- private final Preferences prefs;
- private final History fullHistory;
- private History currentDelegate;
-
- protected EditingHistory(Preferences prefs) {
- this.prefs = prefs;
- this.fullHistory = new MemoryHistory();
- this.currentDelegate = fullHistory;
- load();
- }
-
- @Override
- public int size() {
- return currentDelegate.size();
- }
-
- @Override
- public boolean isEmpty() {
- return currentDelegate.isEmpty();
- }
-
- @Override
- public int index() {
- return currentDelegate.index();
- }
-
- @Override
- public void clear() {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- currentDelegate.clear();
- }
-
- @Override
- public CharSequence get(int index) {
- return currentDelegate.get(index);
- }
-
- @Override
- public void add(CharSequence line) {
- NarrowingHistoryLine currentLine = null;
- int origIndex = fullHistory.index();
- int fullSize;
- try {
- fullHistory.moveToEnd();
- fullSize = fullHistory.index();
- if (currentDelegate == fullHistory) {
- if (origIndex < fullHistory.index()) {
- for (Entry entry : fullHistory) {
- if (!(entry.value() instanceof NarrowingHistoryLine))
- continue;
- int[] cluster = ((NarrowingHistoryLine) entry.value()).span;
- if (cluster[0] == origIndex && cluster[1] > cluster[0]) {
- currentDelegate = new MemoryHistory();
- for (int i = cluster[0]; i <= cluster[1]; i++) {
- currentDelegate.add(fullHistory.get(i));
- }
- }
- }
- }
- }
- fullHistory.moveToEnd();
- while (fullHistory.previous()) {
- CharSequence c = fullHistory.current();
- if (c instanceof NarrowingHistoryLine) {
- currentLine = (NarrowingHistoryLine) c;
- break;
- }
- }
- } finally {
- fullHistory.moveTo(origIndex);
- }
- if (currentLine == null || currentLine.span[1] != (-1)) {
- line = currentLine = new NarrowingHistoryLine(line, fullSize);
- }
- StringBuilder complete = new StringBuilder();
- for (int i = currentLine.span[0]; i < fullSize; i++) {
- complete.append(fullHistory.get(i));
- }
- complete.append(line);
- if (analyzeCompletion(complete.toString()).completeness.isComplete) {
- currentLine.span[1] = fullSize; //TODO: +1?
- currentDelegate = fullHistory;
- }
- fullHistory.add(line);
- }
-
- protected abstract CompletionInfo analyzeCompletion(String input);
-
- @Override
- public void set(int index, CharSequence item) {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- currentDelegate.set(index, item);
- }
-
- @Override
- public CharSequence remove(int i) {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- return currentDelegate.remove(i);
- }
-
- @Override
- public CharSequence removeFirst() {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- return currentDelegate.removeFirst();
- }
-
- @Override
- public CharSequence removeLast() {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- return currentDelegate.removeLast();
- }
-
- @Override
- public void replace(CharSequence item) {
- if (currentDelegate != fullHistory)
- throw new IllegalStateException("narrowed");
- currentDelegate.replace(item);
- }
-
- @Override
- public ListIterator<Entry> entries(int index) {
- return currentDelegate.entries(index);
- }
-
- @Override
- public ListIterator<Entry> entries() {
- return currentDelegate.entries();
- }
-
- @Override
- public Iterator<Entry> iterator() {
- return currentDelegate.iterator();
- }
-
- @Override
- public CharSequence current() {
- return currentDelegate.current();
- }
-
- @Override
- public boolean previous() {
- return currentDelegate.previous();
- }
-
- @Override
- public boolean next() {
- return currentDelegate.next();
- }
-
- @Override
- public boolean moveToFirst() {
- return currentDelegate.moveToFirst();
- }
-
- @Override
- public boolean moveToLast() {
- return currentDelegate.moveToLast();
- }
-
- @Override
- public boolean moveTo(int index) {
- return currentDelegate.moveTo(index);
- }
-
- @Override
- public void moveToEnd() {
- currentDelegate.moveToEnd();
- }
-
- public boolean previousSnippet() {
- for (int i = index() - 1; i >= 0; i--) {
- if (get(i) instanceof NarrowingHistoryLine) {
- moveTo(i);
- return true;
- }
- }
-
- return false;
- }
-
- public boolean nextSnippet() {
- for (int i = index() + 1; i < size(); i++) {
- if (get(i) instanceof NarrowingHistoryLine) {
- moveTo(i);
- return true;
- }
- }
-
- if (index() < size()) {
- moveToEnd();
- return true;
- }
-
- return false;
- }
-
- private static final String HISTORY_LINE_PREFIX = "HISTORY_LINE_";
- private static final String HISTORY_SNIPPET_START = "HISTORY_SNIPPET";
-
- public final void load() {
- try {
- Set<Integer> snippetsStart = new HashSet<>();
- for (String start : prefs.get(HISTORY_SNIPPET_START, "").split(";")) {
- if (!start.isEmpty())
- snippetsStart.add(Integer.parseInt(start));
- }
- List<String> keys = Stream.of(prefs.keys()).sorted().collect(Collectors.toList());
- NarrowingHistoryLine currentHistoryLine = null;
- int currentLine = 0;
- for (String key : keys) {
- if (!key.startsWith(HISTORY_LINE_PREFIX))
- continue;
- CharSequence line = prefs.get(key, "");
- if (snippetsStart.contains(currentLine)) {
- class PersistentNarrowingHistoryLine extends NarrowingHistoryLine implements PersistentEntryMarker {
- public PersistentNarrowingHistoryLine(CharSequence delegate, int start) {
- super(delegate, start);
- }
- }
- line = currentHistoryLine = new PersistentNarrowingHistoryLine(line, currentLine);
- } else {
- class PersistentLine implements CharSequence, PersistentEntryMarker {
- private final CharSequence delegate;
- public PersistentLine(CharSequence delegate) {
- this.delegate = delegate;
- }
- @Override public int length() {
- return delegate.length();
- }
- @Override public char charAt(int index) {
- return delegate.charAt(index);
- }
- @Override public CharSequence subSequence(int start, int end) {
- return delegate.subSequence(start, end);
- }
- @Override public String toString() {
- return delegate.toString();
- }
- }
- line = new PersistentLine(line);
- }
- if (currentHistoryLine != null)
- currentHistoryLine.span[1] = currentLine;
- currentLine++;
- fullHistory.add(line);
- }
- currentLine = 0;
- } catch (BackingStoreException ex) {
- throw new IllegalStateException(ex);
- }
- }
-
- public void save() {
- try {
- for (String key : prefs.keys()) {
- if (key.startsWith(HISTORY_LINE_PREFIX))
- prefs.remove(key);
- }
- Iterator<Entry> entries = fullHistory.iterator();
- if (entries.hasNext()) {
- int len = (int) Math.ceil(Math.log10(fullHistory.size()+1));
- String format = HISTORY_LINE_PREFIX + "%0" + len + "d";
- StringBuilder snippetStarts = new StringBuilder();
- String snippetStartDelimiter = "";
- while (entries.hasNext()) {
- Entry entry = entries.next();
- prefs.put(String.format(format, entry.index()), entry.value().toString());
- if (entry.value() instanceof NarrowingHistoryLine) {
- snippetStarts.append(snippetStartDelimiter);
- snippetStarts.append(entry.index());
- snippetStartDelimiter = ";";
- }
- }
- prefs.put(HISTORY_SNIPPET_START, snippetStarts.toString());
- }
- } catch (BackingStoreException ex) {
- throw new IllegalStateException(ex);
- }
- }
-
- public List<String> currentSessionEntries() {
- List<String> result = new ArrayList<>();
-
- for (Entry e : fullHistory) {
- if (!(e.value() instanceof PersistentEntryMarker)) {
- result.add(e.value().toString());
- }
- }
-
- return result;
- }
-
- void fullHistoryReplace(String source) {
- fullHistory.replace(source);
- }
-
- private class NarrowingHistoryLine implements CharSequence {
- private final CharSequence delegate;
- private final int[] span;
-
- public NarrowingHistoryLine(CharSequence delegate, int start) {
- this.delegate = delegate;
- this.span = new int[] {start, -1};
- }
-
- @Override
- public int length() {
- return delegate.length();
- }
-
- @Override
- public char charAt(int index) {
- return delegate.charAt(index);
- }
-
- @Override
- public CharSequence subSequence(int start, int end) {
- return delegate.subSequence(start, end);
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
-
- }
-
- private interface PersistentEntryMarker {}
-}
-
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java Thu May 19 19:47:04 2016 +0000
@@ -47,6 +47,9 @@
// Patern for substituted fields within a customized format string
private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}");
+ // Internal field name for truncation length
+ private static final String TRUNCATION_FIELD = "<truncation>";
+
// Current mode
private Mode mode = new Mode("", false); // initial value placeholder during start-up
@@ -103,6 +106,10 @@
return new Setter(messageHandler, at).setFormat();
}
+ public boolean setTruncation(MessageHandler messageHandler, ArgTokenizer at) {
+ return new Setter(messageHandler, at).setTruncation();
+ }
+
public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) {
return new Setter(messageHandler, at).setNewMode();
}
@@ -251,13 +258,42 @@
return sb.toString();
}
+ // Compute the display output given full context and values
String format(FormatCase fc, FormatAction fa, FormatWhen fw,
FormatResolve fr, FormatUnresolved fu, FormatErrors fe,
String name, String type, String value, String unresolved, List<String> errorLines) {
+ // Convert the context into a bit representation used as selectors for store field formats
long bits = bits(fc, fa, fw, fr, fu, fe);
String fname = name==null? "" : name;
String ftype = type==null? "" : type;
- String fvalue = value==null? "" : value;
+ // Compute the representation of value
+ String fvalue;
+ if (value==null) {
+ fvalue = "";
+ } else {
+ // Retrieve the truncation length
+ String truncField = format(TRUNCATION_FIELD, bits);
+ if (truncField.isEmpty()) {
+ // No truncation set, use whole value
+ fvalue = value;
+ } else {
+ // Convert truncation length to int
+ // this is safe since it has been tested before it is set
+ int trunc = Integer.parseUnsignedInt(truncField);
+ if (value.length() > trunc) {
+ if (trunc <= 5) {
+ // Very short truncations have no room for "..."
+ fvalue = value.substring(0, trunc);
+ } else {
+ // Normal truncation, make total length equal truncation length
+ fvalue = value.substring(0, trunc - 4) + " ...";
+ }
+ } else {
+ // Within truncation length, use whole value
+ fvalue = value;
+ }
+ }
+ }
String funresolved = unresolved==null? "" : unresolved;
String errors = errorLines.stream()
.map(el -> String.format(
@@ -564,7 +600,7 @@
return valid;
}
- // For /set newmode <new-mode> [command|quiet [<old-mode>]]
+ // For /set newmode <new-mode> [-command|-quiet [<old-mode>]]
boolean setNewMode() {
String umode = at.next();
if (umode == null) {
@@ -575,8 +611,8 @@
errorat("jshell.err.feedback.expected.mode.name", umode);
valid = false;
}
- String[] fluffOpt = at.next("command", "quiet");
- boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "command".equals(fluffOpt[0]);
+ String[] fluffOpt = at.next("-command", "-quiet");
+ boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "-command".equals(fluffOpt[0]);
if (fluffOpt != null && fluffOpt.length != 1) {
errorat("jshell.err.feedback.command.quiet");
valid = false;
@@ -619,7 +655,32 @@
errorat("jshell.err.feedback.expected.field");
valid = false;
}
- String format = valid? nextFormat() : null;
+ String format = valid ? nextFormat() : null;
+ return installFormat(m, field, format, "/help /set format");
+ }
+
+ // For /set truncation <mode> <length> <selector>...
+ boolean setTruncation() {
+ Mode m = nextMode();
+ String length = at.next();
+ if (length == null) {
+ errorat("jshell.err.truncation.expected.length");
+ valid = false;
+ } else {
+ try {
+ // Assure that integer format is correct
+ Integer.parseUnsignedInt(length);
+ } catch (NumberFormatException ex) {
+ errorat("jshell.err.truncation.length.not.integer", length);
+ valid = false;
+ }
+ }
+ // install length into an internal format field
+ return installFormat(m, TRUNCATION_FIELD, length, "/help /set truncation");
+ }
+
+ // install the format of a field under parsed selectors
+ boolean installFormat(Mode m, String field, String format, String help) {
String slRaw;
List<SelectorList> slList = new ArrayList<>();
while (valid && (slRaw = at.next()) != null) {
@@ -629,8 +690,10 @@
}
if (valid) {
if (slList.isEmpty()) {
+ // No selectors specified, then always the format
m.set(field, ALWAYS, format);
} else {
+ // Set the format of the field for specified selector
slList.stream()
.forEach(sl -> m.set(field,
sl.cases.getSet(), sl.actions.getSet(), sl.whens.getSet(),
@@ -638,7 +701,7 @@
format));
}
} else {
- fluffmsg("jshell.msg.see", "/help /set format");
+ fluffmsg("jshell.msg.see", help);
}
return valid;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java Thu May 19 19:47:04 2016 +0000
@@ -113,7 +113,7 @@
private static final String LINE_SEP = System.getProperty("line.separator");
private static final Pattern LINEBREAK = Pattern.compile("\\R");
private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile(
- "((?<cmd>(all|history|start))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)");
+ "((?<cmd>(-all|-history|-start))(\\z|\\p{javaWhitespace}+))?(?<filename>.*)");
private static final String RECORD_SEPARATOR = "\u241E";
private static final String RB_NAME_PREFIX = "jdk.internal.jshell.tool.resources";
private static final String VERSION_RB_NAME = RB_NAME_PREFIX + ".version";
@@ -879,8 +879,8 @@
}
private static final CompletionProvider EMPTY_COMPLETION_PROVIDER = new FixedCompletionProvider();
- private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("all ", "start ", "history ");
- private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("restore", "quiet");
+ private static final CompletionProvider KEYWORD_COMPLETION_PROVIDER = new FixedCompletionProvider("-all ", "-start ", "-history ");
+ private static final CompletionProvider RELOAD_OPTIONS_COMPLETION_PROVIDER = new FixedCompletionProvider("-restore", "-quiet");
private static final CompletionProvider FILE_COMPLETION_PROVIDER = fileCompletions(p -> true);
private final Map<String, Command> commands = new LinkedHashMap<>();
private void registerCommand(Command cmd) {
@@ -917,11 +917,10 @@
p.getFileName().toString().endsWith(".jar"));
}
- private CompletionProvider editCompletion() {
+ private CompletionProvider snippetCompletion(Supplier<List<? extends Snippet>> snippetsSupplier) {
return (prefix, cursor, anchor) -> {
anchor[0] = 0;
- return state.snippets()
- .stream()
+ return snippetsSupplier.get() .stream()
.flatMap(k -> (k instanceof DeclarationSnippet)
? Stream.of(String.valueOf(k.id()), ((DeclarationSnippet) k).name())
: Stream.of(String.valueOf(k.id())))
@@ -931,11 +930,11 @@
};
}
- private CompletionProvider editKeywordCompletion() {
+ private CompletionProvider snippetKeywordCompletion(Supplier<List<? extends Snippet>> snippetsSupplier) {
return (code, cursor, anchor) -> {
List<Suggestion> result = new ArrayList<>();
result.addAll(KEYWORD_COMPLETION_PROVIDER.completionSuggestions(code, cursor, anchor));
- result.addAll(editCompletion().completionSuggestions(code, cursor, anchor));
+ result.addAll(snippetCompletion(snippetsSupplier).completionSuggestions(code, cursor, anchor));
return result;
};
}
@@ -963,18 +962,51 @@
};
}
+ // Snippet lists
+
+ List<Snippet> allSnippets() {
+ return state.snippets();
+ }
+
+ List<Snippet> dropableSnippets() {
+ return state.snippets().stream()
+ .filter(sn -> state.status(sn).isActive)
+ .collect(toList());
+ }
+
+ List<VarSnippet> allVarSnippets() {
+ return state.snippets().stream()
+ .filter(sn -> sn.kind() == Snippet.Kind.VAR)
+ .map(sn -> (VarSnippet) sn)
+ .collect(toList());
+ }
+
+ List<MethodSnippet> allMethodSnippets() {
+ return state.snippets().stream()
+ .filter(sn -> sn.kind() == Snippet.Kind.METHOD)
+ .map(sn -> (MethodSnippet) sn)
+ .collect(toList());
+ }
+
+ List<TypeDeclSnippet> allTypeSnippets() {
+ return state.snippets().stream()
+ .filter(sn -> sn.kind() == Snippet.Kind.TYPE_DECL)
+ .map(sn -> (TypeDeclSnippet) sn)
+ .collect(toList());
+ }
+
// Table of commands -- with command forms, argument kinds, helpKey message, implementation, ...
{
registerCommand(new Command("/list",
arg -> cmdList(arg),
- editKeywordCompletion()));
+ snippetKeywordCompletion(this::allSnippets)));
registerCommand(new Command("/edit",
arg -> cmdEdit(arg),
- editCompletion()));
+ snippetCompletion(this::allSnippets)));
registerCommand(new Command("/drop",
arg -> cmdDrop(arg),
- editCompletion(),
+ snippetCompletion(this::dropableSnippets),
CommandKind.REPLAY));
registerCommand(new Command("/save",
arg -> cmdSave(arg),
@@ -983,14 +1015,14 @@
arg -> cmdOpen(arg),
FILE_COMPLETION_PROVIDER));
registerCommand(new Command("/vars",
- arg -> cmdVars(),
- EMPTY_COMPLETION_PROVIDER));
+ arg -> cmdVars(arg),
+ snippetKeywordCompletion(this::allVarSnippets)));
registerCommand(new Command("/methods",
- arg -> cmdMethods(),
- EMPTY_COMPLETION_PROVIDER));
- registerCommand(new Command("/classes",
- arg -> cmdClasses(),
- EMPTY_COMPLETION_PROVIDER));
+ arg -> cmdMethods(arg),
+ snippetKeywordCompletion(this::allMethodSnippets)));
+ registerCommand(new Command("/types",
+ arg -> cmdTypes(arg),
+ snippetKeywordCompletion(this::allTypeSnippets)));
registerCommand(new Command("/imports",
arg -> cmdImports(),
EMPTY_COMPLETION_PROVIDER));
@@ -1019,7 +1051,7 @@
EMPTY_COMPLETION_PROVIDER));
registerCommand(new Command("/set",
arg -> cmdSet(arg),
- new FixedCompletionProvider("format", "feedback", "prompt", "newmode", "start", "editor")));
+ new FixedCompletionProvider(SET_SUBCOMMANDS)));
registerCommand(new Command("/?",
"help.quest",
arg -> cmdHelp(arg),
@@ -1094,7 +1126,7 @@
// --- Command implementations ---
private static final String[] SET_SUBCOMMANDS = new String[]{
- "format", "feedback", "newmode", "prompt", "editor", "start"};
+ "format", "truncation", "feedback", "newmode", "prompt", "editor", "start"};
final boolean cmdSet(String arg) {
ArgTokenizer at = new ArgTokenizer("/set ", arg.trim());
@@ -1105,6 +1137,8 @@
switch (which) {
case "format":
return feedback.setFormat(this, at);
+ case "truncation":
+ return feedback.setTruncation(this, at);
case "feedback":
return feedback.setFeedback(this, at);
case "newmode":
@@ -1310,7 +1344,7 @@
/**
* Avoid parameterized varargs possible heap pollution warning.
*/
- private interface SnippetPredicate extends Predicate<Snippet> { }
+ private interface SnippetPredicate<T extends Snippet> extends Predicate<T> { }
/**
* Apply filters to a stream until one that is non-empty is found.
@@ -1320,10 +1354,11 @@
* @param filters Filters to attempt
* @return The non-empty filtered Stream, or null
*/
- private static Stream<Snippet> nonEmptyStream(Supplier<Stream<Snippet>> supplier,
- SnippetPredicate... filters) {
- for (SnippetPredicate filt : filters) {
- Iterator<Snippet> iterator = supplier.get().filter(filt).iterator();
+ @SafeVarargs
+ private static <T extends Snippet> Stream<T> nonEmptyStream(Supplier<Stream<T>> supplier,
+ SnippetPredicate<T>... filters) {
+ for (SnippetPredicate<T> filt : filters) {
+ Iterator<T> iterator = supplier.get().filter(filt).iterator();
if (iterator.hasNext()) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}
@@ -1352,24 +1387,40 @@
* Convert a user argument to a Stream of snippets referenced by that argument
* (or lack of argument).
*
- * @param arg The user's argument to the command, maybe be the empty string
+ * @param snippets the base list of possible snippets
+ * @param arg the user's argument to the command, maybe be the empty string
+ * @param allowAll if true, allow the use of '-all' and '-start'
* @return a Stream of referenced snippets or null if no matches to specific arg
*/
- private Stream<Snippet> argToSnippets(String arg, boolean allowAll) {
- List<Snippet> snippets = state.snippets();
- if (allowAll && arg.equals("all")) {
+ private <T extends Snippet> Stream<T> argToSnippets(List<T> snippets, String arg, boolean allowAll) {
+ return argToSnippets(snippets, this::mainActive, arg, allowAll);
+ }
+
+ /**
+ * Convert a user argument to a Stream of snippets referenced by that argument
+ * (or lack of argument).
+ *
+ * @param snippets the base list of possible snippets
+ * @param defFilter the filter to apply to the arguments if no argument
+ * @param arg the user's argument to the command, maybe be the empty string
+ * @param allowAll if true, allow the use of '-all' and '-start'
+ * @return a Stream of referenced snippets or null if no matches to specific arg
+ */
+ private <T extends Snippet> Stream<T> argToSnippets(List<T> snippets,
+ Predicate<Snippet> defFilter, String arg, boolean allowAll) {
+ if (allowAll && arg.equals("-all")) {
// all snippets including start-up, failed, and overwritten
return snippets.stream();
- } else if (allowAll && arg.equals("start")) {
+ } else if (allowAll && arg.equals("-start")) {
// start-up snippets
return snippets.stream()
.filter(this::inStartUp);
} else if (arg.isEmpty()) {
// Default is all active user snippets
return snippets.stream()
- .filter(this::mainActive);
+ .filter(defFilter);
} else {
- Stream<Snippet> result =
+ Stream<T> result =
nonEmptyStream(
() -> snippets.stream(),
// look for active user declarations matching the name
@@ -1383,12 +1434,39 @@
}
}
+ /**
+ * Convert a user argument to a Stream of snippets referenced by that
+ * argument, printing an informative message if no matches. Allow '-all' and
+ * '-start'.
+ *
+ * @param snippets the base list of possible snippets
+ * @param defFilter the filter to apply to the arguments if no argument
+ * @param arg the user's argument to the command, maybe be the empty string
+ * @param cmd the name of the command (for use in a help message
+ * @return a Stream of referenced snippets or null if no matches to specific
+ * arg
+ */
+ private <T extends Snippet> Stream<T> argToSnippetsWithMessage(List<T> snippets,
+ Predicate<Snippet> defFilter, String arg, String cmd) {
+ Stream<T> stream = argToSnippets(snippets, defFilter, arg, true);
+ if (stream == null) {
+ errormsg("jshell.err.def.or.id.not.found", arg);
+ // Check if there are any definitions at all
+ if (argToSnippets(snippets, "", false).iterator().hasNext()) {
+ fluffmsg("jshell.msg.try.command.without.args", cmd);
+ } else {
+ hardmsg("jshell.msg.no.active");
+ }
+ }
+ return stream;
+ }
+
private boolean cmdDrop(String arg) {
if (arg.isEmpty()) {
errormsg("jshell.err.drop.arg");
return false;
}
- Stream<Snippet> stream = argToSnippets(arg, false);
+ Stream<Snippet> stream = argToSnippets(dropableSnippets(), arg, false);
if (stream == null) {
errormsg("jshell.err.def.or.id.not.found", arg);
fluffmsg("jshell.msg.see.classes.etc");
@@ -1415,10 +1493,9 @@
}
private boolean cmdEdit(String arg) {
- Stream<Snippet> stream = argToSnippets(arg, true);
+ Stream<Snippet> stream = argToSnippetsWithMessage(state.snippets(),
+ this::mainActive, arg, "/edit");
if (stream == null) {
- errormsg("jshell.err.def.or.id.not.found", arg);
- fluffmsg("jshell.msg.see.classes.etc");
return false;
}
Set<String> srcSet = new LinkedHashSet<>();
@@ -1518,18 +1595,12 @@
}
private boolean cmdList(String arg) {
- if (arg.equals("history")) {
+ if (arg.equals("-history")) {
return cmdHistory();
}
- Stream<Snippet> stream = argToSnippets(arg, true);
+ Stream<Snippet> stream = argToSnippetsWithMessage(state.snippets(),
+ this::mainActive, arg, "/list");
if (stream == null) {
- errormsg("jshell.err.def.or.id.not.found", arg);
- // Check if there are any definitions at all
- if (argToSnippets("", false).iterator().hasNext()) {
- fluffmsg("jshell.msg.try.list.without.args");
- } else {
- hardmsg("jshell.msg.no.active");
- }
return false;
}
@@ -1601,13 +1672,13 @@
Iterable<String> history = replayableHistory;
boolean echo = true;
if (arg.length() > 0) {
- if ("restore".startsWith(arg)) {
+ if ("-restore".startsWith(arg)) {
if (replayableHistoryPrevious == null) {
errormsg("jshell.err.reload.no.previous");
return false;
}
history = replayableHistoryPrevious;
- } else if ("quiet".startsWith(arg)) {
+ } else if ("-quiet".startsWith(arg)) {
echo = false;
} else {
errormsg("jshell.err.arg", "/reload", arg);
@@ -1634,13 +1705,13 @@
boolean saveStart = false;
String cmd = mat.group("cmd");
if (cmd != null) switch (cmd) {
- case "all":
- saveAll = "all";
+ case "-all":
+ saveAll = "-all";
break;
- case "history":
+ case "-history":
useHistory = true;
break;
- case "start":
+ case "-start":
saveStart = true;
break;
}
@@ -1660,7 +1731,7 @@
} else if (saveStart) {
writer.append(DEFAULT_STARTUP);
} else {
- Stream<Snippet> stream = argToSnippets(saveAll, true);
+ Stream<Snippet> stream = argToSnippets(state.snippets(), saveAll, true);
if (stream != null) {
for (Snippet sn : stream.collect(toList())) {
writer.write(sn.source());
@@ -1678,25 +1749,42 @@
return true;
}
- private boolean cmdVars() {
- for (VarSnippet vk : state.variables()) {
+ private boolean cmdVars(String arg) {
+ Stream<VarSnippet> stream = argToSnippetsWithMessage(allVarSnippets(),
+ this::isActive, arg, "/vars");
+ if (stream == null) {
+ return false;
+ }
+ stream.forEachOrdered(vk ->
+ {
String val = state.status(vk) == Status.VALID
? state.varValue(vk)
: "jshell.msg.vars.not.active";
hard(" %s %s = %s", vk.typeName(), vk.name(), val);
- }
+ });
return true;
}
- private boolean cmdMethods() {
- for (MethodSnippet mk : state.methods()) {
- hard(" %s %s", mk.name(), mk.signature());
+ private boolean cmdMethods(String arg) {
+ Stream<MethodSnippet> stream = argToSnippetsWithMessage(allMethodSnippets(),
+ this::isActive, arg, "/methods");
+ if (stream == null) {
+ return false;
}
+ stream.forEachOrdered(mk
+ -> hard(" %s %s", mk.name(), mk.signature())
+ );
return true;
}
- private boolean cmdClasses() {
- for (TypeDeclSnippet ck : state.types()) {
+ private boolean cmdTypes(String arg) {
+ Stream<TypeDeclSnippet> stream = argToSnippetsWithMessage(allTypeSnippets(),
+ this::isActive, arg, "/types");
+ if (stream == null) {
+ return false;
+ }
+ stream.forEachOrdered(ck
+ -> {
String kind;
switch (ck.subKind()) {
case INTERFACE_SUBKIND:
@@ -1717,7 +1805,7 @@
break;
}
hard(" %s %s", kind, ck.name());
- }
+ });
return true;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu May 19 17:48:04 2016 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties Thu May 19 19:47:04 2016 +0000
@@ -34,11 +34,11 @@
jshell.msg.terminated =\
State engine terminated.\n\
-Restore definitions with: /reload restore
+Restore definitions with: /reload -restore
jshell.msg.use.one.of = Use one of: {0}
-jshell.err.def.or.id.not.found = No definition or id found named: {0}
-jshell.msg.see.classes.etc = See /classes, /methods, /vars, or /list
+jshell.err.def.or.id.not.found = No applicable definition or id found named: {0}
+jshell.msg.see.classes.etc = See /types, /methods, /vars, or /list
jshell.err.arg = Invalid ''{0}'' argument: {1}
jshell.msg.see = See {0} for help.
@@ -57,7 +57,7 @@
jshell.err.cant.launch.editor = Cannot launch editor -- unexpected exception: {0}
jshell.msg.try.set.editor = Try /set editor to use external editor.
-jshell.msg.try.list.without.args = Try ''/list'' without arguments.
+jshell.msg.try.command.without.args = Try ''{0}'' without arguments.
jshell.msg.no.active = There are no active definitions.
jshell.msg.resetting = Resetting...
@@ -102,7 +102,7 @@
jshell.err.feedback.expected.new.feedback.mode = Expected new feedback mode -- {0}
jshell.err.feedback.expected.mode.name = Expected a new feedback mode name. ''{0}'' is a known feedback mode -- {1}
-jshell.err.feedback.command.quiet = Specify either ''command'' or ''quiet'' -- {0}
+jshell.err.feedback.command.quiet = Specify either ''-command'' or ''-quiet'' -- {0}
jshell.err.feedback.expected.field = Expected field name missing -- {0}
jshell.err.feedback.expected.mode = Expected a feedback mode -- {0}
jshell.err.feedback.does.not.match.mode = Does not match any current feedback mode: {0} -- {1}
@@ -117,6 +117,9 @@
jshell.msg.feedback.mode = Feedback mode: {0}
jshell.msg.feedback.mode.following = The feedback mode should be one of the following:
+jshell.err.truncation.expected.length = Expected truncation length -- {0}
+jshell.err.truncation.length.not.integer = Truncation length must be an integer: {0} -- {1}
+
jshell.console.see.more = <press tab to see more>
jshell.console.do.nothing = Do nothing
jshell.console.choice = Choice: \
@@ -148,15 +151,15 @@
\ -version Version information\n
help.list.summary = list the source you have typed
-help.list.args = [all|start|<name or id>]
+help.list.args = [<name or id>|-all|-start]
help.list =\
Show the source of snippets, prefaced with the snippet id.\n\
\n\
/list\n\t\
List the currently active snippets of code that you typed or read with /open\n\n\
-/list start\n\t\
+/list -start\n\t\
List the automatically evaluated start-up snippets\n\n\
-/list all\n\t\
+/list -all\n\t\
List all snippets including failed, overwritten, dropped, and start-up\n\n\
/list <name>\n\t\
List snippets with the specified name (preference for active snippets)\n\n\
@@ -188,18 +191,18 @@
Drop the snippet with the specified snippet id
help.save.summary = Save snippet source to a file.
-help.save.args = [all|history|start] <file>
+help.save.args = [-all|-history|-start] <file>
help.save =\
Save the specified snippets and/or commands to the specified file.\n\
\n\
/save <file>\n\t\
Save the source of current active snippets to the file.\n\n\
-/save all <file>\n\t\
+/save -all <file>\n\t\
Save the source of all snippets to the file.\n\t\
Includes source including overwritten, failed, and start-up code.\n\n\
-/save history <file>\n\t\
+/save -history <file>\n\t\
Save the sequential history of all commands and snippets entered since jshell was launched.\n\n\
-/save start <file>\n\t\
+/save -start <file>\n\t\
Save the default start-up definitions to the file.
help.open.summary = open a file as source input
@@ -211,19 +214,52 @@
Read the specified file as jshell input.
help.vars.summary = list the declared variables and their values
-help.vars.args =
+help.vars.args = [<name or id>|-all|-start]
help.vars =\
-List the type, name, and value of the current active jshell variables.
+List the type, name, and value of jshell variables.\n\
+\n\
+/vars\n\t\
+ List the type, name, and value of the current active jshell variables\n\n\
+/vars <name>\n\t\
+ List jshell variables with the specified name (preference for active variables)\n\n\
+/vars <id>\n\t\
+ List the jshell variable with the specified snippet id\n\n\
+/vars -start\n\t\
+ List the automatically added start-up jshell variables\n\n\
+/vars -all\n\t\
+ List all jshell variables including failed, overwritten, dropped, and start-up
help.methods.summary = list the declared methods and their signatures
-help.methods.args =
+help.methods.args = [<name or id>|-all|-start]
help.methods =\
-List the name, parameter types, and return type of the current active jshell methods.
+List the name, parameter types, and return type of jshell methods.\n\
+\n\
+/methods\n\t\
+ List the name, parameter types, and return type of the current active jshell methods\n\n\
+/methods <name>\n\t\
+ List jshell methods with the specified name (preference for active methods)\n\n\
+/methods <id>\n\t\
+ List the jshell method with the specified snippet id\n\n\
+/methods -start\n\t\
+ List the automatically added start-up jshell methods\n\n\
+/methods -all\n\t\
+ List all snippets including failed, overwritten, dropped, and start-up
-help.classes.summary = list the declared classes
-help.classes.args =
-help.classes =\
-List the current active jshell classes, interfaces, and enums.
+help.types.summary = list the declared types
+help.types.args =[<name or id>|-all|-start]
+help.types =\
+List jshell classes, interfaces, and enums.\n\
+\n\
+/types\n\t\
+ List the current active jshell classes, interfaces, and enums.\n\n\
+/types <name>\n\t\
+ List jshell types with the specified name (preference for active types)\n\n\
+/types <id>\n\t\
+ List the jshell type with the specified snippet id\n\n\
+/types -start\n\t\
+ List the automatically added start-up jshell types\n\n\
+/types -all\n\t\
+ List all jshell types including failed, overwritten, dropped, and start-up
help.imports.summary = list the imported items
help.imports.args =
@@ -247,8 +283,8 @@
Tool settings are maintained, as set with: /set ...\n\
Save any work before using this command
-help.reload.summary = reset and replay relevant history -- current or previous (restore)
-help.reload.args = [restore] [quiet]
+help.reload.summary = reset and replay relevant history -- current or previous (-restore)
+help.reload.args = [-restore] [-quiet]
help.reload =\
Reset the jshell tool code and execution state then replay each\n\
jshell valid command and valid snippet in the order they were entered.\n\
@@ -257,13 +293,13 @@
Reset and replay the valid history since jshell was entered, or\n\t\
a /reset, or /reload command was executed -- whichever is most\n\t\
recent.\n\n\
-/reload restore\n\t\
+/reload -restore\n\t\
Reset and replay the valid history between the previous and most\n\t\
recent time that jshell was entered, or a /reset, or /reload\n\t\
command was executed. This can thus be used to restore a previous\n\t\
jshell tool sesson.\n\n\
-/reload [restore] quiet\n\t\
- With the 'quiet' argument the replay is not shown. Errors will display.
+/reload [-restore] -quiet\n\t\
+ With the '-quiet' argument the replay is not shown. Errors will display.
help.classpath.summary = add a path to the classpath
help.classpath.args = <path>
@@ -301,7 +337,7 @@
Display information about the specified help subject. Example: /help intro
help.set.summary = set jshell configuration information
-help.set.args = editor|start|feedback|newmode|prompt|format ...
+help.set.args = editor|start|feedback|newmode|prompt|truncation|format ...
help.set =\
Set jshell configuration information, including:\n\
the external editor to use, the start-up definitions to use, a new feedback mode,\n\
@@ -314,10 +350,12 @@
The contents of the specified <file> become the default start-up snippets and commands.\n\n\
/set feedback <mode>\n\t\
Set the feedback mode describing displayed feedback for entered snippets and commands.\n\n\
-/set newmode <new-mode> [command|quiet [<old-mode>]]\n\t\
+/set newmode <new-mode> [-command|-quiet [<old-mode>]]\n\t\
Create a user-defined feedback mode, optionally copying from an existing mode.\n\n\
/set prompt <mode> "<prompt>" "<continuation-prompt>"\n\t\
Set the displayed prompts for a given feedback mode.\n\n\
+/set truncation <mode> <length> <selector>...\n\t\
+ Set the maximum length of a displayed value\n\t\
/set format <mode> <field> "<format>" <selector>...\n\t\
Configure a feedback mode by setting the format of a field when the selector matchs.\n\n\
To get more information about one of these forms, use /help with the form specified.\n\
@@ -462,6 +500,37 @@
/set format myformat display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update\n\n\
Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n
+help.set.truncation = \
+Set the max length a displayed value.\n\
+\n\t\
+/set truncation <mode> <length> <selector>...\n\
+\n\
+Where <mode> is the name of a previously defined feedback mode -- see '/help /set newmode'.\n\
+Where <length> is an unsigned integer representing a maximum length.\n\
+Where <format> is a quoted string which will be the value of the field if one of\n\
+Where <selector> is only needed if you wish to fine-tune value truncation length\n\
+by context, <selector> is the context in which the truncation is applied.\n\
+The structure of selector is a hyphen separated list of selector kind lists.\n\
+A selector kind list is a comma separated list of values of one selector kind.\n\
+A selector matches if each selector kind list matches; A selector kind list\n\
+matches if one of the values matches.\n\n\
+Below are the relevant selector kinds for truncation.\n\n\
+The case selector kind describes the kind of snippet. The values are:\n\t\
+ vardecl -- variable declaration without init\n\t\
+ varinit -- variable declaration with init\n\t\
+ expression -- expression -- note: {name}==scratch-variable-name\n\t\
+ varvalue -- variable value expression\n\t\
+ assignment -- assign variable\n\t\
+The action selector kind describes what happened to the snippet. The values are:\n\t\
+ added -- snippet has been added\n\t\
+ modified -- an existing snippet has been modified\n\t\
+ replaced -- an existing snippet has been replaced with a new snippet\n\
+Examples:\n\t\
+/set trunc mymode 80\n\t\
+/set truncation mymode 45 expression\n\t\
+/set truncation mymode 0 vardecl-modified,replaced\n\n\
+Note that subsequent selectors for a field may overwrite some or all of previous used selectors -- last one wins\n
+
help.set.feedback = \
Set the feedback mode describing displayed feedback for entered snippets and commands.\n\
\n\t\
@@ -475,12 +544,12 @@
help.set.newmode = \
Create a user-defined feedback mode, optionally copying from an existing mode.\n\
\n\t\
-/set newmode <new-mode> [command|quiet [<old-mode>]]\n\
+/set newmode <new-mode> [-command|-quiet [<old-mode>]]\n\
\n\
Where <new-mode> is the name of a mode you wish to create.\n\
Where <old-mode> is the name of a previously defined feedback mode.\n\
If <old-mode> is present, its settings are copied to the new mode.\n\
-'command' vs 'quiet' determines if informative/verifying command feedback is displayed.\n\
+'-command' vs '-quiet' determines if informative/verifying command feedback is displayed.\n\
\n\
Once the new mode is created, use '/set format' and '/set prompt' to configure it.\n\
Use '/set feedback' to use the new mode.\n\
@@ -514,7 +583,7 @@
which are run when the jshell tool is started or reset.
startup.feedback = \
-/set newmode verbose command \n\
+/set newmode verbose -command \n\
\n\
/set prompt verbose '\\njshell> ' ' ...> ' \n\
\n\
@@ -578,11 +647,14 @@
/set format verbose display '{pre}attempted to use {typeKind} {name}{resolve}{post}' used-class,interface,enum,annotation \n\
/set format verbose display '{pre}attempted to call method {name}({type}){resolve}{post}' used-method \n\
\n\
-/set newmode normal command verbose \n\
+/set truncation verbose 80\n\
+/set truncation verbose 500 varvalue\n\
+\n\
+/set newmode normal -command verbose \n\
/set format normal display '' added,modified,replaced,overwrote,dropped-update \n\
/set format normal display '{pre}{action} variable {name}, reset to null{post}' replaced-vardecl,varinit-ok-update \n\
/set format normal display '{result}' added,modified,replaced-expression,varvalue,assignment,varinit,vardecl-ok-primary \n\
-/set newmode concise quiet normal \n\
+/set newmode concise -quiet normal \n\
\n\
/set prompt concise 'jshell> ' ' ...> ' \n\
\n\
@@ -590,7 +662,7 @@
\n\
/set feedback normal \n\
\n\
-/set newmode silent quiet \n\
+/set newmode silent -quiet \n\
/set prompt silent '-> ' '>> ' \n\
/set format silent pre '| ' \n\
/set format silent post '%n' \n\
--- a/langtools/test/ProblemList.txt Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/ProblemList.txt Thu May 19 19:47:04 2016 +0000
@@ -66,7 +66,6 @@
# javac
tools/javac/Paths/AbsolutePathTest.java 8055768 generic-all ToolBox does not close opened files
-tools/javac/Paths/MineField.sh 8149599 generic-all needs rewrite
tools/javac/annotations/typeAnnotations/failures/CantAnnotatePackages.java 8057679 generic-all clarify error messages trying to annotate scoping
tools/javac/annotations/typeAnnotations/failures/CantAnnotateScoping.java 8057679 generic-all clarify error messages trying to annotate scoping
tools/javac/annotations/typeAnnotations/failures/CantAnnotateStaticClass2.java 8057679 generic-all clarify error messages trying to annotate scoping
@@ -95,6 +94,3 @@
#
# jdeps
-tools/jdeps/modules/GenModuleInfo.java 8152502,8153481 generic-all fails to clean up files, java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
-tools/jdeps/modules/ModuleTest.java 8153481 generic-all java.util.HashMap$Node cannot be cast to java.util.HashMap$TreeNode
-
--- a/langtools/test/jdk/jshell/CommandCompletionTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/CommandCompletionTest.java Thu May 19 19:47:04 2016 +0000
@@ -53,18 +53,18 @@
public void testCommand() {
assertCompletion("/deb|", false);
- assertCompletion("/c|", false, "/classes ", "/classpath ");
+ assertCompletion("/re|", false, "/reload ", "/reset ");
assertCompletion("/h|", false, "/help ", "/history ");
}
public void testList() {
test(false, new String[] {"-nostartup"},
a -> assertCompletion(a, "/l|", false, "/list "),
- a -> assertCompletion(a, "/list |", false, "all ", "history ", "start "),
- a -> assertCompletion(a, "/list h|", false, "history "),
+ a -> assertCompletion(a, "/list |", false, "-all ", "-history ", "-start "),
+ a -> assertCompletion(a, "/list -h|", false, "-history "),
a -> assertCompletion(a, "/list q|", false),
a -> assertVariable(a, "int", "xray"),
- a -> assertCompletion(a, "/list |", false, "1", "all ", "history ", "start ", "xray"),
+ a -> assertCompletion(a, "/list |", false, "-all ", "-history ", "-start ", "1", "xray"),
a -> assertCompletion(a, "/list x|", false, "xray")
);
}
@@ -108,7 +108,7 @@
Compiler compiler = new Compiler();
assertCompletion("/s|", false, "/save ", "/set ");
List<String> p1 = listFiles(Paths.get(""));
- Collections.addAll(p1, "all ", "history ", "start ");
+ Collections.addAll(p1, "-all ", "-history ", "-start ");
FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString()));
Collections.sort(p1);
assertCompletion("/save |", false, p1.toArray(new String[p1.size()]));
@@ -116,7 +116,7 @@
List<String> p2 = listFiles(classDir);
assertCompletion("/save " + classDir + "/|",
false, p2.toArray(new String[p2.size()]));
- assertCompletion("/save all " + classDir + "/|",
+ assertCompletion("/save -all " + classDir + "/|",
false, p2.toArray(new String[p2.size()]));
}
--- a/langtools/test/jdk/jshell/EditorTestBase.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/EditorTestBase.java Thu May 19 19:47:04 2016 +0000
@@ -142,7 +142,7 @@
exit();
loadClass(true, "enum A {}", "enum", "A");
}),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses())
+ a -> assertCommandCheckOutput(a, "/types", assertClasses())
);
}
@@ -161,7 +161,7 @@
exit();
loadClass(true, "enum A {}", "enum", "A");
}),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses())
+ a -> assertCommandCheckOutput(a, "/types", assertClasses())
);
}
--- a/langtools/test/jdk/jshell/HistoryTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/HistoryTest.java Thu May 19 19:47:04 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -24,152 +24,64 @@
/*
* @test
* @summary Test Completion
- * @modules jdk.jshell/jdk.internal.jshell.tool
- * jdk.internal.le/jdk.internal.jline.console.history
+ * @modules jdk.internal.le/jdk.internal.jline.extra
+ * jdk.jshell/jdk.internal.jshell.tool
* @build HistoryTest
* @run testng HistoryTest
*/
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.prefs.AbstractPreferences;
-import java.util.prefs.BackingStoreException;
-import jdk.internal.jline.console.history.MemoryHistory;
-
-import jdk.jshell.JShell;
-import jdk.jshell.SourceCodeAnalysis;
-import jdk.jshell.SourceCodeAnalysis.CompletionInfo;
+import java.lang.reflect.Field;
+import jdk.internal.jline.extra.EditingHistory;
import org.testng.annotations.Test;
-import jdk.internal.jshell.tool.EditingHistory;
-
import static org.testng.Assert.*;
@Test
-public class HistoryTest {
+public class HistoryTest extends ReplToolTesting {
public void testHistory() {
- JShell eval = JShell.builder()
- .in(new ByteArrayInputStream(new byte[0]))
- .out(new PrintStream(new ByteArrayOutputStream()))
- .err(new PrintStream(new ByteArrayOutputStream()))
- .build();
- SourceCodeAnalysis analysis = eval.sourceCodeAnalysis();
- MemoryPreferences prefs = new MemoryPreferences(null, "");
- EditingHistory history = new EditingHistory(prefs) {
- @Override protected CompletionInfo analyzeCompletion(String input) {
- return analysis.analyzeCompletion(input);
- }
- };
- history.add("void test() {");
- history.add(" System.err.println(1);");
- history.add("}");
- history.add("/exit");
-
- previousAndAssert(history, "/exit");
-
- history.previous(); history.previous(); history.previous();
-
- history.add("void test() { /*changed*/");
-
- previousAndAssert(history, "}");
- previousAndAssert(history, " System.err.println(1);");
- previousAndAssert(history, "void test() {");
-
- assertFalse(history.previous());
-
- nextAndAssert(history, " System.err.println(1);");
- nextAndAssert(history, "}");
- nextAndAssert(history, "");
-
- history.add(" System.err.println(2);");
- history.add("} /*changed*/");
-
- assertEquals(history.size(), 7);
-
- history.save();
-
- history = new EditingHistory(prefs) {
- @Override protected CompletionInfo analyzeCompletion(String input) {
- return analysis.analyzeCompletion(input);
- }
- };
-
- previousSnippetAndAssert(history, "void test() { /*changed*/");
- previousSnippetAndAssert(history, "/exit");
- previousSnippetAndAssert(history, "void test() {");
-
- assertFalse(history.previousSnippet());
-
- nextSnippetAndAssert(history, "/exit");
- nextSnippetAndAssert(history, "void test() { /*changed*/");
- nextSnippetAndAssert(history, "");
-
- assertFalse(history.nextSnippet());
-
- history.add("{");
- history.add("}");
-
- history.save();
-
- history = new EditingHistory(prefs) {
- @Override protected CompletionInfo analyzeCompletion(String input) {
- return analysis.analyzeCompletion(input);
- }
- };
-
- previousSnippetAndAssert(history, "{");
- previousSnippetAndAssert(history, "void test() { /*changed*/");
- previousSnippetAndAssert(history, "/exit");
- previousSnippetAndAssert(history, "void test() {");
-
- while (history.next());
-
- history.add("/*current1*/");
- history.add("/*current2*/");
- history.add("/*current3*/");
-
- assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/"));
-
- history.remove(0);
-
- assertEquals(history.currentSessionEntries(), Arrays.asList("/*current1*/", "/*current2*/", "/*current3*/"));
-
- while (history.size() > 2)
- history.remove(0);
-
- assertEquals(history.currentSessionEntries(), Arrays.asList("/*current2*/", "/*current3*/"));
-
- for (int i = 0; i < MemoryHistory.DEFAULT_MAX_SIZE * 2; i++) {
- history.add("/exit");
- }
-
- history.add("void test() { /*after full*/");
- history.add(" System.err.println(1);");
- history.add("}");
-
- previousSnippetAndAssert(history, "void test() { /*after full*/");
+ test(
+ a -> {if (!a) setCommandInput("void test() {\n");},
+ a -> {if (!a) setCommandInput(" System.err.println(1);\n");},
+ a -> {if (!a) setCommandInput(" System.err.println(1);\n");},
+ a -> {assertCommand(a, "} //test", "| created method test()");},
+ a -> {
+ if (!a) {
+ try {
+ previousAndAssert(getHistory(), "} //test");
+ previousSnippetAndAssert(getHistory(), "void test() {");
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ assertCommand(a, "int dummy;", "dummy ==> 0");
+ });
+ test(
+ a -> {if (!a) setCommandInput("void test2() {\n");},
+ a -> {assertCommand(a, "} //test2", "| created method test2()");},
+ a -> {
+ if (!a) {
+ try {
+ previousAndAssert(getHistory(), "} //test2");
+ previousSnippetAndAssert(getHistory(), "void test2() {");
+ previousSnippetAndAssert(getHistory(), "/debug 0"); //added by test framework
+ previousSnippetAndAssert(getHistory(), "/exit");
+ previousSnippetAndAssert(getHistory(), "int dummy;");
+ previousSnippetAndAssert(getHistory(), "void test() {");
+ } catch (Exception ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
+ assertCommand(a, "int dummy;", "dummy ==> 0");
+ });
}
- public void testSaveOneHistory() {
- JShell eval = JShell.builder()
- .in(new ByteArrayInputStream(new byte[0]))
- .out(new PrintStream(new ByteArrayOutputStream()))
- .err(new PrintStream(new ByteArrayOutputStream()))
- .build();
- SourceCodeAnalysis analysis = eval.sourceCodeAnalysis();
- MemoryPreferences prefs = new MemoryPreferences(null, "");
- EditingHistory history = new EditingHistory(prefs) {
- @Override protected CompletionInfo analyzeCompletion(String input) {
- return analysis.analyzeCompletion(input);
- }
- };
-
- history.add("first");
- history.save();
+ private EditingHistory getHistory() throws Exception {
+ Field input = repl.getClass().getDeclaredField("input");
+ input.setAccessible(true);
+ Object console = input.get(repl);
+ Field history = console.getClass().getDeclaredField("history");
+ history.setAccessible(true);
+ return (EditingHistory) history.get(console);
}
private void previousAndAssert(EditingHistory history, String expected) {
@@ -177,71 +89,9 @@
assertEquals(history.current().toString(), expected);
}
- private void nextAndAssert(EditingHistory history, String expected) {
- assertTrue(history.next());
- assertEquals(history.current().toString(), expected);
- }
-
private void previousSnippetAndAssert(EditingHistory history, String expected) {
assertTrue(history.previousSnippet());
assertEquals(history.current().toString(), expected);
}
- private void nextSnippetAndAssert(EditingHistory history, String expected) {
- assertTrue(history.nextSnippet());
- assertEquals(history.current().toString(), expected);
- }
-
- private static final class MemoryPreferences extends AbstractPreferences {
-
- private final Map<String, String> key2Value = new HashMap<>();
- private final Map<String, MemoryPreferences> key2SubNode = new HashMap<>();
-
- public MemoryPreferences(AbstractPreferences parent, String name) {
- super(parent, name);
- }
-
- @Override
- protected void putSpi(String key, String value) {
- key2Value.put(key, value);
- }
-
- @Override
- protected String getSpi(String key) {
- return key2Value.get(key);
- }
-
- @Override
- protected void removeSpi(String key) {
- key2Value.remove(key);
- }
-
- @Override
- protected void removeNodeSpi() throws BackingStoreException {
- ((MemoryPreferences) parent()).key2SubNode.remove(name());
- }
-
- @Override
- protected String[] keysSpi() throws BackingStoreException {
- return key2Value.keySet().toArray(new String[key2Value.size()]);
- }
-
- @Override
- protected String[] childrenNamesSpi() throws BackingStoreException {
- return key2SubNode.keySet().toArray(new String[key2SubNode.size()]);
- }
-
- @Override
- protected AbstractPreferences childSpi(String name) {
- return key2SubNode.computeIfAbsent(name, n -> new MemoryPreferences(this, n));
- }
-
- @Override
- protected void syncSpi() throws BackingStoreException {}
-
- @Override
- protected void flushSpi() throws BackingStoreException {}
-
- }
-
}
--- a/langtools/test/jdk/jshell/ReplToolTesting.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ReplToolTesting.java Thu May 19 19:47:04 2016 +0000
@@ -70,6 +70,9 @@
new MethodInfo("void printf(String format, Object... args) { System.out.printf(format, args); }",
"(String,Object...)void", "printf"))
.collect(toList());
+ final static List<String> START_UP_CMD_METHOD = Stream.of(
+ "| printf (String,Object...)void")
+ .collect(toList());
final static List<String> START_UP = Collections.unmodifiableList(
Stream.concat(START_UP_IMPORTS.stream(), START_UP_METHODS.stream())
.map(s -> s.getSource())
--- a/langtools/test/jdk/jshell/ToolBasicTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java Thu May 19 19:47:04 2016 +0000
@@ -118,9 +118,9 @@
(a) -> assertCommand(a, "class A {" + s, ""),
interrupt,
(a) -> assertCommand(a, "class A {}\u0003", ""),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertClass(a, "interface A {}", "interface", "A"),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertCommand(a, "import java.util.stream." + s, ""),
interrupt,
(a) -> assertCommand(a, "import java.util.stream.\u0003", ""),
@@ -338,13 +338,13 @@
(a) -> assertMethod(a, "void f() { }", "()void", "f"),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertClass(a, "class A { }", "class", "A"),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports()),
(a) -> assertReset(a, "/reset"),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertCommandCheckOutput(a, "/imports", assertImports())
);
}
@@ -369,7 +369,7 @@
loadClass(a, "class A { public String toString() { return \"A\"; } }",
"class", "A");
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
- assertCommandCheckOutput(a, "/classes", assertClasses());
+ assertCommandCheckOutput(a, "/types", assertClasses());
},
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
@@ -403,13 +403,13 @@
(a) -> assertCommand(a, "int a;", null),
(a) -> assertCommand(a, "()", null, null, null, "", ""),
(a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"),
- (a) -> assertCommandCheckOutput(a, "/list all", (out) ->
+ (a) -> assertCommandCheckOutput(a, "/list -all", (out) ->
output.addAll(Stream.of(out.split("\n"))
.filter(str -> !str.isEmpty())
.map(str -> str.substring(str.indexOf(':') + 2))
.filter(str -> !str.startsWith("/"))
.collect(Collectors.toList()))),
- (a) -> assertCommand(a, "/save all " + path.toString(), "")
+ (a) -> assertCommand(a, "/save -all " + path.toString(), "")
);
assertEquals(Files.readAllLines(path), output);
}
@@ -451,7 +451,7 @@
loadVariable(a, "double", "b", "10.0", "10.0");
loadMethod(a, "void f() {}", "()void", "f");
loadImport(a, "import java.util.stream.*;", "", "java.util.stream.*");
- assertCommandCheckOutput(a, "/classes", assertClasses());
+ assertCommandCheckOutput(a, "/types", assertClasses());
},
(a) -> assertCommandCheckOutput(a, "/vars", assertVariables()),
(a) -> assertCommandCheckOutput(a, "/methods", assertMethods()),
@@ -472,7 +472,7 @@
public void testStartSave() throws IOException {
Compiler compiler = new Compiler();
Path startSave = compiler.getPath("startSave.txt");
- test(a -> assertCommand(a, "/save start " + startSave.toString(), null));
+ test(a -> assertCommand(a, "/save -start " + startSave.toString(), null));
List<String> lines = Files.lines(startSave)
.filter(s -> !s.isEmpty())
.collect(Collectors.toList());
--- a/langtools/test/jdk/jshell/ToolFormatTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ToolFormatTest.java Thu May 19 19:47:04 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8148316 8148317 8151755 8152246 8153551
+ * @bug 8148316 8148317 8151755 8152246 8153551 8154812
* @summary Tests for output customization
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@@ -43,7 +43,7 @@
public void testSetFormat() {
try {
test(
- (a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"),
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode test -command", "| Created new feedback mode: test"),
(a) -> assertCommand(a, "/set format test pre '$ '", ""),
(a) -> assertCommand(a, "/set format test post ''", ""),
(a) -> assertCommand(a, "/set format test act 'ADD' added", ""),
@@ -82,7 +82,7 @@
public void testSetFormatSelector() {
List<ReplTest> tests = new ArrayList<>();
- tests.add((a) -> assertCommandOutputStartsWith(a, "/set newmode ate quiet",
+ tests.add((a) -> assertCommandOutputStartsWith(a, "/set newmode ate -quiet",
"| Created new feedback mode: ate"));
tests.add((a) -> assertCommand(a, "/set feedback ate", ""));
StringBuilder sb = new StringBuilder();
@@ -155,6 +155,29 @@
}
}
+ public void testSetTruncation() {
+ try {
+ test(
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", ""),
+ (a) -> assertCommand(a, "String s = java.util.stream.IntStream.range(65, 74)"+
+ ".mapToObj(i -> \"\"+(char)i).reduce((a,b) -> a + b + a).get()",
+ "s ==> \"ABACABADABACABAEABACABADABACABAFABACABADABACABAEABACABADABACABAGABACABADABA ..."),
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode test -quiet", ""),
+ (a) -> assertCommandOutputStartsWith(a, "/set feedback test", ""),
+ (a) -> assertCommand(a, "/set format test display '{type}:{value}' primary", ""),
+ (a) -> assertCommand(a, "/set truncation test 20", ""),
+ (a) -> assertCommand(a, "/set trunc test 10 varvalue", ""),
+ (a) -> assertCommand(a, "/set trunc test 3 assignment", ""),
+ (a) -> assertCommand(a, "String r = s", "String:\"ABACABADABACABA ..."),
+ (a) -> assertCommand(a, "r", "String:\"ABACA ..."),
+ (a) -> assertCommand(a, "r=s", "String:\"AB")
+ );
+ } finally {
+ assertCommandCheckOutput(false, "/set feedback normal", s -> {
+ });
+ }
+ }
+
public void testShowFeedbackModes() {
test(
(a) -> assertCommandOutputContains(a, "/set feedback", "normal")
@@ -164,11 +187,11 @@
public void testSetNewModeQuiet() {
try {
test(
- (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"),
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq -quiet normal", "| Created new feedback mode: nmq"),
(a) -> assertCommand(a, "/set feedback nmq", ""),
- (a) -> assertCommand(a, "/se ne nmq2 q nor", ""),
+ (a) -> assertCommand(a, "/se ne nmq2 -q nor", ""),
(a) -> assertCommand(a, "/se fee nmq2", ""),
- (a) -> assertCommand(a, "/set newmode nmc command normal", ""),
+ (a) -> assertCommand(a, "/set newmode nmc -command normal", ""),
(a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"),
(a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm"),
@@ -183,15 +206,15 @@
public void testSetError() {
try {
test(
- (a) -> assertCommandOutputStartsWith(a, "/set newmode tee command foo",
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode tee -command foo",
"| Does not match any current feedback mode: foo"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode tee flurb",
- "| Specify either 'command' or 'quiet'"),
+ "| Specify either '-command' or '-quiet'"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode te2",
"| Created new feedback mode: te2"),
- (a) -> assertCommandOutputStartsWith(a, "/set newmode te2 command",
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode te2 -command",
"| Expected a new feedback mode name. 'te2' is a known feedback mode"),
- (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal",
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode te -command normal",
"| Created new feedback mode: te"),
(a) -> assertCommand(a, "/set format te errorpre 'ERROR: '", ""),
(a) -> assertCommandOutputStartsWith(a, "/set feedback te",
@@ -226,13 +249,19 @@
"ERROR: Selector kind in multiple sections of"),
(a) -> assertCommandOutputStartsWith(a, "/set format te fld 'aaa' import,added",
"ERROR: Different selector kinds in same sections of"),
+ (a) -> assertCommandOutputStartsWith(a, "/set trunc te 20x",
+ "ERROR: Truncation length must be an integer: 20x"),
+ (a) -> assertCommandOutputStartsWith(a, "/set trunc te",
+ "ERROR: Expected truncation length"),
+ (a) -> assertCommandOutputStartsWith(a, "/set truncation te 111 import,added",
+ "ERROR: Different selector kinds in same sections of"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode",
"ERROR: Expected new feedback mode"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode te",
"ERROR: Expected a new feedback mode name"),
(a) -> assertCommandOutputStartsWith(a, "/set newmode x xyz",
- "ERROR: Specify either 'command' or 'quiet'"),
- (a) -> assertCommandOutputStartsWith(a, "/set newmode x quiet y",
+ "ERROR: Specify either '-command' or '-quiet'"),
+ (a) -> assertCommandOutputStartsWith(a, "/set newmode x -quiet y",
"ERROR: Does not match any current feedback mode"),
(a) -> assertCommandOutputStartsWith(a, "/set prompt",
"ERROR: Expected a feedback mode"),
--- a/langtools/test/jdk/jshell/ToolLocaleMessageTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ToolLocaleMessageTest.java Thu May 19 19:47:04 2016 +0000
@@ -76,7 +76,7 @@
public void testSample() {
try {
testLocale(
- (a) -> assertCommandOK(a, "/set newmode test command normal", "test"),
+ (a) -> assertCommandOK(a, "/set newmode test -command normal", "test"),
(a) -> assertCommandOK(a, "/set format test errorpre 'ERROR: '"),
(a) -> assertCommandOK(a, "/set feedback test", "test"),
@@ -101,7 +101,7 @@
public void testCommand() {
try {
testLocale(
- (a) -> assertCommandOK(a, "/set newmode test command normal", "test"),
+ (a) -> assertCommandOK(a, "/set newmode test -command normal", "test"),
(a) -> assertCommandOK(a, "/set format test errorpre 'ERROR: '"),
(a) -> assertCommandOK(a, "/set feedback test", "test"),
@@ -134,13 +134,13 @@
public void testHelp() {
testLocale(
- (a) -> assertCommandOK(a, "/help", "/list", "/save", "/set", "[restore]"),
- (a) -> assertCommandOK(a, "/help /list", "start", "all"),
+ (a) -> assertCommandOK(a, "/help", "/list", "/save", "/set", "[-restore]"),
+ (a) -> assertCommandOK(a, "/help /list", "-start", "-all"),
(a) -> assertCommandOK(a, "/help /edit", "/set editor"),
(a) -> assertCommandOK(a, "/help /drop", "/drop"),
- (a) -> assertCommandOK(a, "/help /save", "all", "start"),
+ (a) -> assertCommandOK(a, "/help /save", "-all", "-start"),
(a) -> assertCommandOK(a, "/help /open", "/open"),
- (a) -> assertCommandOK(a, "/help /reload", "restore"),
+ (a) -> assertCommandOK(a, "/help /reload", "-restore"),
(a) -> assertCommandOK(a, "/help /help", "intro"),
(a) -> assertCommandOK(a, "/help /set", "newmode"),
(a) -> assertCommandOK(a, "/help /?", "intro"),
@@ -156,11 +156,11 @@
public void testFeedbackError() {
try {
testLocale(
- (a) -> assertCommandOK(a, "/set newmode tee command foo", "foo"),
- (a) -> assertCommandOK(a, "/set newmode tee flurb", "command", "quiet"),
+ (a) -> assertCommandOK(a, "/set newmode tee -command foo", "foo"),
+ (a) -> assertCommandOK(a, "/set newmode tee flurb", "-command", "-quiet"),
(a) -> assertCommandOK(a, "/set newmode te2", "te2"),
- (a) -> assertCommandOK(a, "/set newmode te2 command", "te2"),
- (a) -> assertCommandOK(a, "/set newmode te command normal", "te"),
+ (a) -> assertCommandOK(a, "/set newmode te2 -command", "te2"),
+ (a) -> assertCommandOK(a, "/set newmode te -command normal", "te"),
(a) -> assertCommandOK(a, "/set format te errorpre 'ERROR: '"),
(a) -> assertCommandOK(a, "/set feedback te"),
@@ -182,7 +182,7 @@
(a) -> assertCommandFail(a, "/set newmode"),
(a) -> assertCommandFail(a, "/set newmode te"),
(a) -> assertCommandFail(a, "/set newmode x xyz"),
- (a) -> assertCommandFail(a, "/set newmode x quiet y"),
+ (a) -> assertCommandFail(a, "/set newmode x -quiet y"),
(a) -> assertCommandFail(a, "/set prompt"),
(a) -> assertCommandFail(a, "/set prompt te"),
(a) -> assertCommandFail(a, "/set prompt te aaa xyz", "aaa"),
--- a/langtools/test/jdk/jshell/ToolReloadTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ToolReloadTest.java Thu May 19 19:47:04 2016 +0000
@@ -107,7 +107,7 @@
"-: /drop A\n"),
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/types", assertClasses()),
a -> assertCommandCheckOutput(a, "/imports", assertImports())
);
}
@@ -120,11 +120,11 @@
a -> dropMethod(a, "/drop b", "b ()I", "| dropped method b()"),
a -> assertClass(a, "class A {}", "class", "A"),
a -> dropClass(a, "/dr A", "class A", "| dropped class A"),
- a -> assertCommand(a, "/reload quiet",
+ a -> assertCommand(a, "/reload -quiet",
"| Restarting and restoring state."),
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/types", assertClasses()),
a -> assertCommandCheckOutput(a, "/imports", assertImports())
);
}
@@ -169,7 +169,7 @@
"(int)int", "m"),
(a) -> evaluateExpression(a, "int", "m(x)", "25"),
(a) -> assertCommand(a, "/reset", "| Resetting state."),
- (a) -> assertCommand(a, "/reload restore",
+ (a) -> assertCommand(a, "/reload -restore",
"| Restarting and restoring from previous state.\n" +
"-: int x = 5;\n" +
"-: int m(int z) { return z * z; }\n" +
@@ -188,8 +188,8 @@
(a) -> evaluateExpression(a, "int", "m(x)", "25"),
(a) -> assertCommand(a, "System.exit(1);",
"| State engine terminated.\n" +
- "| Restore definitions with: /reload restore"),
- (a) -> assertCommand(a, "/reload restore",
+ "| Restore definitions with: /reload -restore"),
+ (a) -> assertCommand(a, "/reload -restore",
"| Restarting and restoring from previous state.\n" +
"-: int x = 5;\n" +
"-: int m(int z) { return z * z; }\n" +
@@ -208,7 +208,7 @@
(a) -> evaluateExpression(a, "int", "m(x)", "25")
);
test(false, new String[]{"-nostartup"},
- (a) -> assertCommand(a, "/reload restore",
+ (a) -> assertCommand(a, "/reload -restore",
"| Restarting and restoring from previous state.\n" +
"-: int x = 5;\n" +
"-: int m(int z) { return z * z; }\n" +
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java Thu May 19 19:47:04 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8153716 8143955 8151754 8150382
+ * @bug 8153716 8143955 8151754 8150382 8153920
* @summary Simple jshell tool tests
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
@@ -101,22 +101,22 @@
);
}
- public void defineClasses() {
+ public void defineTypes() {
test(
(a) -> assertCommandCheckOutput(a, "/list", assertList()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertClass(a, "class A { }", "class", "A"),
(a) -> assertCommandCheckOutput(a, "/list", assertList()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertClass(a, "interface A { }", "interface", "A"),
(a) -> assertCommandCheckOutput(a, "/list", assertList()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertClass(a, "enum A { }", "enum", "A"),
(a) -> assertCommandCheckOutput(a, "/list", assertList()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
(a) -> assertClass(a, "@interface A { }", "@interface", "A"),
(a) -> assertCommandCheckOutput(a, "/list", assertList()),
- (a) -> assertCommandCheckOutput(a, "/classes", assertClasses())
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses())
);
}
@@ -211,7 +211,7 @@
a -> dropImport(a, "/drop 4", "import java.util.stream.*", ""),
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/types", assertClasses()),
a -> assertCommandCheckOutput(a, "/imports", assertImports())
);
test(false, new String[]{"-nostartup"},
@@ -223,15 +223,15 @@
a -> dropClass(a, "/drop A", "class A", "| dropped class A"),
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/types", assertClasses()),
a -> assertCommandCheckOutput(a, "/imports", assertImports())
);
}
public void testDropNegative() {
test(false, new String[]{"-nostartup"},
- a -> assertCommandOutputStartsWith(a, "/drop 0", "| No definition or id found named: 0"),
- a -> assertCommandOutputStartsWith(a, "/drop a", "| No definition or id found named: a"),
+ a -> assertCommandOutputStartsWith(a, "/drop 0", "| No applicable definition or id found named: 0"),
+ a -> assertCommandOutputStartsWith(a, "/drop a", "| No applicable definition or id found named: a"),
a -> assertCommandCheckOutput(a, "/drop",
assertStartsWith("| In the /drop argument, please specify an import, variable, method, or class to drop.")),
a -> assertVariable(a, "int", "a"),
@@ -253,7 +253,7 @@
a -> assertCommandCheckOutput(a, "/drop a", check),
a -> assertCommandCheckOutput(a, "/vars", assertVariables()),
a -> assertCommandCheckOutput(a, "/methods", assertMethods()),
- a -> assertCommandCheckOutput(a, "/classes", assertClasses()),
+ a -> assertCommandCheckOutput(a, "/types", assertClasses()),
a -> assertCommandCheckOutput(a, "/imports", assertImports())
);
test(
@@ -284,7 +284,7 @@
(a) -> assertHelp(a, "/?", "/list", "/help", "/exit", "intro"),
(a) -> assertHelp(a, "/help", "/list", "/help", "/exit", "intro"),
(a) -> assertHelp(a, "/help short", "shortcuts", "<tab>"),
- (a) -> assertHelp(a, "/? /li", "/list all", "snippets"),
+ (a) -> assertHelp(a, "/? /li", "/list -all", "snippets"),
(a) -> assertHelp(a, "/help /help", "/help <command>")
);
}
@@ -299,7 +299,10 @@
// Check that each line of output contains the corresponding string from the list
private void checkLineToList(String in, List<String> match) {
- String[] res = in.trim().split("\n");
+ String trimmed = in.trim();
+ String[] res = trimmed.isEmpty()
+ ? new String[0]
+ : trimmed.split("\n");
assertEquals(res.length, match.size(), "Got: " + Arrays.asList(res));
for (int i = 0; i < match.size(); ++i) {
assertTrue(res[i].contains(match.get(i)));
@@ -311,23 +314,131 @@
List<String> startVarList = new ArrayList<>(START_UP);
startVarList.add("int aardvark");
test(
- a -> assertCommandCheckOutput(a, "/list all",
+ a -> assertCommandCheckOutput(a, "/list -all",
s -> checkLineToList(s, START_UP)),
a -> assertCommandOutputStartsWith(a, "/list " + arg,
- "| No definition or id found named: " + arg),
+ "| No applicable definition or id found named: " + arg),
a -> assertVariable(a, "int", "aardvark"),
a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"),
- a -> assertCommandCheckOutput(a, "/list start",
+ a -> assertCommandCheckOutput(a, "/list -start",
s -> checkLineToList(s, START_UP)),
- a -> assertCommandCheckOutput(a, "/list all",
+ a -> assertCommandCheckOutput(a, "/list -all",
s -> checkLineToList(s, startVarList)),
a -> assertCommandCheckOutput(a, "/list printf",
s -> assertTrue(s.contains("void printf"))),
a -> assertCommandOutputStartsWith(a, "/list " + arg,
- "| No definition or id found named: " + arg)
+ "| No applicable definition or id found named: " + arg)
+ );
+ }
+
+ public void testVarsArgs() {
+ String arg = "qqqq";
+ List<String> startVarList = new ArrayList<>();
+ test(
+ a -> assertCommandCheckOutput(a, "/vars -all",
+ s -> checkLineToList(s, startVarList)),
+ a -> assertCommandOutputStartsWith(a, "/vars " + arg,
+ "| No applicable definition or id found named: " + arg),
+ a -> assertVariable(a, "int", "aardvark"),
+ a -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
+ a -> assertVariable(a, "int", "a"),
+ a -> assertVariable(a, "double", "a", "1", "1.0"),
+ a -> assertCommandOutputStartsWith(a, "/vars aardvark", "| int aardvark = 0"),
+ a -> assertCommandCheckOutput(a, "/vars -start",
+ s -> checkLineToList(s, startVarList)),
+ a -> assertCommandOutputStartsWith(a, "/vars -all",
+ "| int aardvark = 0\n| int a = "),
+ a -> assertCommandOutputStartsWith(a, "/vars printf",
+ "| No applicable definition or id found named: printf"),
+ a -> assertCommandOutputStartsWith(a, "/vars " + arg,
+ "| No applicable definition or id found named: " + arg)
);
}
+ public void testMethodsArgs() {
+ String arg = "qqqq";
+ List<String> startMethodList = new ArrayList<>(START_UP_CMD_METHOD);
+ test(
+ a -> assertCommandCheckOutput(a, "/methods -all",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandCheckOutput(a, "/methods -start",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandCheckOutput(a, "/methods printf",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandCheckOutput(a, "/methods",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandOutputStartsWith(a, "/methods " + arg,
+ "| No applicable definition or id found named: " + arg),
+ a -> assertMethod(a, "int f() { return 0; }", "()int", "f"),
+ a -> assertVariable(a, "int", "aardvark"),
+ a -> assertMethod(a, "void f(int a) { g(); }", "(int)void", "f"),
+ a -> assertMethod(a, "void g() {}", "()void", "g"),
+ a -> assertCommandOutputStartsWith(a, "/methods " + arg,
+ "| No applicable definition or id found named: " + arg),
+ a -> assertCommandOutputStartsWith(a, "/methods aardvark",
+ "| No applicable definition or id found named: aardvark"),
+ a -> assertCommandCheckOutput(a, "/methods -start",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandCheckOutput(a, "/methods printf",
+ s -> checkLineToList(s, startMethodList)),
+ a -> assertCommandOutputStartsWith(a, "/methods g",
+ "| g ()void"),
+ a -> assertCommandOutputStartsWith(a, "/methods f",
+ "| f ()int\n" +
+ "| f (int)void")
+ );
+ }
+
+ public void testTypesArgs() {
+ String arg = "qqqq";
+ List<String> startTypeList = new ArrayList<>();
+ test(
+ a -> assertCommandCheckOutput(a, "/types -all",
+ s -> checkLineToList(s, startTypeList)),
+ a -> assertCommandCheckOutput(a, "/types -start",
+ s -> checkLineToList(s, startTypeList)),
+ a -> assertCommandOutputStartsWith(a, "/types " + arg,
+ "| No applicable definition or id found named: " + arg),
+ a -> assertVariable(a, "int", "aardvark"),
+ (a) -> assertClass(a, "class A { }", "class", "A"),
+ (a) -> assertClass(a, "interface A { }", "interface", "A"),
+ a -> assertCommandOutputStartsWith(a, "/types -all",
+ "| class A\n" +
+ "| interface A"),
+ (a) -> assertClass(a, "enum E { }", "enum", "E"),
+ (a) -> assertClass(a, "@interface B { }", "@interface", "B"),
+ a -> assertCommandOutputStartsWith(a, "/types aardvark",
+ "| No applicable definition or id found named: aardvark"),
+ a -> assertCommandOutputStartsWith(a, "/types A",
+ "| interface A"),
+ a -> assertCommandOutputStartsWith(a, "/types E",
+ "| enum E"),
+ a -> assertCommandOutputStartsWith(a, "/types B",
+ "| @interface B"),
+ a -> assertCommandOutputStartsWith(a, "/types " + arg,
+ "| No applicable definition or id found named: " + arg),
+ a -> assertCommandCheckOutput(a, "/types -start",
+ s -> checkLineToList(s, startTypeList))
+ );
+ }
+ public void defineClasses() {
+ test(
+ (a) -> assertCommandCheckOutput(a, "/list", assertList()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
+ (a) -> assertClass(a, "class A { }", "class", "A"),
+ (a) -> assertCommandCheckOutput(a, "/list", assertList()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
+ (a) -> assertClass(a, "interface A { }", "interface", "A"),
+ (a) -> assertCommandCheckOutput(a, "/list", assertList()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
+ (a) -> assertClass(a, "enum A { }", "enum", "A"),
+ (a) -> assertCommandCheckOutput(a, "/list", assertList()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses()),
+ (a) -> assertClass(a, "@interface A { }", "@interface", "A"),
+ (a) -> assertCommandCheckOutput(a, "/list", assertList()),
+ (a) -> assertCommandCheckOutput(a, "/types", assertClasses())
+ );
+ }
public void testCommandPrefix() {
test(a -> assertCommandCheckOutput(a, "/s",
assertStartsWith("| Command: '/s' is ambiguous: /save, /set")),
--- a/langtools/test/tools/all/RunCodingRules.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/all/RunCodingRules.java Thu May 19 19:47:04 2016 +0000
@@ -50,6 +50,17 @@
import com.sun.tools.javac.util.Assert;
+/**
+ * This is a test to verify specific coding standards for source code in the langtools repository.
+ *
+ * As such, it is not a standard unit, regression or functional test, and will
+ * automatically skip if the langtools source code is not available.
+ *
+ * If the source code is available, it will find and compile the coding
+ * style analyzers found in langtools/make/tools/crules/*.java, and run the resulting
+ * code on all source files under langtools/src/share/classes. Any coding style
+ * violations will cause the test to fail.
+ */
public class RunCodingRules {
public static void main(String... args) throws Exception {
new RunCodingRules().run();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,23 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8156180
+ * @summary javac accepts code that violates JLS chapter 16
+ *
+ * @compile/fail/ref=T8156180.out -XDrawDiagnostics T8156180.java
+ */
+
+class T8156180 {
+ public final int a1, b1, c1, d1;
+ public int a2, b2, c2, d2;
+
+ T8156180(int value) {
+ a2 = this.a1;
+ b2 = (this).b1;
+ c2 = ((this)).c1;
+ d2 = (((this))).d1;
+ a1 = value;
+ b1 = value;
+ c1 = value;
+ d1 = value;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/DefiniteAssignment/8156180/T8156180.out Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,5 @@
+T8156180.java:14:18: compiler.err.var.might.not.have.been.initialized: a1
+T8156180.java:15:20: compiler.err.var.might.not.have.been.initialized: b1
+T8156180.java:16:22: compiler.err.var.might.not.have.been.initialized: c1
+T8156180.java:17:24: compiler.err.var.might.not.have.been.initialized: d1
+4 errors
--- a/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/Diagnostics/compressed/T8012003b.out Thu May 19 19:47:04 2016 +0000
@@ -1,5 +1,5 @@
T8012003b.java:30:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, java.lang.String, compiler.misc.no.args, kindname.class, T8012003b, (compiler.misc.arg.length.mismatch)))
-T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void))
+T8012003b.java:31:16: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
T8012003b.java:32:22: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.conditional.target.cant.be.void))
T8012003b.java:33:12: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.String)))
T8012003b.java:34:12: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer))
--- a/langtools/test/tools/javac/Paths/MineField.sh Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/Paths/MineField.sh Thu May 19 19:47:04 2016 +0000
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, 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
@@ -25,7 +25,7 @@
#
# @test
-# @bug 4758537 4809833
+# @bug 4758537 4809833 8149599
# @summary Test that javac and java find files in similar ways
# @author Martin Buchholz
#
@@ -49,14 +49,33 @@
# - Only for the user classpath is an empty string value equivalent to "."
# - Specifying a bootclasspath on the command line obliterates any
# previous -Xbootclasspath/p: or -Xbootclasspath/a: command line flags.
+#
+# JDK 9 update:
+# java: The java launcher does not support any of the following:
+# * -Xbootclasspath/p: -Xbootclasspath:
+# * -endorseddirs -Djava.endorsed.dirs
+# * -extdirs -Djava.ext.dirs
+# All test cases exercising these features have been removed.
+# javac: The following features are only supported when compiling
+# for older releases:
+# * -Xbootclasspath/p: -Xbootclasspath: -bootclasspath -Xbootclasspath/a:
+# * -endorseddirs -Djava.endorsed.dirs
+# * -extdirs -Djava.ext.dirs
+# All test cases exercising these features have been modified to
+# use -source 8 -target 8. In addition, javac test cases involving
+# use of the runtime properties java.endorsed.dirs and java.extdirs
+# (by means of -J-Dname=value) have been removed.
+# Although the primary purpose of the test cases in this file is to
+# compare javac and java behavior, some tests remain for javac for
+# which there is no java equivalent. However, the cases remain as useful
+# test cases for javac handling of the paths involved.
+
#----------------------------------------------------------------
. ${TESTSRC-.}/Util.sh
set -u
-# BCP=`DefaultBootClassPath`
-
#----------------------------------------------------------------
# Prepare the "Minefield"
#----------------------------------------------------------------
@@ -64,6 +83,7 @@
Sys rm -rf GooSrc GooJar GooZip GooClass
Sys rm -rf BadSrc BadJar BadZip BadClass
Sys rm -rf OneDir *.class Main.java MANIFEST.MF
+ Sys rm -f java-lang.jar
}
Cleanup
@@ -88,215 +108,95 @@
echo 'public class Main {public static void main(String[] a) {Lib.f();}}' > Main.java
+# Create a jar file that is good enough to put on the javac boot class path (i.e. contains java.lang.**)
+Sys "$jimage" extract --dir modules ${TESTJAVA}/lib/modules
+Sys "$jar" cf java-lang.jar -C modules/java.base java/lang
+Sys rm -rf modules
+
#----------------------------------------------------------------
# Verify that javac class search order is the same as java's
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -J-Djava.endorsed.dirs="GooJar" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \
-# -J-Djava.endorsed.dirs="BadJar${PS}GooZip" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -Djava.endorsed.dirs="GooJar" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \
-# -Djava.endorsed.dirs="BadJar${PS}GooZip" \
-# Main
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Xbootclasspath/p:"GooClass" \
+ -bootclasspath "java-lang.jar${PS}BadZip/Lib.zip" \
+ Main.java
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Xbootclasspath/p:"BadClass${PS}GooClass" \
+ -bootclasspath "java-lang.jar${PS}GooZip/Lib.zip${PS}BadClass" \
+ Main.java
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Xbootclasspath/p:"BadJar/Lib.jar" \
+ -Xbootclasspath:"java-lang.jar${PS}GooClass" \
+ Main.java
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -bootclasspath "$BCP${PS}BadZip/Lib.zip" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"BadClass${PS}GooClass" \
-# -bootclasspath "$BCP${PS}GooZip/Lib.zip${PS}BadClass" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"BadJar/Lib.jar" \
-# -Xbootclasspath:"$BCP${PS}GooClass" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -Xbootclasspath:"$BCP${PS}BadZip/Lib.zip" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"BadClass${PS}GooClass" \
-# -Xbootclasspath:"$BCP${PS}GooZip/Lib.zip${PS}BadClass" \
-# Main
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -bootclasspath "java-lang.jar${PS}GooZip/Lib.zip" \
+ -Xbootclasspath/p:"BadClass" \
+ Main.java
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -bootclasspath "java-lang.jar${PS}BadZip/Lib.zip" \
+ -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \
+ Main.java
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -bootclasspath "$BCP${PS}GooZip/Lib.zip" \
-# -Xbootclasspath/p:"BadClass" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -bootclasspath "$BCP${PS}BadZip/Lib.zip" \
-# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath:"$BCP${PS}GooClass" \
-# -Xbootclasspath/p:"BadClass" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath:"$BCP${PS}BadClass" \
-# -Xbootclasspath/p:"GooClass${PS}BadJar/Lib.jar" \
-# Main
-
-#----------------------------------------------------------------
-Failure "$javac" ${TESTTOOLVMOPTS} \
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-Xbootclasspath/p:"BadClass" \
-Xbootclasspath/a:"GooClass" \
Main.java
-Success "$javac" ${TESTTOOLVMOPTS} \
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-Xbootclasspath/p:"GooClass${PS}BadClass" \
-Xbootclasspath/a:"BadClass" \
Main.java
-Failure "$java" ${TESTVMOPTS} \
- -Xbootclasspath/p:"BadClass" \
+Success "$java" ${TESTVMOPTS} \
-Xbootclasspath/a:"GooClass" \
Main
-Success "$java" ${TESTVMOPTS} \
- -Xbootclasspath/p:"GooClass${PS}BadClass" \
- -Xbootclasspath/a:"BadClass" \
- Main
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -J-Djava.endorsed.dirs="BadZip" \
-# -bootclasspath "GooClass${PS}$BCP" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -J-Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
-# -bootclasspath "BadClass${PS}$BCP" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -Djava.endorsed.dirs="BadZip" \
-# -Xbootclasspath:"GooClass${PS}$BCP" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# Main
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Xbootclasspath/p:"GooClass" \
+ -Xbootclasspath:"BadClass${PS}java-lang.jar" \
+ -Xbootclasspath/a:"GooClass" \
+ Main.java
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Xbootclasspath/p:"BadClass" \
+ -Xbootclasspath:"GooClass${PS}BadClass${PS}java-lang.jar" \
+ -Xbootclasspath/a:"BadClass" \
+ Main.java
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# -Xbootclasspath/a:"GooClass" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -Xbootclasspath:"GooClass${PS}BadClass${PS}$BCP" \
-# -Xbootclasspath/a:"BadClass" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"GooClass" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# -Xbootclasspath/a:"GooClass" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/p:"BadClass" \
-# -Xbootclasspath:"GooClass${PS}BadClass${PS}$BCP" \
-# -Xbootclasspath/a:"BadClass" \
-# Main
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -endorseddirs "BadClass${PS}GooZip${PS}BadJar" \
+ -Xbootclasspath:"BadClass${PS}java-lang.jar" \
+ Main.java
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
+ -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
+ -Xbootclasspath:"BadClass${PS}java-lang.jar" \
+ Main.java
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -J-Djava.endorsed.dirs="BadZip" \
-# -Xbootclasspath:"GooClass${PS}$BCP" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -endorseddirs "BadClass${PS}GooZip${PS}BadJar" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -J-Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Djava.endorsed.dirs="BadZip" \
-# -Xbootclasspath:"GooClass${PS}$BCP" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Djava.endorsed.dirs="BadClass${PS}GooZip${PS}BadJar" \
-# -Xbootclasspath:"BadClass${PS}$BCP" \
-# Main
-
-#----------------------------------------------------------------
-Failure "$javac" ${TESTTOOLVMOPTS} \
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-Xbootclasspath/a:"BadClass" \
-extdirs "GooZip" \
Main.java
-Success "$javac" ${TESTTOOLVMOPTS} \
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-Xbootclasspath/a:"GooClass${PS}BadClass" \
-extdirs "BadZip" \
Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/a:"BadClass" \
-# -Djava.ext.dirs="GooZip" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath/a:"GooClass${PS}BadClass" \
-# -Djava.ext.dirs="BadZip" \
-# Main
#----------------------------------------------------------------
-# Failure "$javac" ${TESTTOOLVMOPTS} \
-# -bootclasspath "$BCP${PS}BadJar/Lib.jar" \
-# -J-Djava.ext.dir="GooJar" \
-# Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -bootclasspath "$BCP${PS}GooJar/Lib.jar${PS}BadClass" \
-# -J-Djava.ext.dir="BadJar" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Xbootclasspath:"$BCP${PS}BadJar/Lib.jar" \
-# -Djava.ext.dirs="GooJar" \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Xbootclasspath:"$BCP${PS}GooJar/Lib.jar${PS}BadClass" \
-# -Djava.ext.dirs="BadJar" \
-# Main
-
-#----------------------------------------------------------------
-Failure "$javac" ${TESTTOOLVMOPTS} \
+Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-extdirs "GooClass${PS}BadZip" \
-cp "GooZip/Lib.zip" \
Main.java
-Success "$javac" ${TESTTOOLVMOPTS} \
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-extdirs "BadClass${PS}GooZip${PS}BadJar" \
-cp "BadZip/Lib.zip" \
Main.java
-Success "$javac" ${TESTTOOLVMOPTS} \
+Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} \
-Djava.ext.dirs="GooZip${PS}BadJar" \
-classpath "BadZip/Lib.zip" \
Main.java
-# Success "$javac" ${TESTTOOLVMOPTS} \
-# -J-Djava.ext.dirs="GooZip${PS}BadJar" \
-# -classpath "BadZip/Lib.zip" \
-# Main.java
-# Failure "$java" ${TESTVMOPTS} \
-# -Djava.ext.dirs="GooClass${PS}BadZip" \
-# -cp "GooZip/Lib.zip${PS}." \
-# Main
-# Success "$java" ${TESTVMOPTS} \
-# -Djava.ext.dirs="GooZip${PS}BadJar" \
-# -cp "BadZip/Lib.zip${PS}." \
-# Main
#----------------------------------------------------------------
Failure "$javac" ${TESTTOOLVMOPTS} -classpath "BadClass${PS}GooClass" Main.java
@@ -338,45 +238,32 @@
In GooClass Success "$java" ${TESTVMOPTS} -cp "..${PS}${PS}/xyzzy" Main
# All other empty path elements are ignored.
-In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -extdirs "" -cp ".." ../Main.java
-# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.ext.dirs="" -cp ".." Main
+In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -extdirs "" -cp ".." ../Main.java
-In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -extdirs "${PS}" -cp ".." ../Main.java
-In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." ../Main.java
-# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." Main
+In GooJar Failure "$javac" -source 8 -targt 8 ${TESTTOOLVMOPTS} -extdirs "${PS}" -cp ".." ../Main.java
+In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.ext.dirs="${PS}" -cp ".." ../Main.java
-In GooJar Success "$javac" ${TESTTOOLVMOPTS} -extdirs "." -cp ".." ../Main.java
-In GooJar Success "$javac" ${TESTTOOLVMOPTS} -Djava.ext.dirs="." -cp ".." ../Main.java
-# In GooJar Success "$java" ${TESTVMOPTS} -Djava.ext.dirs="." -cp ".." Main
+In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -extdirs "." -cp ".." ../Main.java
+In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.ext.dirs="." -cp ".." ../Main.java
-# In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="" -cp ".." ../Main.java
-In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="" -cp ".." ../Main.java
-# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="" -cp ".." Main
+In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="" -cp ".." ../Main.java
+
+In GooJar Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -endorseddirs "${PS}" -cp ".." ../Main.java
-# In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="${PS}" -cp ".." ../Main.java
-In GooJar Failure "$javac" ${TESTTOOLVMOPTS} -endorseddirs "${PS}" -cp ".." ../Main.java
-# In GooJar Failure "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="${PS}" -cp ".." Main
+In GooJar Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="." -cp ".." ../Main.java
-# In GooJar Success "$javac" ${TESTTOOLVMOPTS} -J-Djava.endorsed.dirs="." -cp ".." ../Main.java
-In GooJar Success "$javac" ${TESTTOOLVMOPTS} -Djava.endorsed.dirs="." -cp ".." ../Main.java
-# In GooJar Success "$java" ${TESTVMOPTS} -Djava.endorsed.dirs="." -cp ".." Main
+In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/p: -cp ".." ../Main.java
-In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/p: -cp ".." ../Main.java
-In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath/p: -cp ".." Main
+In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/p:. -cp ".." ../Main.java
-In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/p:. -cp ".." ../Main.java
-In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath/p:. -cp ".." Main
+In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath:"../java-lang.jar" -cp ".." ../Main.java
-# In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath:"$BCP" -cp ".." ../Main.java
-# In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath:"$BCP" -cp ".." Main
+In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath:"../java-lang.jar${PS}." -cp ".." ../Main.java
-# In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath:"$BCP${PS}." -cp ".." ../Main.java
-# In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath:"$BCP${PS}." -cp ".." Main
-
-In GooClass Failure "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/a: -cp ".." ../Main.java
+In GooClass Failure "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/a: -cp ".." ../Main.java
In GooClass Failure "$java" ${TESTVMOPTS} -Xbootclasspath/a: -cp ".." Main
-In GooClass Success "$javac" ${TESTTOOLVMOPTS} -Xbootclasspath/a:. -cp ".." ../Main.java
+In GooClass Success "$javac" -source 8 -target 8 ${TESTTOOLVMOPTS} -Xbootclasspath/a:. -cp ".." ../Main.java
In GooClass Success "$java" ${TESTVMOPTS} -Xbootclasspath/a:. -cp ".." Main
Cleanup
--- a/langtools/test/tools/javac/Paths/Util.sh Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/Paths/Util.sh Thu May 19 19:47:04 2016 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2003, 2016, 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
@@ -24,9 +24,10 @@
# Utilities for shell tests
: ${TESTSRC=.} ${TESTCLASSES=.}
- java="${TESTJAVA+${TESTJAVA}/bin/}java"
-javac="${TESTJAVA+${TESTJAVA}/bin/}javac"
- jar="${TESTJAVA+${TESTJAVA}/bin/}jar"
+ java="${TESTJAVA+${TESTJAVA}/bin/}java"
+ javac="${TESTJAVA+${TESTJAVA}/bin/}javac"
+ jar="${TESTJAVA+${TESTJAVA}/bin/}jar"
+jimage="${TESTJAVA+${TESTJAVA}/bin/}jimage"
case `uname -s` in
Windows*|CYGWIN*)
@@ -105,21 +106,6 @@
for jarfilename in "$@"; do pwd > "$jarfilename"; done
}
-# #----------------------------------------------------------------
-# # Usage: BCP=`DefaultBootClassPath`
-# # Returns default bootclasspath, discarding non-existent entries
-# #----------------------------------------------------------------
-# DefaultBootClassPath() {
-# echo 'public class B {public static void main(String[] a) {
-# System.out.println(System.getProperty("sun.boot.class.path"));}}' > B.java
-# "$javac" ${TESTTOOLVMOPTS} B.java
-# _BCP_=""
-# for elt in `"$java" ${TESTVMOPTS} B | tr "${PS}" " "`; do
-# test -r "$elt" -a -n "$elt" && _BCP_="${_BCP_:+${_BCP_}${PS}}${elt}"
-# done
-# rm -f B.java B.class
-# printf "%s" "$_BCP_" # Don't use echo -- unsafe on Windows
-# }
#----------------------------------------------------------------
# Foil message localization
--- a/langtools/test/tools/javac/diags/Example.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/diags/Example.java Thu May 19 19:47:04 2016 +0000
@@ -63,6 +63,8 @@
procFiles = new ArrayList<File>();
supportFiles = new ArrayList<File>();
srcPathFiles = new ArrayList<File>();
+ moduleSourcePathFiles = new ArrayList<File>();
+ additionalFiles = new ArrayList<File>();
findFiles(file, srcFiles);
for (File f: srcFiles) {
@@ -81,13 +83,23 @@
else if (files == srcFiles && c.getName().equals("sourcepath")) {
srcPathDir = c;
findFiles(c, srcPathFiles);
+ } else if (files == srcFiles && c.getName().equals("modulesourcepath")) {
+ moduleSourcePathDir = c;
+ findFiles(c, moduleSourcePathFiles);
+ } else if (files == srcFiles && c.getName().equals("additional")) {
+ additionalFilesDir = c;
+ findFiles(c, additionalFiles);
} else if (files == srcFiles && c.getName().equals("support"))
findFiles(c, supportFiles);
else
findFiles(c, files);
}
- } else if (f.isFile() && f.getName().endsWith(".java")) {
- files.add(f);
+ } else if (f.isFile()) {
+ if (f.getName().endsWith(".java")) {
+ files.add(f);
+ } else if (f.getName().equals("modulesourcepath")) {
+ moduleSourcePathDir = f;
+ }
}
}
@@ -228,14 +240,27 @@
}
}
+ List<File> files = srcFiles;
+
if (srcPathDir != null) {
opts.add("-sourcepath");
opts.add(srcPathDir.getPath());
}
+ if (moduleSourcePathDir != null) {
+ opts.add("-modulesourcepath");
+ opts.add(moduleSourcePathDir.getPath());
+ files = moduleSourcePathFiles;
+ }
+
+ if (additionalFiles.size() > 0) {
+ List<String> sOpts = Arrays.asList("-d", classesDir.getPath());
+ new Jsr199Compiler(verbose).run(null, null, false, sOpts, additionalFiles);
+ }
+
try {
Compiler c = Compiler.getCompiler(runOpts, verbose);
- c.run(out, keys, raw, opts, srcFiles);
+ c.run(out, keys, raw, opts, files);
} catch (IllegalArgumentException e) {
if (out != null) {
out.println("Invalid value for run tag: " + runOpts);
@@ -298,7 +323,11 @@
List<File> srcFiles;
List<File> procFiles;
File srcPathDir;
+ File moduleSourcePathDir;
+ File additionalFilesDir;
List<File> srcPathFiles;
+ List<File> moduleSourcePathFiles;
+ List<File> additionalFiles;
List<File> supportFiles;
File infoFile;
private List<String> runOpts;
--- a/langtools/test/tools/javac/diags/examples.not-yet.txt Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/diags/examples.not-yet.txt Thu May 19 19:47:04 2016 +0000
@@ -110,67 +110,26 @@
compiler.misc.bad.class.file # class file is malformed
compiler.misc.bad.const.pool.entry # constant pool entry has wrong type
-# The following are new module-related messages, that need new examples to be created
-compiler.err.addmods.all.module.path.invalid
-compiler.err.cant.find.module
-compiler.err.cyclic.requires
-compiler.err.duplicate.exports
-compiler.err.duplicate.module
+# The following module-related messages will have to stay on the not-yet list for various reasons:
+compiler.warn.locn.unknown.file.on.module.path # Never issued ATM (short circuited with an if (false))
+compiler.err.no.output.dir # -d is always specified by test infrastructure
+compiler.err.output.dir.must.be.specified.with.dash.m.option # -d is always specified by test infrastructure
+compiler.warn.outdir.is.in.exploded.module # No control over -d specified by test infrastructure
+compiler.err.invalid.module.specifier # Not possible (?)
+compiler.err.locn.cant.get.module.name.for.jar # bad binary ? Infer module name failure
+compiler.misc.bad.module-info.name # bad class file
+compiler.err.locn.bad.module-info # bad class file
+compiler.err.locn.cant.read.file # bad class file
+compiler.err.locn.cant.read.directory # file system issue
+compiler.misc.unnamed.module # fragment uninteresting in and of itself
+compiler.misc.kindname.module # fragment uninteresting in and of itself
+compiler.misc.locn.module_path # fragment uninteresting in and of itself
+compiler.misc.locn.module_source_path # fragment uninteresting in and of itself
+compiler.misc.locn.system_modules # fragment uninteresting in and of itself
+compiler.misc.locn.upgrade_module_path # fragment uninteresting in and of itself
+
+# The following are new module-related messages, that need new examples to be created
compiler.err.duplicate.module.on.path
-compiler.err.duplicate.provides
-compiler.err.duplicate.requires
-compiler.err.duplicate.uses
-compiler.err.expected.module
-compiler.err.illegal.argument.for.option
-compiler.err.invalid.module.specifier
-compiler.err.locn.bad.module-info
-compiler.err.locn.cant.get.module.name.for.jar
-compiler.err.locn.cant.read.directory
-compiler.err.locn.cant.read.file
-compiler.err.locn.invalid.arg.for.xpatch
compiler.err.locn.module-info.not.allowed.on.patch.path
-compiler.err.module-info.with.xmodule.classpath
-compiler.err.module-info.with.xmodule.sourcepath
-compiler.err.module.decl.sb.in.module-info.java
-compiler.err.module.name.mismatch
-compiler.err.module.not.found
-compiler.err.module.not.found.in.module.source.path
-compiler.err.modules.not.supported.in.source
-compiler.err.modulesourcepath.must.be.specified.with.dash.m.option
-compiler.err.multi-module.outdir.cannot.be.exploded.module
-compiler.err.no.output.dir
-compiler.err.not.def.access.package.cant.access
-compiler.err.output.dir.must.be.specified.with.dash.m.option
-compiler.err.package.clash.from.requires
-compiler.err.package.empty.or.not.found
-compiler.err.package.in.other.module
-compiler.err.processorpath.no.processormodulepath
-compiler.err.service.definition.is.inner
-compiler.err.service.definition.is.enum
-compiler.err.service.implementation.doesnt.have.a.no.args.constructor
-compiler.err.service.implementation.is.abstract
-compiler.err.service.implementation.is.inner
-compiler.err.service.implementation.no.args.constructor.not.public
-compiler.err.service.implementation.not.in.right.module
-compiler.err.too.many.modules
-compiler.err.unexpected.after.module
-compiler.err.unnamed.pkg.not.allowed.named.modules
-compiler.err.xaddexports.malformed.entry
-compiler.err.xaddexports.too.many
-compiler.err.xaddreads.malformed.entry
-compiler.err.xaddreads.too.many
-compiler.err.xmodule.no.module.sourcepath
-compiler.misc.bad.module-info.name
compiler.misc.cant.resolve.modules
compiler.misc.file.does.not.contain.module
-compiler.misc.kindname.module
-compiler.misc.locn.module_path
-compiler.misc.locn.module_source_path
-compiler.misc.locn.system_modules
-compiler.misc.locn.upgrade_module_path
-compiler.misc.unnamed.module
-compiler.warn.dir.path.element.not.directory
-compiler.warn.locn.unknown.file.on.module.path
-compiler.warn.outdir.is.in.exploded.module
-compiler.warn.service.provided.but.not.exported.or.used
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/AddmodsAllModulePathInvalid/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.addmods.all.module.path.invalid
+// options: -addmods ALL-MODULE-PATH
+module m {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.cant.find.module
+// key: compiler.err.doesnt.exist
+
+// options: -XaddExports:undef/undef=ALL-UNNAMED
+
+import undef.Any;
+
+class Test {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/CyclicRequires.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.cyclic.requires
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {
+ requires m2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/CyclicRequires/modulesourcepath/m2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m2 {
+ requires m1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/DirPathElementNotDirectory.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.warn.dir.path.element.not.directory
+// options: -Xlint:path
+// run: simple
+
+class DirPathElementNotDirectory { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DirPathElementNotDirectory/modulesourcepath Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// a file to be passed in where a directory is expected (-modulesourcepath option)
+// to trigger an error deliberately.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateExports/exported/Class.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public class Class {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateExports/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.duplicate.exports
+
+module DuplicateExports {
+ exports exported;
+ exports exported;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/DuplicateModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.duplicate.module
+// key: compiler.err.module.name.mismatch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module blah {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateModule/modulesourcepath/m2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module blah {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/impl/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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 impl;
+
+import exported.Service;
+
+public class ServiceImplementation implements Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateProvides/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.duplicate.provides
+
+module DuplicateExports {
+ exports exported;
+ provides exported.Service with impl.ServiceImplementation;
+ provides exported.Service with impl.ServiceImplementation;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateRequires/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.duplicate.requires
+
+module DuplicateRequires {
+ requires java.se;
+ requires java.se;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateUses/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/DuplicateUses/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.duplicate.uses
+
+module DuplicateExports {
+ exports exported;
+ uses exported.Service;
+ uses exported.Service;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/IllegalArgumentForOption/IllegalArgumentForOption.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.illegal.argument.for.option
+// options: -modulepath doesNotExist
+// run: simple
+
+class X {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/InvalidArgForXPatch/InvalidArgForXpatch.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.locn.invalid.arg.for.xpatch
+// options: -Xpatch:blah
+
+class InvalidArgForXpatch {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleDeclSbInModuleInfoJava.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+//key: compiler.err.module.decl.sb.in.module-info.java
+
+module ModuleDeclSbInModuleInfoJava {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/Extra.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.module-info.with.xmodule.sourcepath
+// options: -Xmodule:java.compiler
+
+package javax.lang.model.element;
+
+public interface Extra {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXModuleSourcePath/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module java.compiler {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/ModuleInfoWithXmoduleClasspath.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.module-info.with.xmodule.classpath
+// options: -Xmodule:java.compiler
+
+package javax.lang.model.element;
+
+public interface ModuleInfoWithXModuleClasspath {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithXmoduleClasspath/additional/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module mod {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/ModuleInfoWithoutModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.expected.module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleInfoWithoutModule/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// No module description here
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/ModuleNameMismatch.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.module.name.mismatch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleNameMismatch/modulesourcepath/m/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module other {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleNotFound/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.module.not.found
+
+module m {
+ requires does.not.exist;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleNotFoundInModuleSourcePath/ModuleNotFoundInModuleSourcePath.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.module.not.found.in.module.source.path
+// options: -m m1 -modulesourcepath src
+
+class ModuleNotFoundInModuleSourcePath {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleSourcePathMustWithDashM/ModuleSourcePathMustWithDashM.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.modulesourcepath.must.be.specified.with.dash.m.option
+// options: -m m1 -d blah
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModulesNotSupportedInSource/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.modules.not.supported.in.source
+// key: compiler.warn.source.no.bootclasspath
+// options: -source 8 -Xlint:-path
+
+module ModulesNotSupportedInSource {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/MultiModuleOutputCannotBeExplodedModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.multi-module.outdir.cannot.be.exploded.module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/additional/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/MultiModuleOutputCannotBeExplodedModule/modulesourcepath/m2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m2 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/NotDefAccessClassPackageCantAccess.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.not.def.access.package.cant.access
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m1/p1/C1.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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 p1;
+
+public class C1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m2 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/NotDefAccessClassPackageCantAccess/modulesourcepath/m2/p2/C2.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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 p2;
+
+public class C2 {
+ p1.C1 c1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/PackageClashFromRequires.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.package.clash.from.requires
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/exported/Api1.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public class Api1 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module lib1 {
+ exports exported;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/exported/Api2.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public class Api2 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/lib2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module lib2 {
+ exports exported;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageClashFromRequires/modulesourcepath/use/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module use {
+ requires lib1;
+ requires lib2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/PackageEmptyOrNotFound.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.package.empty.or.not.found
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageEmptyOrNotFound/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {
+ exports p1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/PackageInOtherModule/PackageInOtherModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.package.in.other.module
+
+package java.util;
+
+class PackageInOtherModule {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ProcessorPathNoProcessorModulePath/ProcessorPathNoProcessorModulePath.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.processorpath.no.processormodulepath
+// options: -processormodulepath mods -processorpath mods
+
+class ProcessorPathNoProcessorModulePath {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.definition.is.inner
+// key: compiler.err.encl.class.required
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m {
+ provides p1.C1.InnerDefinition with p2.C2;
+ exports p1;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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 p1;
+
+public class C1 {
+ public class InnerDefinition {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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 p2;
+
+public class C2 extends p1.C1.InnerDefinition {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.definition.is.enum
+
+module m {
+ uses pkg.EnumST;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceDefinitionIsEnum/pkg/EnumST.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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 pkg;
+
+public enum EnumST {
+ A,
+ B
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/impl/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 impl;
+
+import exported.Service;
+
+public class ServiceImplementation implements Service {
+ public ServiceImplementation(int i) {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationDoesntHaveANoArgsConstructor/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.implementation.doesnt.have.a.no.args.constructor
+
+module ServiceImplementationDoesntHaveANoArgsConstructor {
+ exports exported;
+ provides exported.Service with impl.ServiceImplementation;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/impl/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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 impl;
+
+import exported.Service;
+
+public abstract class ServiceImplementation implements Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsAbstract/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.implementation.is.abstract
+
+module ServiceImplementationDoesntHaveANoArgsConstructor {
+ exports exported;
+ provides exported.Service with impl.ServiceImplementation;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/impl/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 impl;
+
+import exported.Service;
+
+public class ServiceImplementation {
+ public class Inner implements Service {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationIsInner/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.implementation.is.inner
+
+module ServiceImplementationIsInner {
+ exports exported;
+ provides exported.Service with impl.ServiceImplementation.Inner;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/impl/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 impl;
+
+import exported.Service;
+
+public class ServiceImplementation implements Service {
+ ServiceImplementation() {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNoArgsConstructorNotPublic/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.implementation.no.args.constructor.not.public
+
+module ServiceImplementationNoArgsConstructorNotPublic {
+ exports exported;
+ provides exported.Service with impl.ServiceImplementation;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/ServiceImplementationNotInRightModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.service.implementation.not.in.right.module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/Service.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public interface Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/exported/ServiceImplementation.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 exported;
+
+public class ServiceImplementation implements Service {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {
+ exports exported;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceImplementationNotInRightModule/modulesourcepath/m2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m2 {
+ requires m1;
+ provides exported.Service with exported.ServiceImplementation;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/ServiceProvidedButNotExportedOrUsed.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.warn.service.provided.but.not.exported.or.used
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m {
+ provides p1.C1 with p2.C2;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p1/C1.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 p1;
+
+public class C1 {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ServiceProvidedButNotExportedOrUsed/modulesourcepath/m/p2/C2.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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 p2;
+
+public class C2 extends p1.C1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/StatExprExpected.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.prob.found.req
+// key: compiler.misc.stat.expr.expected
+
+class StatExprExpected {
+ void test() {
+ Runnable r = () -> (foo());
+ }
+
+ int foo() { return 1; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TooManyModules/TooManyModules.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.too.many.modules
+
+class TooManyModules {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TooManyModules/p1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TooManyModules/p2/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m2 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/UnnamedPackageInNamedModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.unnamed.pkg.not.allowed.named.modules
+
+class UnnamedPackageInNamedModule {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/UnnamedPackageInNamedModule.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+class UnnamedPackageInNamedModule {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnnamedPackageInNamedModule/modulesourcepath/m1/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m1 {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/XModuleWithModulePath/XModuleWithModulePath.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.xmodule.no.module.sourcepath
+// options: -Xmodule:java.compiler -modulesourcepath src
+
+class XModuleWithModulePath {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.xaddexports.malformed.entry
+// options: -XaddExports:jdk.compiler/com.sun.tools.javac.util
+
+public class XaddexportsMalformedEntry {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.xaddexports.too.many
+// options: -XaddExports:jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED -XaddExports:jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+
+public class XaddexportsTooMany {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.xaddreads.malformed.entry
+// options: -XaddReads:jdk.compiler
+
+public class XaddreadsMalformedEntry {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+// key: compiler.err.xaddreads.too.many
+// options: -XaddReads:jdk.compiler=ALL-UNNAMED -XaddReads:jdk.compiler=ALL-UNNAMED
+
+public class XaddreadsTooMany {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8156954/T8156954.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8156954
+ * @summary javac incorrectly complains of incompatible types
+ * @compile T8156954.java
+ */
+import java.util.function.Function;
+
+class T8156954 {
+
+ <T, R> void m1(Function<R, T> f1, Function<T, R> f2, R r) { }
+ <T, R> void m2(Function<T, R> f1, Function<R, T> f2, R r) { }
+
+ void m(Integer intValue) {
+ m1(o -> o, o -> o , intValue);
+ m2(o -> o, o -> o , intValue);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8153884/T8153884.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,14 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8153884
+ * @summary Expression lambda erroneously compatible with void-returning descriptor
+ * @compile/fail/ref=T8153884.out -XDrawDiagnostics T8153884.java
+ */
+
+class T8153884 {
+ void test() {
+ Runnable r = () -> (foo());
+ }
+
+ void foo() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8153884/T8153884.out Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,2 @@
+T8153884.java:10:32: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
+1 error
--- a/langtools/test/tools/javac/lambda/LambdaExpr10.out Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaExpr10.out Thu May 19 19:47:04 2016 +0000
@@ -4,6 +4,6 @@
LambdaExpr10.java:24:46: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object)
LambdaExpr10.java:28:29: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object)
LambdaExpr10.java:29:33: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object)
-LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void))
-LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, void))
+LambdaExpr10.java:33:35: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
+LambdaExpr10.java:34:49: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
8 errors
--- a/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/lambda/LambdaExprNotVoid.out Thu May 19 19:47:04 2016 +0000
@@ -1,3 +1,3 @@
-LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void))
-LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, void))
+LambdaExprNotVoid.java:14:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
+LambdaExprNotVoid.java:15:21: compiler.err.prob.found.req: (compiler.misc.stat.expr.expected)
2 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180a.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.function.Consumer;
+import java.nio.ByteBuffer;
+
+/*
+ * @test
+ * @bug 8154180
+ * @summary Regression: stuck expressions do not behave correctly
+ * @compile T8154180a.java
+ */
+class T8154180a {
+ T8154180a(Consumer<ByteBuffer> cb) { }
+
+ public static void main(String[] args) {
+ new T8154180a(b -> System.out.println(asString(b)));
+ new T8154180a((b -> System.out.println(asString(b))));
+ new T8154180a(true ? b -> System.out.println(asString(b)) : b -> System.out.println(asString(b)));
+ new T8154180a((true ? b -> System.out.println(asString(b)) : b -> System.out.println(asString(b))));
+ new T8154180a((true ? (b -> System.out.println(asString(b))) : (b -> System.out.println(asString(b)))));
+ }
+
+ static String asString(ByteBuffer buf) {
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8154180
+ * @summary Regression: stuck expressions do not behave correctly
+ * @compile/fail/ref=T8154180b.out -XDrawDiagnostics T8154180b.java
+ */
+class T8154180b {
+ interface Foo1 {
+ Object m(String s);
+ }
+
+ interface Foo2 {
+ String m(String s);
+ }
+
+
+ void m(Foo1 f1) { }
+ void m(Foo2 f2) { }
+
+ void test() {
+ m(x->"");
+ m((x->""));
+ m(true ? x -> "" : x -> "");
+ m((true ? x -> "" : x -> ""));
+ m((true ? (x -> "") : (x -> "")));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/speculative/8154180/T8154180b.out Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,6 @@
+T8154180b.java:21:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b
+T8154180b.java:22:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b
+T8154180b.java:23:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b
+T8154180b.java:24:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b
+T8154180b.java:25:9: compiler.err.ref.ambiguous: m, kindname.method, m(T8154180b.Foo1), T8154180b, kindname.method, m(T8154180b.Foo2), T8154180b
+5 errors
--- a/langtools/test/tools/javac/unicode/Unmappable.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/unicode/Unmappable.java Thu May 19 19:47:04 2016 +0000
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
- * @bug 4767128 5048557 5048773
+ * @bug 4767128 5048557 5048773 8078559
* @summary diagnose encoding errors in Java source files
* @author gafter
*
--- a/langtools/test/tools/javac/unicode/Unmappable.out Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/javac/unicode/Unmappable.out Thu May 19 19:47:04 2016 +0000
@@ -1,2 +1,2 @@
-Unmappable.java:12:18: compiler.err.illegal.char.for.encoding: ascii
+Unmappable.java:12:18: compiler.err.illegal.char.for.encoding: E4, ascii
1 error
--- a/langtools/test/tools/jdeps/APIDeps.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/APIDeps.java Thu May 19 19:47:04 2016 +0000
@@ -25,6 +25,7 @@
* @test
* @bug 8015912 8029216 8048063 8050804
* @summary Test -apionly and -jdkinternals options
+ * @library lib
* @modules java.base/sun.security.x509
* java.management
* jdk.jdeps/com.sun.tools.classfile
@@ -154,7 +155,8 @@
Map<String,String> jdeps(String... args) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
- System.err.println("jdeps " + Arrays.toString(args));
+ System.err.println("jdeps " + Arrays.stream(args)
+ .collect(Collectors.joining(" ")));
int rc = com.sun.tools.jdeps.Main.run(args, pw);
pw.close();
String out = sw.toString();
--- a/langtools/test/tools/jdeps/Basic.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/Basic.java Thu May 19 19:47:04 2016 +0000
@@ -39,6 +39,8 @@
import java.nio.file.Path;
import java.util.*;
import java.util.regex.*;
+import java.util.stream.Collectors;
+
import static java.nio.file.StandardCopyOption.*;
public class Basic {
@@ -157,7 +159,7 @@
Map<String,String> jdeps(String... args) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
- System.err.println("jdeps " + Arrays.toString(args));
+ System.err.println("jdeps " + Arrays.stream(args).collect(Collectors.joining(" ")));
int rc = com.sun.tools.jdeps.Main.run(args, pw);
pw.close();
String out = sw.toString();
--- a/langtools/test/tools/jdeps/CompilerUtils.java Thu May 19 17:48:04 2016 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2016, 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.tools.JavaCompiler;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public final class CompilerUtils {
- private CompilerUtils() { }
-
- /**
- * Compile all the java sources in {@code <source>/**} to
- * {@code <destination>/**}. The destination directory will be created if
- * it doesn't exist.
- *
- * All warnings/errors emitted by the compiler are output to System.out/err.
- *
- * @return true if the compilation is successful
- *
- * @throws IOException if there is an I/O error scanning the source tree or
- * creating the destination directory
- */
- public static boolean compile(Path source, Path destination, String... options)
- throws IOException
- {
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
-
- List<Path> sources
- = Files.find(source, Integer.MAX_VALUE,
- (file, attrs) -> (file.toString().endsWith(".java")))
- .collect(Collectors.toList());
-
- Files.createDirectories(destination);
- jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
- Arrays.asList(destination));
-
- List<String> opts = Arrays.asList(options);
- JavaCompiler.CompilationTask task
- = compiler.getTask(null, jfm, null, opts, null,
- jfm.getJavaFileObjectsFromPaths(sources));
-
- return task.call();
- }
-
- /**
- * Compile the specified module from the given module sourcepath
- *
- * All warnings/errors emitted by the compiler are output to System.out/err.
- *
- * @return true if the compilation is successful
- *
- * @throws IOException if there is an I/O error scanning the source tree or
- * creating the destination directory
- */
- public static boolean compileModule(Path source, Path destination,
- String moduleName, String... options) {
- JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
- StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
-
- try {
- Files.createDirectories(destination);
- jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
- Arrays.asList(destination));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
-
- Stream<String> opts = Arrays.stream(new String[] {
- "-modulesourcepath", source.toString(), "-m", moduleName
- });
- List<String> javacOpts = Stream.concat(opts, Arrays.stream(options))
- .collect(Collectors.toList());
- JavaCompiler.CompilationTask task
- = compiler.getTask(null, jfm, null, javacOpts, null, null);
- return task.call();
- }
-
-
- public static void cleanDir(Path dir) throws IOException {
- if (Files.notExists(dir)) return;
-
- Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
- throws IOException
- {
- Files.delete(file);
- return FileVisitResult.CONTINUE;
- }
- @Override
- public FileVisitResult postVisitDirectory(Path dir, IOException e)
- throws IOException
- {
- if (e == null) {
- Files.delete(dir);
- return FileVisitResult.CONTINUE;
- } else {
- // directory iteration failed
- throw e;
- }
- }
- });
- Files.deleteIfExists(dir);
- }
-}
--- a/langtools/test/tools/jdeps/DotFileTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/DotFileTest.java Thu May 19 19:47:04 2016 +0000
@@ -41,6 +41,7 @@
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.*;
+import java.util.stream.Collectors;
public class DotFileTest {
public static void main(String... args) throws Exception {
@@ -182,7 +183,7 @@
// invoke jdeps
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
- System.err.println("jdeps " + args);
+ System.err.println("jdeps " + args.stream().collect(Collectors.joining(" ")));
int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[0]), pw);
pw.close();
String out = sw.toString();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/lib/CompilerUtils.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2016, 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.tools.JavaCompiler;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public final class CompilerUtils {
+ private CompilerUtils() { }
+
+ /**
+ * Compile all the java sources in {@code <source>/**} to
+ * {@code <destination>/**}. The destination directory will be created if
+ * it doesn't exist.
+ *
+ * All warnings/errors emitted by the compiler are output to System.out/err.
+ *
+ * @return true if the compilation is successful
+ *
+ * @throws IOException if there is an I/O error scanning the source tree or
+ * creating the destination directory
+ */
+ public static boolean compile(Path source, Path destination, String... options)
+ throws IOException
+ {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
+
+ List<Path> sources
+ = Files.find(source, Integer.MAX_VALUE,
+ (file, attrs) -> (file.toString().endsWith(".java")))
+ .collect(Collectors.toList());
+
+ Files.createDirectories(destination);
+ jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
+ Arrays.asList(destination));
+
+ List<String> opts = Arrays.asList(options);
+ JavaCompiler.CompilationTask task
+ = compiler.getTask(null, jfm, null, opts, null,
+ jfm.getJavaFileObjectsFromPaths(sources));
+
+ return task.call();
+ }
+
+ /**
+ * Compile the specified module from the given module sourcepath
+ *
+ * All warnings/errors emitted by the compiler are output to System.out/err.
+ *
+ * @return true if the compilation is successful
+ *
+ * @throws IOException if there is an I/O error scanning the source tree or
+ * creating the destination directory
+ */
+ public static boolean compileModule(Path source, Path destination,
+ String moduleName, String... options) {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null);
+
+ try {
+ Files.createDirectories(destination);
+ jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT,
+ Arrays.asList(destination));
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ Stream<String> opts = Arrays.stream(new String[] {
+ "-modulesourcepath", source.toString(), "-m", moduleName
+ });
+ List<String> javacOpts = Stream.concat(opts, Arrays.stream(options))
+ .collect(Collectors.toList());
+ JavaCompiler.CompilationTask task
+ = compiler.getTask(null, jfm, null, javacOpts, null, null);
+ return task.call();
+ }
+
+
+ public static void cleanDir(Path dir) throws IOException {
+ if (Files.notExists(dir)) return;
+
+ Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException
+ {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException e)
+ throws IOException
+ {
+ if (e == null) {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ } else {
+ // directory iteration failed
+ throw e;
+ }
+ }
+ });
+ Files.deleteIfExists(dir);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/lib/JdepsUtil.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2016, 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 com.sun.tools.jdeps.Analyzer;
+import com.sun.tools.jdeps.DepsAnalyzer;
+import com.sun.tools.jdeps.InverseDepsAnalyzer;
+import com.sun.tools.jdeps.JdepsConfiguration;
+import com.sun.tools.jdeps.JdepsFilter;
+import com.sun.tools.jdeps.JdepsWriter;
+import com.sun.tools.jdeps.ModuleAnalyzer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Utilities to run jdeps command
+ */
+public final class JdepsUtil {
+ /*
+ * Runs jdeps with the given arguments
+ */
+ public static String[] jdeps(String... args) {
+ String lineSep = System.getProperty("line.separator");
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ System.err.println("jdeps " + Arrays.stream(args).collect(Collectors.joining(" ")));
+ int rc = com.sun.tools.jdeps.Main.run(args, pw);
+ pw.close();
+ String out = sw.toString();
+ if (!out.isEmpty())
+ System.err.println(out);
+ if (rc != 0)
+ throw new Error("jdeps failed: rc=" + rc);
+ return out.split(lineSep);
+ }
+
+ public static Command newCommand(String cmd) {
+ return new Command(cmd);
+ }
+
+ public static class Command {
+
+ final StringWriter sw = new StringWriter();
+ final PrintWriter pw = new PrintWriter(sw);
+ final JdepsFilter.Builder filter = new JdepsFilter.Builder().filter(true, true);
+ final JdepsConfiguration.Builder builder = new JdepsConfiguration.Builder();
+ final Set<String> requires = new HashSet<>();
+
+ Analyzer.Type verbose = Analyzer.Type.PACKAGE;
+ boolean apiOnly = false;
+
+ public Command(String cmd) {
+ System.err.println("============ ");
+ System.err.println(cmd);
+ }
+
+ public Command verbose(String verbose) {
+ switch (verbose) {
+ case "-verbose":
+ this.verbose = Analyzer.Type.VERBOSE;
+ filter.filter(false, false);
+ break;
+ case "-verbose:package":
+ this.verbose = Analyzer.Type.PACKAGE;
+ break;
+ case "-verbose:class":
+ this.verbose = Analyzer.Type.CLASS;
+ break;
+ case "-summary":
+ this.verbose = Analyzer.Type.SUMMARY;
+ break;
+ default:
+ throw new IllegalArgumentException(verbose);
+ }
+ return this;
+ }
+
+ public Command filter(String value) {
+ switch (value) {
+ case "-filter:package":
+ filter.filter(true, false);
+ break;
+ case "-filter:archive":
+ case "-filter:module":
+ filter.filter(false, true);
+ break;
+ default:
+ throw new IllegalArgumentException(value);
+ }
+ return this;
+ }
+
+ public Command addClassPath(String classpath) {
+ builder.addClassPath(classpath);
+ return this;
+ }
+
+ public Command addRoot(Path path) {
+ builder.addRoot(path);
+ return this;
+ }
+
+ public Command appModulePath(String modulePath) {
+ builder.appModulePath(modulePath);
+ return this;
+ }
+
+ public Command addmods(Set<String> mods) {
+ builder.addmods(mods);
+ return this;
+ }
+
+ public Command requires(Set<String> mods) {
+ requires.addAll(mods);
+ return this;
+ }
+
+ public Command matchPackages(Set<String> pkgs) {
+ filter.packages(pkgs);
+ return this;
+ }
+
+ public Command regex(String regex) {
+ filter.regex(Pattern.compile(regex));
+ return this;
+ }
+
+ public Command include(String regex) {
+ filter.includePattern(Pattern.compile(regex));
+ return this;
+ }
+
+ public Command includeSystemMoudles(String regex) {
+ filter.includeSystemModules(Pattern.compile(regex));
+ return this;
+ }
+
+ public Command apiOnly() {
+ this.apiOnly = true;
+ return this;
+ }
+
+ public JdepsConfiguration configuration() throws IOException {
+ JdepsConfiguration config = builder.build();
+ requires.forEach(name -> {
+ ModuleDescriptor md = config.findModuleDescriptor(name).get();
+ filter.requires(name, md.packages());
+ });
+ return config;
+ }
+
+ private JdepsWriter writer() {
+ return JdepsWriter.newSimpleWriter(pw, verbose);
+ }
+
+ public DepsAnalyzer getDepsAnalyzer() throws IOException {
+ return new DepsAnalyzer(configuration(), filter.build(), writer(),
+ verbose, apiOnly);
+ }
+
+ public ModuleAnalyzer getModuleAnalyzer(Set<String> mods) throws IOException {
+ // if -check is set, add to the root set and all modules are observable
+ addmods(mods);
+ builder.allModules();
+ return new ModuleAnalyzer(configuration(), pw, mods);
+ }
+
+ public InverseDepsAnalyzer getInverseDepsAnalyzer() throws IOException {
+ return new InverseDepsAnalyzer(configuration(), filter.build(), writer(),
+ verbose, false);
+ }
+
+ public void dumpOutput(PrintStream out) {
+ out.println(sw.toString());
+ }
+ }
+
+ /**
+ * Create a jar file using the list of files provided.
+ */
+ public static void createJar(Path jarfile, Path root, Stream<Path> files)
+ throws IOException {
+ Path dir = jarfile.getParent();
+ if (dir != null && Files.notExists(dir)) {
+ Files.createDirectories(dir);
+ }
+ try (JarOutputStream target = new JarOutputStream(
+ Files.newOutputStream(jarfile))) {
+ files.forEach(file -> add(root.relativize(file), file, target));
+ }
+ }
+
+ private static void add(Path path, Path source, JarOutputStream target) {
+ try {
+ String name = path.toString().replace(File.separatorChar, '/');
+ JarEntry entry = new JarEntry(name);
+ entry.setTime(source.toFile().lastModified());
+ target.putNextEntry(entry);
+ Files.copy(source, target);
+ target.closeEntry();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+}
--- a/langtools/test/tools/jdeps/m/Foo.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/m/Foo.java Thu May 19 19:47:04 2016 +0000
@@ -30,4 +30,3 @@
setF(new f.F());
}
}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/CheckModuleTest.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016, 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
+ * @summary Tests split packages
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng CheckModuleTest
+ */
+
+import java.lang.module.ModuleDescriptor;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+
+import com.sun.tools.jdeps.ModuleAnalyzer;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertEquals;
+
+
+public class CheckModuleTest {
+ private static final String TEST_SRC = System.getProperty("test.src");
+ private static final String TEST_CLASSES = System.getProperty("test.classes");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+
+ // m4 and m5 are analyzed. Others are compiled to make sure they are present
+ // on the module path for analysis
+ private static final Set<String> modules = Set.of("unsafe", "m4", "m5", "m6", "m7", "m8");
+
+ private static final String JAVA_BASE = "java.base";
+
+ /**
+ * Compiles classes used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Exception {
+ CompilerUtils.cleanDir(MODS_DIR);
+ modules.forEach(mn ->
+ assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
+ }
+
+ @DataProvider(name = "javaBase")
+ public Object[][] base() {
+ return new Object[][] {
+ { JAVA_BASE, new ModuleMetaData(JAVA_BASE)
+ },
+ };
+ };
+
+ @Test(dataProvider = "javaBase")
+ public void testJavaBase(String name, ModuleMetaData data) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -check %s -mp %s%n", name, MODS_DIR)
+ );
+ jdeps.appModulePath(MODS_DIR.toString());
+
+ ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name));
+ assertTrue(analyzer.run());
+ jdeps.dumpOutput(System.err);
+
+ ModuleDescriptor[] descriptors = analyzer.descriptors(name);
+ for (int i=0; i < 3; i++) {
+ descriptors[i].requires().stream()
+ .forEach(req -> data.checkRequires(req));
+ }
+ }
+
+ @DataProvider(name = "modules")
+ public Object[][] unnamed() {
+ return new Object[][]{
+ { "m4", new ModuleMetaData[] {
+ // original
+ new ModuleMetaData("m4")
+ .requiresPublic("java.compiler")
+ .requires("java.logging")
+ // unnused exports
+ .exports("p4.internal", Set.of("m6", "m7")),
+ // suggested version
+ new ModuleMetaData("m4")
+ .requires("java.compiler"),
+ // reduced version
+ new ModuleMetaData("m4")
+ .requires("java.compiler")
+ }
+ },
+ { "m5", new ModuleMetaData[] {
+ // original
+ new ModuleMetaData("m5")
+ .requiresPublic("java.compiler")
+ .requiresPublic("java.logging")
+ .requires("java.sql")
+ .requiresPublic("m4"),
+ // suggested version
+ new ModuleMetaData("m5")
+ .requiresPublic("java.compiler")
+ .requires("java.logging")
+ .requiresPublic("java.sql")
+ .requiresPublic("m4"),
+ // reduced version
+ new ModuleMetaData("m5")
+ .requiresPublic("java.compiler")
+ .requiresPublic("java.sql")
+ .requiresPublic("m4"),
+ }
+ },
+ };
+ }
+
+ @Test(dataProvider = "modules")
+ public void modularTest(String name, ModuleMetaData[] data) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -check %s -mp %s%n", name, MODS_DIR)
+ );
+ jdeps.appModulePath(MODS_DIR.toString());
+
+ ModuleAnalyzer analyzer = jdeps.getModuleAnalyzer(Set.of(name));
+ assertTrue(analyzer.run());
+ jdeps.dumpOutput(System.err);
+
+ // compare the module descriptors and the suggested versions
+ ModuleDescriptor[] descriptors = analyzer.descriptors(name);
+ for (int i=0; i < 3; i++) {
+ ModuleMetaData metaData = data[i];
+ descriptors[i].requires().stream()
+ .forEach(req -> metaData.checkRequires(req));
+ }
+
+ Map<String, Set<String>> unused = analyzer.unusedQualifiedExports(name);
+ // verify unuused qualified exports
+ assertEquals(unused, data[0].exports);
+ }
+
+}
--- a/langtools/test/tools/jdeps/modules/GenModuleInfo.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/modules/GenModuleInfo.java Thu May 19 19:47:04 2016 +0000
@@ -24,8 +24,8 @@
/*
* @test
* @summary Tests jdeps -genmoduleinfo option
- * @library ..
- * @build CompilerUtils
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil
* @modules jdk.jdeps/com.sun.tools.jdeps
* @run testng GenModuleInfo
*/
@@ -39,16 +39,12 @@
import java.util.Arrays;
import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import org.testng.annotations.DataProvider;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
-
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -86,7 +82,7 @@
for (String mn : modules) {
Path root = MODS_DIR.resolve(mn);
- createJar(LIBS_DIR.resolve(mn + ".jar"), root,
+ JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root,
Files.walk(root, Integer.MAX_VALUE)
.filter(f -> {
String fn = f.getFileName().toString();
@@ -100,7 +96,7 @@
Stream<String> files = Arrays.stream(modules)
.map(mn -> LIBS_DIR.resolve(mn + ".jar"))
.map(Path::toString);
- jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new));
+ JdepsUtil.jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new));
}
@Test
@@ -109,7 +105,7 @@
.map(mn -> LIBS_DIR.resolve(mn + ".jar"))
.map(Path::toString);
- jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()),
+ JdepsUtil.jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()),
files)
.toArray(String[]::new));
@@ -148,7 +144,7 @@
try (InputStream in1 = Files.newInputStream(p1);
InputStream in2 = Files.newInputStream(p2)) {
verify(ModuleDescriptor.read(in1),
- ModuleDescriptor.read(in2, () -> packages(MODS_DIR.resolve(mn))));
+ ModuleDescriptor.read(in2, () -> packages(MODS_DIR.resolve(mn))));
}
}
}
@@ -188,46 +184,4 @@
}
}
- /*
- * Runs jdeps with the given arguments
- */
- public static String[] jdeps(String... args) {
- String lineSep = System.getProperty("line.separator");
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- System.err.println("jdeps " + Arrays.toString(args));
- int rc = com.sun.tools.jdeps.Main.run(args, pw);
- pw.close();
- String out = sw.toString();
- if (!out.isEmpty())
- System.err.println(out);
- if (rc != 0)
- throw new Error("jdeps failed: rc=" + rc);
- return out.split(lineSep);
- }
-
- /**
- * Create a jar file using the list of files provided.
- */
- public static void createJar(Path jarfile, Path root, Stream<Path> files)
- throws IOException {
- try (JarOutputStream target = new JarOutputStream(
- Files.newOutputStream(jarfile))) {
- files.forEach(file -> add(root.relativize(file), file, target));
- }
- }
-
- private static void add(Path path, Path source, JarOutputStream target) {
- try {
- String name = path.toString().replace(File.separatorChar, '/');
- JarEntry entry = new JarEntry(name);
- entry.setTime(source.toFile().lastModified());
- target.putNextEntry(entry);
- Files.copy(source, target);
- target.closeEntry();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/InverseDeps.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2016, 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
+ * @summary Tests split packages
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng InverseDeps
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.jdeps.Archive;
+import com.sun.tools.jdeps.InverseDepsAnalyzer;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertEquals;
+
+
+public class InverseDeps {
+ private static final String TEST_SRC = System.getProperty("test.src");
+ private static final String TEST_CLASSES = System.getProperty("test.classes");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+ private static final Path LIBS_DIR = Paths.get("libs");
+
+ private static final Set<String> modules = new LinkedHashSet(
+ List.of("unsafe", "m4", "m5", "m6", "m7")
+ );
+
+ /**
+ * Compiles classes used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Exception {
+ CompilerUtils.cleanDir(MODS_DIR);
+
+ for (String mn : modules) {
+ // compile a module
+ assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn));
+
+ // create JAR files with no module-info.class
+ Path root = MODS_DIR.resolve(mn);
+ JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root,
+ Files.walk(root, Integer.MAX_VALUE)
+ .filter(f -> {
+ String fn = f.getFileName().toString();
+ return fn.endsWith(".class") && !fn.equals("module-info.class");
+ }));
+ }
+ }
+
+ @DataProvider(name = "testrequires")
+ public Object[][] expected1() {
+ return new Object[][] {
+ // -requires and result
+ { "java.sql", new String[][] {
+ new String[] { "java.sql", "m5" },
+ }
+ },
+ { "java.compiler", new String[][] {
+ new String[] { "java.compiler", "m5" },
+ new String[] { "java.compiler", "m4", "m5" },
+ }
+ },
+ { "java.logging", new String[][]{
+ new String[] {"java.logging", "m5"},
+ new String[] {"java.logging", "m4", "m5"},
+ new String[] {"java.logging", "java.sql", "m5"},
+ }
+ },
+ { "jdk.unsupported", new String[][] {
+ new String[] {"jdk.unsupported", "unsafe", "m6", "m7"},
+ new String[] {"jdk.unsupported", "unsafe", "m7"}
+ }
+ },
+ };
+ }
+
+ @Test(dataProvider = "testrequires")
+ public void testrequires(String name, String[][] expected) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -modulepath %s -requires %s -addmods %s%n",
+ MODS_DIR, name, modules.stream().collect(Collectors.joining(","))
+ ));
+ jdeps.appModulePath(MODS_DIR.toString())
+ .addmods(modules)
+ .requires(Set.of(name));
+
+ runJdeps(jdeps, expected);
+
+ // automatic module
+ jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -modulepath %s -requires %s -addmods ALL-MODULE-PATH%n",
+ LIBS_DIR, name)
+ );
+ jdeps.appModulePath(MODS_DIR.toString())
+ .addmods(Set.of("ALL-MODULE-PATH"))
+ .requires(Set.of(name));
+
+ runJdeps(jdeps, expected);
+ }
+
+ @DataProvider(name = "testpackage")
+ public Object[][] expected2() {
+ return new Object[][] {
+ // -package and result
+ { "p4", new String[][] {
+ new String[] { "m4", "m5"},
+ }
+ },
+ { "javax.tools", new String[][] {
+ new String[] {"java.compiler", "m5"},
+ new String[] {"java.compiler", "m4", "m5"},
+ }
+ },
+ { "sun.misc", new String[][] {
+ new String[] {"jdk.unsupported", "unsafe", "m6", "m7"},
+ new String[] {"jdk.unsupported", "unsafe", "m7"}
+ }
+ }
+ };
+ }
+
+ @Test(dataProvider = "testpackage")
+ public void testpackage(String name, String[][] expected) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -modulepath %s -package %s -addmods %s%n",
+ MODS_DIR, name, modules.stream().collect(Collectors.joining(","))
+ ));
+ jdeps.appModulePath(MODS_DIR.toString())
+ .addmods(modules)
+ .matchPackages(Set.of(name));
+
+ runJdeps(jdeps, expected);
+ }
+
+ @DataProvider(name = "testregex")
+ public Object[][] expected3() {
+ return new Object[][] {
+ // -regex and result
+ { "org.safe.Lib", new String[][] {
+ new String[] { "unsafe", "m7"},
+ new String[] { "unsafe", "m6", "m7"},
+ }
+ },
+ { "java.util.logging.*|org.safe.Lib", new String[][] {
+ new String[] { "unsafe", "m7"},
+ new String[] { "unsafe", "m6", "m7"},
+ new String[] { "java.logging", "m5"},
+ }
+ }
+ };
+ }
+
+ @Test(dataProvider = "testregex")
+ public void testregex(String name, String[][] expected) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -modulepath %s -regex %s -addmods %s%n",
+ MODS_DIR, name, modules.stream().collect(Collectors.joining(",")))
+ );
+
+ jdeps.appModulePath(MODS_DIR.toString())
+ .addmods(modules)
+ .regex(name);
+
+ runJdeps(jdeps, expected);
+ }
+
+ @DataProvider(name = "classpath")
+ public Object[][] expected4() {
+ return new Object[][] {
+ // -regex and result
+ { "sun.misc.Unsafe", new String[][] {
+ new String[] {"jdk.unsupported", "unsafe.jar", "m6.jar", "m7.jar"},
+ new String[] {"jdk.unsupported", "unsafe.jar", "m7.jar"}
+ }
+ },
+ { "org.safe.Lib", new String[][] {
+ new String[] { "unsafe.jar", "m7.jar"},
+ new String[] { "unsafe.jar", "m6.jar", "m7.jar"},
+ }
+ },
+ { "java.util.logging.*|org.safe.Lib", new String[][] {
+ new String[] { "unsafe.jar", "m7.jar"},
+ new String[] { "unsafe.jar", "m6.jar", "m7.jar"},
+ new String[] { "java.logging", "m5.jar"},
+ }
+ }
+ };
+ }
+
+ @Test(dataProvider = "classpath")
+ public void testClassPath(String name, String[][] expected) throws Exception {
+ // -classpath
+ String cpath = modules.stream()
+ .filter(mn -> !mn.equals("m7"))
+ .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString())
+ .collect(Collectors.joining(File.pathSeparator));
+
+ Path jarfile = LIBS_DIR.resolve("m7.jar");
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -classpath %s -regex %s %s%n",
+ cpath, name, jarfile)
+ );
+ jdeps.verbose("-verbose:class")
+ .addClassPath(cpath)
+ .regex(name).addRoot(jarfile);
+ runJdeps(jdeps, expected);
+
+ // all JAR files on the command-line arguments
+ Set<Path> paths = modules.stream()
+ .map(mn -> LIBS_DIR.resolve(mn + ".jar"))
+ .collect(Collectors.toSet());
+ jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -inverse -regex %s %s%n", name, paths)
+ );
+ jdeps.verbose("-verbose:class").regex(name);
+ paths.forEach(jdeps::addRoot);
+ runJdeps(jdeps, expected);
+
+ }
+
+ private void runJdeps(JdepsUtil.Command jdeps, String[][] expected) throws Exception {
+ InverseDepsAnalyzer analyzer = jdeps.getInverseDepsAnalyzer();
+
+ assertTrue(analyzer.run());
+
+ // get the inverse transitive dependences
+ List<String[]> paths = analyzer.inverseDependences().stream()
+ .map(deque -> deque.stream()
+ .map(Archive::getName)
+ .collect(Collectors.toList()).toArray(new String[0]))
+ .collect(Collectors.toList());
+
+ jdeps.dumpOutput(System.err);
+ paths.forEach(path -> System.err.println(Arrays.stream(path)
+ .collect(Collectors.joining(" <- "))));
+
+ // verify the dependences
+ assertEquals(paths.size(), expected.length);
+
+ for (int i=0; i < paths.size(); i++) {
+ String[] path = paths.get(i);
+ boolean noneMatched = Arrays.stream(expected)
+ .filter(array -> array.length == path.length)
+ .noneMatch(array -> Arrays.equals(array, path));
+ if (noneMatched)
+ System.err.format("Expected: %s found: %s%n",
+ Arrays.stream(expected)
+ .map(Arrays::toString)
+ .collect(Collectors.joining(", ")),
+ Arrays.toString(path));
+
+ assertFalse(noneMatched);
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/ModuleMetaData.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2016, 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 com.sun.tools.jdeps.DepsAnalyzer;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static com.sun.tools.jdeps.DepsAnalyzer.Info.*;
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+import static java.lang.module.ModuleDescriptor.*;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+
+public class ModuleMetaData {
+ public static final String JAVA_BASE = "java.base";
+
+ static final String INTERNAL = "(internal)";
+ static final String QUALIFIED = "(qualified)";
+ static final String JDK_INTERNAL = "JDK internal API";
+
+ final String moduleName;
+ final boolean isNamed;
+ final Map<String, ModuleRequires> requires = new LinkedHashMap<>();
+ final Map<String, Dependence> references = new LinkedHashMap<>();
+ final Map<String, Set<String>> exports = new LinkedHashMap<>();
+
+ ModuleMetaData(String name) {
+ this(name, true);
+ }
+
+ ModuleMetaData(String name, boolean isNamed) {
+ this.moduleName = name;
+ this.isNamed = isNamed;
+ requires(JAVA_BASE); // implicit requires
+ }
+
+ String name() {
+ return moduleName;
+ }
+
+ ModuleMetaData requires(String name) {
+ requires.put(name, new ModuleRequires(name));
+ return this;
+ }
+
+ ModuleMetaData requiresPublic(String name) {
+ requires.put(name, new ModuleRequires(name, PUBLIC));
+ return this;
+ }
+
+ // for unnamed module
+ ModuleMetaData depends(String name) {
+ requires.put(name, new ModuleRequires(name));
+ return this;
+ }
+
+ ModuleMetaData reference(String origin, String target, String module) {
+ return dependence(origin, target, module, "");
+ }
+
+ ModuleMetaData internal(String origin, String target, String module) {
+ return dependence(origin, target, module, INTERNAL);
+ }
+
+ ModuleMetaData qualified(String origin, String target, String module) {
+ return dependence(origin, target, module, QUALIFIED);
+ }
+
+ ModuleMetaData jdkInternal(String origin, String target, String module) {
+ return dependence(origin, target, module, JDK_INTERNAL);
+ }
+
+ ModuleMetaData exports(String pn, Set<String> targets) {
+ exports.put(pn, targets);
+ return this;
+ }
+
+ private ModuleMetaData dependence(String origin, String target, String module, String access) {
+ references.put(key(origin, target), new Dependence(origin, target, module, access));
+ return this;
+ }
+
+ String key(String origin, String target) {
+ return origin + ":" + target;
+ }
+
+ void checkRequires(String name, Set<DepsAnalyzer.Node> adjacentNodes) {
+ // System.err.format("%s: Expected %s Found %s %n", name, requires, adjacentNodes);
+ adjacentNodes.stream()
+ .forEach(v -> checkRequires(v.name));
+ assertEquals(adjacentNodes.size(), requires.size());
+ }
+
+ void checkRequires(String name) {
+ ModuleRequires req = requires.get(name);
+ if (req == null)
+ System.err.println(moduleName + ": unexpected requires " + name);
+ assertTrue(requires.containsKey(name));
+ }
+
+ void checkRequires(Requires require) {
+ String name = require.name();
+ if (name.equals(JAVA_BASE))
+ return;
+
+ ModuleRequires req = requires.get(name);
+ if (req == null)
+ System.err.format("%s: unexpected dependence %s%n", moduleName, name);
+
+ assertTrue(requires.containsKey(name));
+
+ assertEquals(require.modifiers(), req.modifiers());
+ }
+
+ void checkDependences(String name, Set<DepsAnalyzer.Node> adjacentNodes) {
+ // System.err.format("%s: Expected %s Found %s %n", name, references, adjacentNodes);
+
+ adjacentNodes.stream()
+ .forEach(v -> checkDependence(name, v.name, v.source, v.info));
+ assertEquals(adjacentNodes.size(), references.size());
+ }
+
+ void checkDependence(String origin, String target, String module, DepsAnalyzer.Info info) {
+ String key = key(origin, target);
+ Dependence dep = references.get(key);
+ String access = "";
+ if (info == QUALIFIED_EXPORTED_API)
+ access = QUALIFIED;
+ else if (info == JDK_INTERNAL_API)
+ access = JDK_INTERNAL;
+ else if (info == INTERNAL_API)
+ access = INTERNAL;
+
+ assertTrue(references.containsKey(key));
+
+ assertEquals(dep.access, access);
+ assertEquals(dep.module, module);
+ }
+
+
+ public static class ModuleRequires {
+ final String name;
+ final Requires.Modifier mod;
+
+ ModuleRequires(String name) {
+ this.name = name;
+ this.mod = null;
+ }
+
+ ModuleRequires(String name, Requires.Modifier mod) {
+ this.name = name;
+ this.mod = mod;
+ }
+
+ Set<Requires.Modifier> modifiers() {
+ return mod != null ? Set.of(mod) : Collections.emptySet();
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ public static class Dependence {
+ final String origin;
+ final String target;
+ final String module;
+ final String access;
+
+ Dependence(String origin, String target, String module, String access) {
+ this.origin = origin;
+ this.target = target;
+ this.module = module;
+ this.access = access;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s -> %s (%s) %s", origin, target, module, access);
+ }
+ }
+}
--- a/langtools/test/tools/jdeps/modules/ModuleTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/modules/ModuleTest.java Thu May 19 19:47:04 2016 +0000
@@ -24,30 +24,28 @@
/*
* @test
* @summary Tests jdeps -m and -mp options on named modules and unnamed modules
- * @library ..
- * @build CompilerUtils
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil
* @modules jdk.jdeps/com.sun.tools.jdeps
* @run testng ModuleTest
*/
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
-import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
-
import java.util.stream.Collectors;
+
+import com.sun.tools.jdeps.DepsAnalyzer;
+import com.sun.tools.jdeps.Graph;
import org.testng.annotations.DataProvider;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
public class ModuleTest {
@@ -56,6 +54,7 @@
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
private static final Path MODS_DIR = Paths.get("mods");
+ private static final Path UNNAMED_DIR = Paths.get("unnamed");
// the names of the modules in this test
private static final String UNSUPPORTED = "unsupported";
@@ -66,62 +65,68 @@
@BeforeTest
public void compileAll() throws Exception {
CompilerUtils.cleanDir(MODS_DIR);
+ CompilerUtils.cleanDir(UNNAMED_DIR);
+
assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED,
"-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED));
// m4 is not referenced
Arrays.asList("m1", "m2", "m3", "m4")
.forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn)));
+
+ assertTrue(CompilerUtils.compile(SRC_DIR.resolve("m3"), UNNAMED_DIR, "-mp", MODS_DIR.toString()));
+ Files.delete(UNNAMED_DIR.resolve("module-info.class"));
}
@DataProvider(name = "modules")
public Object[][] expected() {
return new Object[][]{
- { "m3", new Data("m3").requiresPublic("java.sql")
- .requiresPublic("m2")
- .requires("java.logging")
- .requiresPublic("m1")
- .reference("p3", "java.lang", "java.base")
- .reference("p3", "java.sql", "java.sql")
- .reference("p3", "java.util.logging", "java.logging")
- .reference("p3", "p1", "m1")
- .reference("p3", "p2", "m2")
- .qualified("p3", "p2.internal", "m2")
+ { "m3", new ModuleMetaData("m3").requiresPublic("java.sql")
+ .requiresPublic("m2")
+ .requires("java.logging")
+ .requiresPublic("m1")
+ .reference("p3", "java.lang", "java.base")
+ .reference("p3", "java.sql", "java.sql")
+ .reference("p3", "java.util.logging", "java.logging")
+ .reference("p3", "p1", "m1")
+ .reference("p3", "p2", "m2")
+ .qualified("p3", "p2.internal", "m2")
},
- { "m2", new Data("m2").requiresPublic("m1")
- .reference("p2", "java.lang", "java.base")
- .reference("p2", "p1", "m1")
- .reference("p2.internal", "java.lang", "java.base")
- .reference("p2.internal", "java.io", "java.base")
+ { "m2", new ModuleMetaData("m2").requiresPublic("m1")
+ .reference("p2", "java.lang", "java.base")
+ .reference("p2", "p1", "m1")
+ .reference("p2.internal", "java.lang", "java.base")
+ .reference("p2.internal", "java.io", "java.base")
},
- { "m1", new Data("m1").requires("unsupported")
- .reference("p1", "java.lang", "java.base")
- .reference("p1.internal", "java.lang", "java.base")
- .reference("p1.internal", "p1", "m1")
- .reference("p1.internal", "q", "unsupported")
+ { "m1", new ModuleMetaData("m1").requires("unsupported")
+ .reference("p1", "java.lang", "java.base")
+ .reference("p1.internal", "java.lang", "java.base")
+ .reference("p1.internal", "p1", "m1")
+ .reference("p1.internal", "q", "unsupported")
},
- { "unsupported", new Data("unsupported")
- .reference("q", "java.lang", "java.base")
- .jdkInternal("q", "jdk.internal.perf", "(java.base)")
+ { "unsupported", new ModuleMetaData("unsupported")
+ .reference("q", "java.lang", "java.base")
+ .jdkInternal("q", "jdk.internal.perf", "java.base")
},
};
}
@Test(dataProvider = "modules")
- public void modularTest(String name, Data data) {
- // print only the specified module
- String excludes = Arrays.stream(modules)
- .filter(mn -> !mn.endsWith(name))
- .collect(Collectors.joining(","));
- String[] result = jdeps("-exclude-modules", excludes,
- "-mp", MODS_DIR.toString(),
- "-m", name);
- assertTrue(data.check(result));
+ public void modularTest(String name, ModuleMetaData data) throws IOException {
+ // jdeps -modulepath mods -m <name>
+ runTest(data, MODS_DIR.toString(), Set.of(name));
+
+ // jdeps -modulepath libs/m1.jar:.... -m <name>
+ String mp = Arrays.stream(modules)
+ .filter(mn -> !mn.equals(name))
+ .map(mn -> MODS_DIR.resolve(mn).toString())
+ .collect(Collectors.joining(File.pathSeparator));
+ runTest(data, mp, Collections.emptySet(), MODS_DIR.resolve(name));
}
@DataProvider(name = "unnamed")
public Object[][] unnamed() {
return new Object[][]{
- { "m3", new Data("m3", false)
+ { "unnamed", new ModuleMetaData("unnamed", false)
.depends("java.sql")
.depends("java.logging")
.depends("m1")
@@ -133,178 +138,43 @@
.reference("p3", "p2", "m2")
.internal("p3", "p2.internal", "m2")
},
- { "unsupported", new Data("unsupported", false)
- .reference("q", "java.lang", "java.base")
- .jdkInternal("q", "jdk.internal.perf", "(java.base)")
- },
};
}
@Test(dataProvider = "unnamed")
- public void unnamedTest(String name, Data data) {
- String[] result = jdeps("-mp", MODS_DIR.toString(), MODS_DIR.resolve(name).toString());
- assertTrue(data.check(result));
- }
-
- /*
- * Runs jdeps with the given arguments
- */
- public static String[] jdeps(String... args) {
- String lineSep = System.getProperty("line.separator");
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- System.err.println("jdeps " + Arrays.toString(args));
- int rc = com.sun.tools.jdeps.Main.run(args, pw);
- pw.close();
- String out = sw.toString();
- if (!out.isEmpty())
- System.err.println(out);
- if (rc != 0)
- throw new Error("jdeps failed: rc=" + rc);
- return out.split(lineSep);
+ public void unnamedTest(String name, ModuleMetaData data) throws IOException {
+ runTest(data, MODS_DIR.toString(), Set.of("m1", "m2"), UNNAMED_DIR);
}
- static class Data {
- static final String INTERNAL = "(internal)";
- static final String QUALIFIED = "(qualified)";
- static final String JDK_INTERNAL = "JDK internal API";
-
- final String moduleName;
- final boolean isNamed;
- final Map<String, ModuleRequires> requires = new LinkedHashMap<>();
- final Map<String, Dependence> references = new LinkedHashMap<>();
- Data(String name) {
- this(name, true);
- }
- Data(String name, boolean isNamed) {
- this.moduleName = name;
- this.isNamed = isNamed;
- requires("java.base"); // implicit requires
- }
+ private void runTest(ModuleMetaData data, String modulepath,
+ Set<String> roots, Path... paths)
+ throws IOException
+ {
+ // jdeps -modulepath <modulepath> -m root paths
- Data requires(String name) {
- requires.put(name, new ModuleRequires(name));
- return this;
- }
- Data requiresPublic(String name) {
- requires.put(name, new ModuleRequires(name, PUBLIC));
- return this;
- }
- // for unnamed module
- Data depends(String name) {
- requires.put(name, new ModuleRequires(name));
- return this;
- }
- Data reference(String origin, String target, String module) {
- return dependence(origin, target, module, "");
- }
- Data internal(String origin, String target, String module) {
- return dependence(origin, target, module, INTERNAL);
- }
- Data qualified(String origin, String target, String module) {
- return dependence(origin, target, module, QUALIFIED);
- }
- Data jdkInternal(String origin, String target, String module) {
- return dependence(origin, target, module, JDK_INTERNAL);
- }
- private Data dependence(String origin, String target, String module, String access) {
- references.put(key(origin, target), new Dependence(origin, target, module, access));
- return this;
- }
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -modulepath %s -addmods %s %s%n", MODS_DIR,
+ roots.stream().collect(Collectors.joining(",")), paths)
+ );
+ jdeps.appModulePath(modulepath)
+ .addmods(roots);
+ Arrays.stream(paths).forEach(jdeps::addRoot);
- String key(String origin, String target) {
- return origin+":"+target;
- }
- boolean check(String[] lines) {
- System.out.format("verifying module %s%s%n", moduleName, isNamed ? "" : " (unnamed module)");
- for (String l : lines) {
- String[] tokens = l.trim().split("\\s+");
- System.out.println(" " + Arrays.stream(tokens).collect(Collectors.joining(" ")));
- switch (tokens[0]) {
- case "module":
- assertEquals(tokens.length, 2);
- assertEquals(moduleName, tokens[1]);
- break;
- case "requires":
- String name = tokens.length == 2 ? tokens[1] : tokens[2];
- Modifier modifier = null;
- if (tokens.length == 3) {
- assertEquals("public", tokens[1]);
- modifier = PUBLIC;
- }
- checkRequires(name, modifier);
- break;
- default:
- if (tokens.length == 3) {
- // unnamed module requires
- assertFalse(isNamed);
- assertEquals(moduleName, tokens[0]);
- String mn = tokens[2];
- checkRequires(mn, null);
- } else {
- checkDependence(tokens);
- }
- }
- }
- return true;
- }
-
- private void checkRequires(String name, Modifier modifier) {
- assertTrue(requires.containsKey(name));
- ModuleRequires req = requires.get(name);
- assertEquals(req.mod, modifier);
- }
+ // run the analyzer
+ DepsAnalyzer analyzer = jdeps.getDepsAnalyzer();
+ assertTrue(analyzer.run());
- private void checkDependence(String[] tokens) {
- assertTrue(tokens.length >= 4);
- String origin = tokens[0];
- String target = tokens[2];
- String module = tokens[3];
- String key = key(origin, target);
- assertTrue(references.containsKey(key));
- Dependence dep = references.get(key);
- if (tokens.length == 4) {
- assertEquals(dep.access, "");
- } else if (tokens.length == 5) {
- assertEquals(dep.access, tokens[4]);
- } else {
- // JDK internal API
- module = tokens[6];
- assertEquals(tokens.length, 7);
- assertEquals(tokens[3], "JDK");
- assertEquals(tokens[4], "internal");
- assertEquals(tokens[5], "API");
- }
- assertEquals(dep.module, module);
- }
+ // analyze result
+ Graph<DepsAnalyzer.Node> g1 = analyzer.moduleGraph();
+ g1.nodes().stream()
+ .filter(u -> u.name.equals(data.moduleName))
+ .forEach(u -> data.checkRequires(u.name, g1.adjacentNodes(u)));
- public static class ModuleRequires {
- final String name;
- final ModuleDescriptor.Requires.Modifier mod;
-
- ModuleRequires(String name) {
- this.name = name;
- this.mod = null;
- }
+ Graph<DepsAnalyzer.Node> g2 = analyzer.dependenceGraph();
+ g2.nodes().stream()
+ .filter(u -> u.name.equals(data.moduleName))
+ .forEach(u -> data.checkDependences(u.name, g2.adjacentNodes(u)));
- ModuleRequires(String name, ModuleDescriptor.Requires.Modifier mod) {
- this.name = name;
- this.mod = mod;
- }
- }
-
- public static class Dependence {
- final String origin;
- final String target;
- final String module;
- final String access;
-
- Dependence(String origin, String target, String module, String access) {
- this.origin = origin;
- this.target = target;
- this.module = module;
- this.access = access;
- }
- }
+ jdeps.dumpOutput(System.err);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/SplitPackage.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, 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
+ * @summary Tests split packages
+ * @library ../lib
+ * @build CompilerUtils
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng SplitPackage
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.jdeps.DepsAnalyzer;
+import com.sun.tools.jdeps.JdepsConfiguration;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class SplitPackage {
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path CLASSES_DIR = Paths.get("classes");
+
+ private static final String SPLIT_PKG_NAME = "javax.annotation";
+ private static final String JAVA_ANNOTATIONS_COMMON = "java.annotations.common";
+ /**
+ * Compiles classes used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Exception {
+ CompilerUtils.cleanDir(CLASSES_DIR);
+ assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "patches"), CLASSES_DIR));
+ }
+
+ @Test
+ public void runTest() throws Exception {
+ // Test jdeps classes
+ runTest(null);
+ // Test jdeps -addmods
+ runTest(JAVA_ANNOTATIONS_COMMON, SPLIT_PKG_NAME);
+ }
+
+ private void runTest(String root, String... splitPackages) throws Exception {
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -verbose:class -addmods %s %s%n",
+ root, CLASSES_DIR)
+ );
+ jdeps.verbose("-verbose:class")
+ .addRoot(CLASSES_DIR);
+ if (root != null)
+ jdeps.addmods(Set.of(root));
+
+
+ JdepsConfiguration config = jdeps.configuration();
+ Map<String, Set<String>> pkgs = config.splitPackages();
+
+ final Set<String> expected;
+ if (splitPackages != null) {
+ expected = Arrays.stream(splitPackages).collect(Collectors.toSet());
+ } else {
+ expected = Collections.emptySet();
+ }
+
+ if (!pkgs.keySet().equals(expected)) {
+ throw new RuntimeException(splitPackages.toString());
+ }
+
+ // java.annotations.common is not observable
+ DepsAnalyzer analyzer = jdeps.getDepsAnalyzer();
+
+ assertTrue(analyzer.run());
+
+ jdeps.dumpOutput(System.err);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/TransitiveDeps.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,325 @@
+/*
+ * Copyright (c) 2016, 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
+ * @summary Tests jdeps -m and -mp options on named modules and unnamed modules
+ * @library ../lib
+ * @build CompilerUtils JdepsUtil
+ * @modules jdk.jdeps/com.sun.tools.jdeps
+ * @run testng TransitiveDeps
+ */
+
+import java.io.File;
+import java.io.IOException;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+
+import com.sun.tools.jdeps.DepsAnalyzer;
+import com.sun.tools.jdeps.Graph;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class TransitiveDeps {
+ private static final String TEST_SRC = System.getProperty("test.src");
+
+ private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+ private static final Path MODS_DIR = Paths.get("mods");
+ private static final Path LIBS_DIR = Paths.get("libs");
+
+ // the names of the modules in this test
+ private static String[] modules = new String[] {"unsafe", "m6", "m7"};
+ /**
+ * Compiles all modules used by the test
+ */
+ @BeforeTest
+ public void compileAll() throws Exception {
+ CompilerUtils.cleanDir(MODS_DIR);
+ CompilerUtils.cleanDir(LIBS_DIR);
+
+ for (String mn : modules) {
+ // compile a module
+ assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn));
+
+ // create JAR files with no module-info.class
+ Path root = MODS_DIR.resolve(mn);
+ JdepsUtil.createJar(LIBS_DIR.resolve(mn + ".jar"), root,
+ Files.walk(root, Integer.MAX_VALUE)
+ .filter(f -> {
+ String fn = f.getFileName().toString();
+ return fn.endsWith(".class") && !fn.equals("module-info.class");
+ }));
+ }
+ }
+
+ @DataProvider(name = "modules")
+ public Object[][] expected1() {
+ return new Object[][]{
+ { "m7",
+ List.of(new ModuleMetaData("m7")
+ .requires("m6")
+ .requires("unsafe")
+ .reference("p7.Main", "java.lang.Object", "java.base")
+ .reference("p7.Main", "java.lang.String", "java.base")
+ .reference("p7.Main", "org.safe.Lib", "unsafe")
+ .reference("p7.Main", "p6.safe.Lib", "m6"),
+ new ModuleMetaData("m6")
+ .requires("unsafe")
+ .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base")
+ .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe")
+ .reference("p6.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Class", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Object", "java.base")
+ .reference("p6.safe.Lib", "java.lang.String", "java.base")
+ .reference("p6.safe.Lib", "java.lang.System", "java.base")
+ .reference("p6.safe.Lib", "org.safe.Lib", "unsafe"),
+ new ModuleMetaData("unsafe")
+ .requires("jdk.unsupported")
+ .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("org.safe.Lib", "java.lang.Class", "java.base")
+ .reference("org.safe.Lib", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.lang.String", "java.base")
+ .reference("org.safe.Lib", "java.lang.System", "java.base")
+ .reference("org.unsafe.UseUnsafe", "java.lang.Object", "java.base")
+ .jdkInternal("org.unsafe.UseUnsafe", "sun.misc.Unsafe", "java.base")
+ )
+ },
+ };
+ }
+
+ @Test(dataProvider = "modules")
+ public void testModulePath(String name, List<ModuleMetaData> data) throws IOException {
+ Set<String> roots = Set.of("m6", "unsafe");
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -modulepath %s -addmods %s -m %s%n", MODS_DIR,
+ roots.stream().collect(Collectors.joining(",")), name)
+ );
+ jdeps.verbose("-verbose:class")
+ .appModulePath(MODS_DIR.toString())
+ .addmods(roots)
+ .addmods(Set.of(name));
+
+ runJdeps(jdeps, data);
+
+ // run automatic modules
+ roots = Set.of("ALL-MODULE-PATH", "jdk.unsupported");
+
+ jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -modulepath %s -addmods %s -m %s%n", LIBS_DIR,
+ roots.stream().collect(Collectors.joining(",")), name)
+ );
+ jdeps.verbose("-verbose:class")
+ .appModulePath(LIBS_DIR.toString())
+ .addmods(roots)
+ .addmods(Set.of(name));
+
+ runJdeps(jdeps, data);
+ }
+
+ @DataProvider(name = "jars")
+ public Object[][] expected2() {
+ return new Object[][]{
+ { "m7", List.of(new ModuleMetaData("m7.jar")
+ .requires("m6.jar")
+ .requires("unsafe.jar")
+ .reference("p7.Main", "java.lang.Object", "java.base")
+ .reference("p7.Main", "java.lang.String", "java.base")
+ .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
+ .reference("p7.Main", "p6.safe.Lib", "m6.jar"))
+ },
+ };
+ }
+
+ @Test(dataProvider = "jars")
+ public void testClassPath(String name, List<ModuleMetaData> data) throws IOException {
+ String cpath = Arrays.stream(modules)
+ .filter(mn -> !mn.equals(name))
+ .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString())
+ .collect(Collectors.joining(File.pathSeparator));
+
+ Path jarfile = LIBS_DIR.resolve(name + ".jar");
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -classpath %s %s%n", cpath, jarfile)
+ );
+ jdeps.verbose("-verbose:class")
+ .addClassPath(cpath)
+ .addRoot(jarfile);
+
+ runJdeps(jdeps, data);
+ }
+
+ @DataProvider(name = "compileTimeView")
+ public Object[][] expected3() {
+ return new Object[][] {
+ {"m7",
+ List.of(new ModuleMetaData("m7.jar")
+ .requires("m6.jar")
+ .requires("unsafe.jar")
+ .reference("p7.Main", "java.lang.Object", "java.base")
+ .reference("p7.Main", "java.lang.String", "java.base")
+ .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
+ .reference("p7.Main", "p6.safe.Lib", "m6.jar"),
+ new ModuleMetaData("m6.jar")
+ .requires("unsafe.jar")
+ .reference("p6.indirect.UnsafeRef", "java.lang.Object", "java.base")
+ .reference("p6.indirect.UnsafeRef", "org.unsafe.UseUnsafe ", "unsafe.jar")
+ .reference("p6.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Class", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Object", "java.base")
+ .reference("p6.safe.Lib", "java.lang.String", "java.base")
+ .reference("p6.safe.Lib", "java.lang.System", "java.base")
+ .reference("p6.safe.Lib", "org.safe.Lib", "unsafe.jar"),
+ new ModuleMetaData("unsafe.jar")
+ .requires("jdk.unsupported")
+ .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("org.safe.Lib", "java.lang.Class", "java.base")
+ .reference("org.safe.Lib", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.lang.String", "java.base")
+ .reference("org.safe.Lib", "java.lang.System", "java.base")
+ .reference("org.unsafe.UseUnsafe", "java.lang.Object", "java.base")
+ .jdkInternal("org.unsafe.UseUnsafe", "sun.misc.Unsafe", "java.base")
+ )
+ },
+ };
+ }
+
+ @Test(dataProvider = "compileTimeView")
+ public void compileTimeView(String name, List<ModuleMetaData> data) throws IOException {
+ String cpath = Arrays.stream(modules)
+ .filter(mn -> !mn.equals(name))
+ .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString())
+ .collect(Collectors.joining(File.pathSeparator));
+
+ Path jarfile = LIBS_DIR.resolve(name + ".jar");
+
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -ct -classpath %s %s%n", cpath, jarfile)
+ );
+
+ jdeps.verbose("-verbose:class")
+ .addClassPath(cpath)
+ .addRoot(jarfile);
+
+ runJdeps(jdeps, data, true, 0 /* -recursive */);
+ }
+
+ @DataProvider(name = "recursiveDeps")
+ public Object[][] expected4() {
+ return new Object[][] {
+ {"m7",
+ List.of(new ModuleMetaData("m7.jar")
+ .requires("m6.jar")
+ .requires("unsafe.jar")
+ .reference("p7.Main", "java.lang.Object", "java.base")
+ .reference("p7.Main", "java.lang.String", "java.base")
+ .reference("p7.Main", "org.safe.Lib", "unsafe.jar")
+ .reference("p7.Main", "p6.safe.Lib", "m6.jar"),
+ new ModuleMetaData("m6.jar")
+ .requires("unsafe.jar")
+ .reference("p6.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Class", "java.base")
+ .reference("p6.safe.Lib", "java.lang.Object", "java.base")
+ .reference("p6.safe.Lib", "java.lang.String", "java.base")
+ .reference("p6.safe.Lib", "java.lang.System", "java.base")
+ .reference("p6.safe.Lib", "org.safe.Lib", "unsafe.jar"),
+ new ModuleMetaData("unsafe.jar")
+ .requires("jdk.unsupported")
+ .reference("org.indirect.UnsafeRef", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.io.PrintStream", "java.base")
+ .reference("org.safe.Lib", "java.lang.Class", "java.base")
+ .reference("org.safe.Lib", "java.lang.Object", "java.base")
+ .reference("org.safe.Lib", "java.lang.String", "java.base")
+ .reference("org.safe.Lib", "java.lang.System", "java.base")
+ )
+ },
+ };
+ }
+ @Test(dataProvider = "recursiveDeps")
+ public void recursiveDeps(String name, List<ModuleMetaData> data) throws IOException {
+ String cpath = Arrays.stream(modules)
+ .filter(mn -> !mn.equals(name))
+ .map(mn -> LIBS_DIR.resolve(mn + ".jar").toString())
+ .collect(Collectors.joining(File.pathSeparator));
+
+ Path jarfile = LIBS_DIR.resolve(name + ".jar");
+
+ JdepsUtil.Command jdeps = JdepsUtil.newCommand(
+ String.format("jdeps -R -classpath %s %s%n", cpath, jarfile)
+ );
+ jdeps.verbose("-verbose:class").filter("-filter:archive")
+ .addClassPath(cpath)
+ .addRoot(jarfile);
+
+ runJdeps(jdeps, data, true, 0 /* -recursive */);
+ }
+
+ private void runJdeps(JdepsUtil.Command jdeps, List<ModuleMetaData> data)
+ throws IOException
+ {
+ runJdeps(jdeps, data, false, 1 /* depth */);
+ }
+
+ private void runJdeps(JdepsUtil.Command jdeps, List<ModuleMetaData> data,
+ boolean compileTimeView, int depth)
+ throws IOException
+ {
+ // run the analyzer
+ DepsAnalyzer analyzer = jdeps.getDepsAnalyzer();
+ assertTrue(analyzer.run(compileTimeView, depth));
+ jdeps.dumpOutput(System.err);
+
+ // analyze result
+ Graph<DepsAnalyzer.Node> g1 = analyzer.moduleGraph();
+ Map<String, ModuleMetaData> dataMap = data.stream()
+ .collect(Collectors.toMap(ModuleMetaData::name, Function.identity()));
+
+ // the returned graph contains all nodes such as java.base and jdk.unsupported
+ g1.nodes().stream()
+ .filter(u -> dataMap.containsKey(u.name))
+ .forEach(u -> {
+ ModuleMetaData md = dataMap.get(u.name);
+ md.checkRequires(u.name, g1.adjacentNodes(u));
+ });
+
+ Graph<DepsAnalyzer.Node> g2 = analyzer.dependenceGraph();
+
+ g2.nodes().stream()
+ .filter(u -> dataMap.containsKey(u.name))
+ .forEach(u -> {
+ ModuleMetaData md = dataMap.get(u.name);
+ md.checkDependences(u.name, g2.adjacentNodes(u));
+ });
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/patches/javax/annotation/NonNull.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, 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 javax.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.*;
+
+@Documented
+@Target({FIELD, LOCAL_VARIABLE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NonNull {
+}
--- a/langtools/test/tools/jdeps/modules/src/m4/module-info.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m4/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -22,8 +22,14 @@
*/
module m4 {
+ // not used in signature
requires public java.compiler;
+
+ // unused dependence
requires java.logging;
+
exports p4;
- exports p4.internal to m1,m2,m3;
+
+ // unuused qualified exports
+ exports p4.internal to m6,m7;
}
--- a/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m4/p4/internal/Impl.java Thu May 19 19:47:04 2016 +0000
@@ -23,9 +23,14 @@
package p4.internal;
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
public class Impl {
+ private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+
public String name() {
return Impl.class.getName();
}
+
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m5/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m5 {
+ // m4 requires public java.compilerr
+ requires public m4;
+ requires public java.compiler;
+
+ // java.sql should be requires public
+ requires java.sql;
+
+ // java.logging is used for implementation only
+ requires public java.logging;
+
+ exports p5;
+
+ // m8 is not in the resolved graph but used by m8
+ exports p5.internal to m8;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m5/p5/Main.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2016, 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 p5;
+
+import java.sql.Driver;
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+public class Main {
+ public void run(Driver driver) throws Exception {
+ driver.getParentLogger().config("test");
+
+ }
+
+ public p4.Lib getLib() {
+ return new p4.Lib();
+ }
+
+ public JavaCompiler getCompiler() {
+ return ToolProvider.getSystemJavaCompiler();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m5/p5/internal/T.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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 p5.internal;
+
+public class T {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m6/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m6 {
+ requires unsafe;
+
+ // no dependency on sun.misc.Unsafe directly or indirectly
+ exports p6.safe;
+
+ // direct dependency on org.unsafe
+ // hence indirect dependency on sun.misc.Unsafe
+ exports p6.indirect;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m6/p6/indirect/UnsafeRef.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 p6.indirect;
+
+// indirectly depend on sun.misc.Unsafe
+public class UnsafeRef {
+ public static org.unsafe.UseUnsafe get() {
+ return new org.unsafe.UseUnsafe();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m6/p6/safe/Lib.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, 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 p6.safe;
+
+// no direct or indirect dependency on sun.misc.Unsafe
+public class Lib {
+ public static void doit() {
+ System.out.println(Lib.class.getName());
+ org.safe.Lib.doit();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m7/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m7 {
+ // only use classes that have no direct or indirect dependency
+ // to sun.misc.Unsafe
+ requires unsafe;
+ requires m6;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m7/p7/Main.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, 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 p7;
+
+// Only use classes in unsafe and m6 modules with no
+// direct or indirect dependency on sun.misc.Unsafe
+public class Main {
+ public static void main(String... args) {
+ p6.safe.Lib.doit();
+ org.safe.Lib.doit();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m8/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module m8 {
+ requires m5;
+
+ // use p5.internal
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/m8/p8/Main.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, 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 p8;
+
+import p5.internal.T;
+
+public class Main {
+ public static void main() {
+ T t = new T();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/unsafe/module-info.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+module unsafe {
+ requires jdk.unsupported;
+
+ // direct dependency on sun.misc.Unsafe
+ exports org.unsafe;
+
+ // no dependency on sun.misc.Unsafe directly or indirectly
+ exports org.safe;
+
+ // indirect dependency on sun.misc.Unsafe
+ exports org.indirect;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/indirect/UnsafeRef.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 org.indirect;
+
+// indirectly depend on sun.misc.Unsafe
+public class UnsafeRef {
+ public static org.unsafe.UseUnsafe get() {
+ return new org.unsafe.UseUnsafe();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/safe/Lib.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2016, 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 org.safe;
+
+// no direct or indirect dependency on sun.misc.Unsafe
+public class Lib {
+ public static void doit() {
+ System.out.println(Lib.class.getName());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/modules/src/unsafe/org/unsafe/UseUnsafe.java Thu May 19 19:47:04 2016 +0000
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 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 org.unsafe;
+
+import sun.misc.Unsafe;
+
+public class UseUnsafe {
+ static Unsafe unsafe = Unsafe.getUnsafe();
+}
--- a/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java Thu May 19 17:48:04 2016 +0000
+++ b/langtools/test/tools/jdeps/unsupported/JDKUnsupportedTest.java Thu May 19 19:47:04 2016 +0000
@@ -62,7 +62,7 @@
public void test(String filename, String[][] expected) {
Path path = Paths.get(TEST_CLASSES, filename);
- Map<String, String> result = jdeps("-M", path.toString());
+ Map<String, String> result = jdeps(path.toString());
for (String[] e : expected) {
String pn = e[0];
String module = e[1];