This commit is contained in:
Lana Steuck 2014-11-13 09:39:52 -08:00
commit fe30b6862a
38 changed files with 2777 additions and 1250 deletions

View File

@ -23,25 +23,46 @@
# questions.
#
# This is the JDK used to build and run the bootstrap version of javac.
# The bootstrap javac is used to compile both boostrap versions of the
# other tools, and product versions of all the tools.
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
#javac configuration for "normal build" (these will be passed to the bootstrap compiler):
javac.debug = true
javac.debuglevel = source,lines,vars
javac.extra.opts=-XDignore.symbol.file=true
javac.includes=
javac.lint.opts = -Xlint:all,-deprecation -Werror
javac.source = 8
javac.target = 8
# boot.java.home = /opt/jdk/1.7.0
boot.java = ${boot.java.home}/bin/java
boot.javac = ${boot.java.home}/bin/javac
#javac configuration for bootstrap build (these will be passed to the compiler from the given boot JDK):
boot.javac.extra.opts=-XDignore.symbol.file=true
boot.javac.includes = \
javax/annotation/processing/ \
javax/lang/model/ \
javax/tools/ \
jdk/ \
com/sun/source/ \
com/sun/tools/javac/ \
com/sun/tools/doclint/
boot.javac.lint.opts=
boot.javac.source = 8
boot.javac.target = 8
# This is the JDK used to run the product version of the tools,
# for example, for testing. If you're building a complete JDK, specify that.
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
#configuration of submodules (share by both the bootstrap and normal compilation):
langtools.modules=java.base:java.compiler:jdk.compiler:jdk.dev:jdk.javadoc
java.base.dependencies=
java.compiler.dependencies=java.base
jdk.compiler.dependencies=java.base:java.compiler
jdk.javadoc.dependencies=java.base:java.compiler:jdk.compiler
jdk.dev.dependencies=java.base:java.compiler:jdk.compiler
# target.java.home = /opt/jdk/1.8.0
target.java = ${target.java.home}/bin/java
#test configuration:
jtreg.tests=
boot.javac.tests = tools/javac
crules.tests = ../make/test/crules
#javadoc configuration
javadoc.jls.cite=The Java™ Language Specification
javadoc.jls.option=-tag "jls:a:See <cite>${javadoc.jls.cite}</cite>:" \
-tag "implNote:a:Implementation Note:"
# Version info -- override as needed
jdk.version = 1.9.0
@ -55,146 +76,4 @@ milestone = internal
# timestamps
# FIXME -- need to include openjdk as needed
release = ${jdk.version}-${milestone}
bootstrap.release = ${release}_bootstrap
full.version = ${release}-${build.number}
bootstrap.full.version = ${bootstrap.release}-${build.number}
# options for the <javac> tasks used to compile the tools
javac.source = 8
javac.target = 8
javac.debug = true
javac.debuglevel = source,lines
javac.no.jdk.warnings = -XDignore.symbol.file=true
# set the following to -version to verify the versions of javac being used
javac.version.opt =
# in time, there should be no exceptions to -Xlint:all
javac.lint.opts = -Xlint:all,-deprecation -Werror
# options for the <javadoc> task for javac
#javadoc.jls3.url=http://java.sun.com/docs/books/jls/
#javadoc.jls3.cite=&lt;a href=&quot;${javadoc.jls3.url}&quot;&gt;The Java Language Specification, Third Edition&lt;/a&gt;
#javadoc.jls3.option=-tag "jls3:a:See &lt;cite&gt;${javadoc.jls3.cite}&lt;/cite&gt;:"
javadoc.jls.cite=The Java&trade; Language Specification
javadoc.jls.option=-tag "jls:a:See &lt;cite&gt;${javadoc.jls.cite}&lt;/cite&gt;:"
# jtreg, used to run the JDK regression tests
# See http://openjdk.java.net/jtreg/
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
# jtreg.home = /opt/jtreg/4.1
# findbugs
# See http://findbugs.sourceforge.net/
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
# findbugs.home = /opt/findbugs/1.2.1
# vizant (graph visualization tool for Ant)
# See http://vizant.sourceforge.net/
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
# vizant.jar = /opt/vizant/0.1.2/vizant-0.1.2.jar
# dot = dot
#------------------------------------------------------------
# The following properties define the packages for each of the tools.
# Syntactically, they should be suitable as arguments for the "includes"
# parameter of Ant filesets. In particular, note the trailing '/'.
javac.includes = \
javax/annotation/processing/ \
javax/lang/model/ \
javax/tools/ \
jdk/ \
com/sun/source/ \
com/sun/tools/javac/ \
com/sun/tools/doclint/
javac.tests = \
tools/javac
#
javadoc.includes = \
com/sun/javadoc/ \
com/sun/tools/javadoc/ \
com/sun/tools/doclets/
javadoc.tests = \
tools/javadoc/ \
com/sun/javadoc/
#
javah.includes = \
com/sun/tools/javah/
javah.tests = \
tools/javah/
#
javap.includes = \
com/sun/tools/classfile/ \
com/sun/tools/javap/ \
com/sun/tools/jdeps/ \
sun/tools/javap/
javap.tests = \
tools/javap/
#
sjavac.includes = \
com/sun/tools/sjavac/
sjavac.tests = \
tools/sjavac
crules.tests = ../make/test/crules
#
# The following files require the latest JDK to be available.
# The API can be provided by using a suitable boot.java.home
# or by setting import.jdk
require.latest.jdk.files = \
com/sun/tools/javac/nio/*.java
# The following files in the import jdk source directory are required
# in order to compile the files defined in ${require.latest.jdk.files}
#
# For NIO, the list of stub files is defined by the contents of the primary
# API packages, together with such types that may be required in order to
# compile the stubs. Some of these dependencies would go away if the stub
# generator were to be improved -- e.g. by removing unnecessary imports.
#
import.jdk.stub.files = \
java/io/File.java \
java/nio/file/**.java \
java/nio/file/attribute/**.java \
java/nio/file/spi/**.java \
java/nio/channels/AsynchronousChannel.java \
java/nio/channels/AsynchronousFileChannel.java \
java/nio/channels/CompletionHandler.java \
java/nio/channels/SeekableByteChannel.java
# The following value is used by the main jtreg target.
# An empty value means all tests
# Override as desired to run a specific set of tests
jtreg.tests =
# Check style configuration
# overridable name and version
checkstyle.name.version = checkstyle-5.4

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,8 @@
<project name="langtools" basedir="..">
<script language="javascript" classpath=".idea/classes">
var ideaListener = project.getBuildListeners().firstElement();
var LangtoolsLogger = Java.type("idea.LangtoolsIdeaAntLogger");
project.removeBuildListener(ideaListener)
project.addBuildListener(new LangtoolsLogger(ideaListener))
new LangtoolsLogger(project)
</script>
<import file="../make/build.xml"/>

View File

@ -26,7 +26,9 @@
package idea;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import java.util.EnumSet;
import java.util.Stack;
@ -166,21 +168,17 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger {
}
},
/** build bootstrap tool target - executed when bootstrapping javac */
BUILD_BOOTSTRAP_TOOL("build-bootstrap-.*") {
BUILD_BOOTSTRAP_JAVAC("build-bootstrap-javac-classes") {
@Override
String getDisplayMessage(BuildEvent e) {
String targetName = e.getTarget().getName();
String tool = targetName.split("-")[2];
return "Building bootstrap " + tool + "...";
return "Building bootstrap javac...";
}
},
/** build classes target - executed when building classes of given tool */
BUILD_TOOL("build-classes-.*") {
BUILD_ALL_CLASSES("build-all-classes") {
@Override
String getDisplayMessage(BuildEvent e) {
String targetName = e.getTarget().getName();
String tool = targetName.split("-")[2];
return "Building " + tool + "...";
return "Building all classes...";
}
},
/** synthetic target catching any other target not in this list */
@ -195,14 +193,14 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger {
}
};
String targetRegex;
String targetName;
Target(String targetRegex) {
this.targetRegex = targetRegex;
Target(String targetName) {
this.targetName = targetName;
}
boolean matches(String msg) {
return msg.matches(targetRegex);
return msg.equals(targetName);
}
abstract String getDisplayMessage(BuildEvent e);
@ -253,8 +251,14 @@ public final class LangtoolsIdeaAntLogger extends DefaultLogger {
/** stack of pending tasks */
Stack<Task> tasks = new Stack<>();
public LangtoolsIdeaAntLogger(DefaultLogger logger) {
this.logger = logger;
public LangtoolsIdeaAntLogger(Project project) {
for (Object o : project.getBuildListeners()) {
if (o instanceof DefaultLogger) {
this.logger = (DefaultLogger)o;
project.removeBuildListener((BuildListener)o);
project.addBuildListener(this);
}
}
tasks.push(Task.ROOT);
}

View File

@ -10,7 +10,7 @@
<!-- standard tools -->
<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="-Xbootclasspath/p:build/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@ -24,12 +24,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javac" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<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="-Xbootclasspath/p:build/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@ -43,12 +43,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javadoc" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<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="-Xbootclasspath/p:build/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@ -62,12 +62,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javap" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<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="-Xbootclasspath/p:build/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@ -81,12 +81,12 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-javah" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<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="-Xbootclasspath/p:build/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/java.compiler/classes:build/jdk.compiler/classes:build/java.base/classes:build/jdk.javadoc/classes:build/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
@ -100,13 +100,13 @@
<ConfigurationWrapper RunnerId="Run" />
<method>
<option name="Make" enabled="false" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-classes-sjavac" />
<option name="AntTarget" enabled="true" antfile="file://$PROJECT_DIR$/.idea/build.xml" target="build-all-classes" />
</method>
</configuration>
<!-- bootstrap javac -->
<configuration default="false" name="javac (bootstrap)" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="com.sun.tools.javac.Main" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/bootstrap/classes" />
<option name="VM_PARAMETERS" value="-Xbootclasspath/p:build/bootstrap/java.compiler/classes:build/bootstrap/jdk.compiler/classes:build/bootstrap/java.base/classes:build/bootstrap/jdk.javadoc/classes:build/bootstrap/jdk.dev/classes" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />

View File

@ -43,10 +43,9 @@ mylib="$mydir/../lib"
# dependent jar files for additional dependencies.
if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then
cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF |
grep "Class-Path:" |
sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'`
bcp="$mylib/#PROGRAM#.jar#PS#$cp"
cp=`echo "$mylib"/*.jar |
sed -e 's|\([a-z.]*\.jar\) *|\1#PS#|g'`
bcp=$cp
fi
# tools currently assumes that assertions are enabled in the launcher
@ -72,4 +71,4 @@ done
unset DUALCASE
IFS=$nl
"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} -jar "${mylib}/#PROGRAM#.jar" ${toolOpts}
"#TARGET_JAVA#" "${bcp:+-Xbootclasspath/p:"$bcp"}" ${ea} ${javaOpts} com.sun.tools.#PROGRAM#.Main ${toolOpts}

View File

@ -46,48 +46,34 @@
-->
<import file="../../build.xml"/>
<!-- Build project. (action: build; F11)
If langtools.tool.name is set, then just build that tool; otherwise
build all tools.
-->
<!-- Build project. (action: build; F11) -->
<target name="build" depends="-get-tool-if-set,-build-tool,-build-all"
description="Build one or all langtools tools"
/>
<condition property="use_bootstrap" value="bootstrap-" else="">
<isset property="langtools.tool.bootstrap"/>
</condition>
<condition property="with_bootclasspath" value="${build.bootstrap.dir}/classes" else="${build.classes.dir}">
<isset property="langtools.tool.bootstrap"/>
</condition>
<target name="-build-tool" if="langtools.tool.name">
<echo level="info" message="Building ${use_bootstrap}${langtools.tool.name}"/>
<echo level="verbose" message="(Unset langtools.tool.name to build all tools)"/>
<antcall target="build-${use_bootstrap}${langtools.tool.name}"/>
<target name="build" depends="-get-tool-if-set,-build-bootstrap-javac,-build-all" />
<target name="-build-bootstrap-javac" if="langtools.tool.bootstrap">
<antcall target="build-bootstrap-javac"/>
</target>
<target name="-build-all" unless="langtools.tool.name">
<echo level="info" message="Building all tools"/>
<echo level="verbose" message="(Set langtools.tool.name to build a single tool)"/>
<target name="-build-all" unless="langtools.tool.bootstrap">
<antcall target="build-all-tools"/>
</target>
<!-- Compile a single file. (action: compile.single; F9) -->
<target name="compile-single" depends="build-bootstrap-javac">
<target name="compile-single" depends="-get-tool-if-set,build-bootstrap-javac-classes" unless="langtools.tool.bootstrap">
<fail unless="includes">Must set property 'includes'</fail>
<javac fork="true" executable="${build.bootstrap.dir}/bin/javac"
srcdir="${srcdir}"
destdir="${build.classes.dir}"
<mkdir dir="${build.dir}/${module.name}/classes" />
<javac fork="true" executable="${boot.java.home}/bin/javac"
srcdir="${basedir}/src/${module.name}/share/classes"
destdir="${build.dir}/${module.name}/classes"
includes="${includes}"
sourcepath=""
classpath="${langtools.classes}"
includeAntRuntime="no"
source="${javac.source}"
target="${javac.target}"
debug="${javac.debug}"
debuglevel="${javac.debuglevel}"/>
debuglevel="${javac.debuglevel}">
<compilerarg value="-J-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
</javac>
</target>
<!-- Run tool. (action: run; F6)
@ -95,16 +81,24 @@
the user.
-->
<target name="run" depends="-check-target.java.home,build,-def-run,-get-tool-and-args"
<target name="run" depends="-check-target.java.home,-build-classes,-def-run,-get-tool-and-args,-setup-bootclasspath"
description="run tool">
<echo level="info" message="${with_bootclasspath}"/>
<echo level="info" message="Run ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
<run bcp="${with_bootclasspath}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}"/>
</target>
<target name="-build-classes" depends="-get-tool-if-set,-build-classes-bootstrap-javac,-build-classes-all" />
<target name="-build-classes-bootstrap-javac" if="langtools.tool.bootstrap">
<antcall target="build-bootstrap-javac-classes"/>
</target>
<target name="-build-classes-all" unless="langtools.tool.bootstrap">
<antcall target="build-all-classes"/>
</target>
<!-- Run a selected class. (action: run.single; shift-F6) -->
<target name="run-single" depends="-check-target.java.home,-def-run">
<target name="run-single" depends="-check-target.java.home,-setup-bootclasspath,-def-run">
<fail unless="run.classname">Must set property 'run.classname' </fail>
<echo level="info" message="run ${run.classname}"/>
<run mainclass="${run.classname}" args=""/>
@ -115,22 +109,22 @@
test all tools.
-->
<target name="jtreg" depends="-get-tool-if-set,-jtreg-tool,-jtreg-all"
description="Test one or all langtools tools"
<target name="jtreg" depends="-get-tool-if-set,-jtreg-bootstrap-javac,-jtreg-all"
description="Test langtools tools or bootstrap javac"
/>
<target name="-jtreg-tool" if="langtools.tool.name">
<echo level="info" message="Testing ${langtools.tool.name}"/>
<echo level="verbose" message="(Unset langtools.tool.name to test all tools)"/>
<target name="-jtreg-bootstrap-javac" if="langtools.tool.bootstrap">
<echo level="info" message="Testing bootstrap javac"/>
<echo level="verbose" message="(Unset langtools.tool.bootstrap to test all tools)"/>
<antcall>
<target name="jtreg-${langtools.tool.name}"/>
<target name="jtreg-bootstrap-javac"/>
<target name="-show-jtreg"/>
</antcall>
</target>
<target name="-jtreg-all" unless="langtools.tool.name">
<target name="-jtreg-all" unless="langtools.tool.bootstrap">
<echo level="info" message="Testing all tools"/>
<echo level="verbose" message="(Set langtools.tool.name to test a single tool)"/>
<echo level="verbose" message="(Set langtools.tool.bootstrap to test bootstrap javac)"/>
<antcall>
<target name="langtools.jtreg"/>
<target name="-show-jtreg"/>
@ -165,7 +159,7 @@
<!-- Debug tool in NetBeans. -->
<target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,build" if="netbeans.home">
<target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,-setup-bootclasspath,-build-classes" if="netbeans.home">
<echo level="info" message="Debug ${use_bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
<start-debugger/>
<run bcp="${with_bootclasspath}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
@ -179,20 +173,29 @@
</target>
<!-- Debug a jtreg test. -->
<target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg">
<target name="debug-jtreg" depends="-check-target.java.home,-def-start-debugger,-def-jtreg,-get-tool-if-set,-setup-bootclasspath">
<fail unless="jtreg.tests">Must set property 'jtreg.tests'</fail>
<start-debugger/>
<jtreg-tool name="debug" samevm="false" tests="${jtreg.tests}" jpda.jvmargs="${jpda.jvmargs}"/>
<jtreg-tool name="debug"
samevm="false"
tests="${jtreg.tests}"
jpda.jvmargs="${jpda.jvmargs}"
langtools.classes="${with_bootclasspath}"/>
</target>
<!-- Update a class being debugged. -->
<target name="debug-fix">
<target name="debug-fix" depends="-get-tool-if-set">
<fail unless="class">Must set property 'class'
</fail>
<antcall target="compile-single">
<param name="includes" value="${class}.java"/>
</antcall>
<condition property="build.classes.dir"
value="${build.dir}/${module.name}/classes"
else="${boot.build.dir}/${module.name}/classes">
<isset property="use_bootstrap"/>
</condition>
<nbjpdareload>
<fileset dir="${build.classes.dir}">
<include name="${class}.class"/>
@ -205,31 +208,10 @@
test all tools.
-->
<target name="javadoc" depends="-javadoc-tool,-javadoc-all"
description="Generate javadoc for one or all langtools tools"
/>
<target name="-javadoc-tool" if="langtools.tool.name">
<echo level="info" message="Generate javadoc for ${langtools.tool.name}"/>
<echo level="verbose" message="(Unset langtools.tool.name to generate javadoc for all tools)"/>
<antcall>
<target name="javadoc-${langtools.tool.name}"/>
<target name="-show-javadoc"/>
</antcall>
</target>
<target name="-javadoc-all" unless="langtools.tool.name">
<echo level="info" message="Generate javadoc for all tools"/>
<echo level="verbose" message="(Set langtools.tool.name to generate javadoc for a single tool)"/>
<antcall>
<target name="langtools.javadoc"/>
<target name="-show-javadoc"/>
</antcall>
</target>
<target name="javadoc" depends="langtools.javadoc,-show-javadoc" />
<target name="-show-javadoc" if="netbeans.home">
<!-- what if doing javadoc for all? -->
<nbbrowse file="${build.javadoc.dir}/${langtools.tool.name}/index.html"/>
<nbbrowse file="${build.javadoc.dir}/index.html"/>
</target>
<!-- Prompt for values. -->
@ -253,6 +235,15 @@
/>
</target>
<target name="-setup-bootclasspath">
<condition property="use_bootstrap" value="bootstrap-" else="">
<isset property="langtools.tool.bootstrap"/>
</condition>
<condition property="with_bootclasspath" value="${langtools.boot.classes}" else="${langtools.classes}">
<isset property="langtools.tool.bootstrap"/>
</condition>
</target>
<!-- Macro to run a tool or selected class - used by run* and debug* tasks -->
<target name="-def-run">
<macrodef name="run">
@ -262,7 +253,7 @@
<attribute name="jpda.jvmargs" default=""/>
<sequential>
<java fork="true" jvm="${target.java}" classname="@{mainclass}">
<java fork="true" jvm="${target.java.home}/bin/java" classname="@{mainclass}">
<jvmarg line="-Xbootclasspath/p:@{bcp}"/>
<jvmarg line="@{jpda.jvmargs}"/>
<arg line="@{args}"/>
@ -278,11 +269,11 @@
<sequential>
<nbjpdastart name="${ant.project.name}" addressproperty="jpda.address" transport="dt_socket">
<bootclasspath>
<pathelement location="${build.classes.dir}"/>
<pathelement path="${langtools.classes}"/>
<pathelement location="${target.java.home}/jre/lib/rt.jar"/>
</bootclasspath>
<sourcepath>
<path refid="src.dirs"/>
<pathelement path="${langtools.sources}"/>
</sourcepath>
</nbjpdastart>
<property

View File

@ -107,7 +107,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
<property name="srcdir">src/java.base/share/classes</property>
<property name="module.name">java.base</property>
<context>
<property>includes</property>
<folder>${root}/src/java.base/share/classes</folder>
@ -120,7 +120,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
<property name="srcdir">src/java.compiler/share/classes</property>
<property name="module.name">java.compiler</property>
<context>
<property>includes</property>
<folder>${root}/src/java.compiler/share/classes</folder>
@ -133,7 +133,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
<property name="srcdir">src/jdk.compiler/share/classes</property>
<property name="module.name">jdk.compiler</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.compiler/share/classes</folder>
@ -146,7 +146,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
<property name="srcdir">src/jdk.dev/share/classes</property>
<property name="module.name">jdk.dev</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.dev/share/classes</folder>
@ -159,7 +159,7 @@
</action>
<action name="compile.single">
<target>compile-single</target>
<property name="srcdir">src/jdk.javadoc/share/classes</property>
<property name="module.name">jdk.javadoc</property>
<context>
<property>includes</property>
<folder>${root}/src/jdk.javadoc/share/classes</folder>
@ -333,7 +333,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
<property name="srcdir">src/java.base/share/classes</property>
<property name="module.name">java.base</property>
<context>
<property>class</property>
<folder>${root}/src/java.base/share/classes</folder>
@ -346,7 +346,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
<property name="srcdir">src/java.compiler/share/classes</property>
<property name="module.name">java.compiler</property>
<context>
<property>class</property>
<folder>${root}/src/java.compiler/share/classes</folder>
@ -359,7 +359,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
<property name="srcdir">src/jdk.compiler/share/classes</property>
<property name="module.name">jdk.compiler</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.compiler/share/classes</folder>
@ -372,7 +372,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
<property name="srcdir">src/jdk.dev/share/classes</property>
<property name="module.name">jdk.dev</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.dev/share/classes</folder>
@ -385,7 +385,7 @@
</action>
<action name="debug.fix">
<target>debug-fix</target>
<property name="srcdir">src/jdk.dev/share/classes</property>
<property name="module.name">jdk.javadoc</property>
<context>
<property>class</property>
<folder>${root}/src/jdk.javadoc/share/classes</folder>
@ -478,11 +478,31 @@
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/4">
<compilation-unit>
<package-root>${root}/src/java.base/share/classes</package-root>
<built-to>${root}/build/java.base/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/src/java.compiler/share/classes</package-root>
<classpath mode="compile">${root}/build/java.base/classes</classpath>
<built-to>${root}/build/java.compiler/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/src/jdk.compiler/share/classes</package-root>
<classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes</classpath>
<built-to>${root}/build/jdk.compiler/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/src/jdk.dev/share/classes</package-root>
<classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
<built-to>${root}/build/jdk.dev/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
<compilation-unit>
<package-root>${root}/src/jdk.javadoc/share/classes</package-root>
<built-to>${root}/build/classes</built-to>
<classpath mode="compile">${root}/build/java.base/classes:${root}/build/java.compiler/classes:${root}/build/jdk.compiler/classes</classpath>
<built-to>${root}/build/jdk.javadoc/classes</built-to>
<source-level>1.8</source-level>
</compilation-unit>
</java-data>

View File

@ -74,7 +74,18 @@ public class SelectToolTask extends Task {
enum ToolChoices {
NONE(""),
JAVAC("javac"),
BOOSTRAP_JAVAC("bootstrap-javac", true) {
@Override
public ToolChoices baseTool() {
return JAVAC;
}
},
JAVAC("javac") {
@Override
public ToolChoices asBootstrap() {
return BOOSTRAP_JAVAC;
}
},
JAVADOC("javadoc"),
JAVAH("javah"),
JAVAP("javap");
@ -91,6 +102,14 @@ public class SelectToolTask extends Task {
this.bootstrap = bootstrap;
}
public ToolChoices asBootstrap() {
return this;
}
public ToolChoices baseTool() {
return this;
}
@Override
public String toString() {
return toolName;
@ -176,9 +195,11 @@ public class SelectToolTask extends Task {
JOptionPane p = createPane(guiProps);
p.createDialog("Select Tool").setVisible(true);
toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName;
ToolChoices tool = (ToolChoices)toolChoice.getSelectedItem();
toolName = tool.baseTool().toolName;
toolBootstrap = tool.bootstrap;
toolArgs = argsField.getText();
toolBootstrap = bootstrapCheckbox.isSelected();
if (defaultCheck.isSelected()) {
if (toolName.equals("")) {
fileProps.remove("tool.name");
@ -213,30 +234,31 @@ public class SelectToolTask extends Task {
EnumSet<ToolChoices> toolChoices = toolProperty == null ?
EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP);
toolChoice = new JComboBox<>(toolChoices.toArray());
if (toolName != null)
toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase()));
ToolChoices tool = toolName != null ? ToolChoices.valueOf(toolName.toUpperCase()) : null;
if (toolName != null) {
if (toolBootstrap)
tool = tool.asBootstrap();
toolChoice.setSelectedItem(tool);
}
toolChoice.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
String tn = ((ToolChoices)e.getItem()).toolName;
argsField.setText(getDefaultArgsForTool(props, tn));
ToolChoices tool = (ToolChoices)e.getItem();
argsField.setText(getDefaultArgsForTool(props, tool));
if (toolProperty != null)
okButton.setEnabled(!tn.equals(""));
okButton.setEnabled(tool != ToolChoices.NONE);
}
});
GridBagConstraints checkConstraint = new GridBagConstraints();
fc.anchor = GridBagConstraints.EAST;
GridBagConstraints toolConstraint = new GridBagConstraints();
fc.anchor = GridBagConstraints.WEST;
toolPane.add(toolChoice, toolConstraint);
bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap);
toolPane.add(bootstrapCheckbox, checkConstraint);
body.add(toolPane, fc);
argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40);
argsField = new JTextField(getDefaultArgsForTool(props, tool), 40);
if (toolProperty == null || argsProperty != null) {
JLabel argsLabel = new JLabel("Args:");
body.add(argsLabel, lc);
@ -322,8 +344,11 @@ public class SelectToolTask extends Task {
}
}
String getDefaultArgsForTool(Properties props, String tn) {
return (tn == null || tn.equals("")) ? "" : props.getProperty(tn + ".args", "");
String getDefaultArgsForTool(Properties props, ToolChoices tool) {
if (tool == null)
return "";
String toolName = tool.baseTool().toolName;
return toolName.equals("") ? "" : props.getProperty(toolName + ".args", "");
}
// Ant task parameters
@ -335,7 +360,6 @@ public class SelectToolTask extends Task {
// GUI components
private JComboBox<?> toolChoice;
private JCheckBox bootstrapCheckbox;
private JTextField argsField;
private JCheckBox defaultCheck;
private JButton okButton;

View File

@ -37,13 +37,19 @@ public interface TaskListener
{
/**
* Invoked when an event has begun.
*
* @implSpec The default implementation of this method does nothing.
*
* @param e the event
*/
public void started(TaskEvent e);
default void started(TaskEvent e) { }
/**
* Invoked when an event has been completed.
*
* @implSpec The default implementation of this method does nothing.
*
* @param e the event
*/
public void finished(TaskEvent e);
default void finished(TaskEvent e) { }
}

View File

@ -305,7 +305,32 @@ public abstract class Scope {
* the table of its outer scope.
*/
public WriteableScope dupUnshared(Symbol newOwner) {
return new ScopeImpl(this, newOwner, this.table.clone(), this.nelems);
if (shared > 0) {
//The nested Scopes might have already added something to the table, so all items
//that don't originate in this Scope or any of its outer Scopes need to be cleared:
Set<Scope> acceptScopes = Collections.newSetFromMap(new IdentityHashMap<>());
ScopeImpl c = this;
while (c != null) {
acceptScopes.add(c);
c = c.next;
}
int n = 0;
Entry[] oldTable = this.table;
Entry[] newTable = new Entry[this.table.length];
for (int i = 0; i < oldTable.length; i++) {
Entry e = oldTable[i];
while (e != null && e != sentinel && !acceptScopes.contains(e.scope)) {
e = e.shadowed;
}
if (e != null) {
n++;
newTable[i] = e;
}
}
return new ScopeImpl(this, newOwner, newTable, n);
} else {
return new ScopeImpl(this, newOwner, this.table.clone(), this.nelems);
}
}
/** Remove all entries of this scope from its table, if shared

View File

@ -145,7 +145,7 @@ public class TypeAnnotationPosition {
public final int bound_index;
// For type parameter and method parameter
public final int parameter_index;
public int parameter_index;
// For class extends, implements, and throws clauses
public final int type_index;

View File

@ -1196,35 +1196,35 @@ public class Attr extends JCTree.Visitor {
boolean hasDefault = false; // Is there a default label?
for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
JCCase c = l.head;
if (c.pat != null) {
if (enumSwitch) {
Symbol sym = enumConstant(c.pat, seltype);
if (sym == null) {
log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
} else if (!labels.add(sym)) {
log.error(c.pos(), "duplicate.case.label");
}
} else {
Type pattype = attribExpr(c.pat, switchEnv, seltype);
if (!pattype.hasTag(ERROR)) {
if (pattype.constValue() == null) {
log.error(c.pat.pos(),
(stringSwitch ? "string.const.req" : "const.expr.req"));
} else if (labels.contains(pattype.constValue())) {
log.error(c.pos(), "duplicate.case.label");
} else {
labels.add(pattype.constValue());
}
}
}
} else if (hasDefault) {
log.error(c.pos(), "duplicate.default.label");
} else {
hasDefault = true;
}
Env<AttrContext> caseEnv =
switchEnv.dup(c, env.info.dup(switchEnv.info.scope.dup()));
try {
if (c.pat != null) {
if (enumSwitch) {
Symbol sym = enumConstant(c.pat, seltype);
if (sym == null) {
log.error(c.pat.pos(), "enum.label.must.be.unqualified.enum");
} else if (!labels.add(sym)) {
log.error(c.pos(), "duplicate.case.label");
}
} else {
Type pattype = attribExpr(c.pat, switchEnv, seltype);
if (!pattype.hasTag(ERROR)) {
if (pattype.constValue() == null) {
log.error(c.pat.pos(),
(stringSwitch ? "string.const.req" : "const.expr.req"));
} else if (labels.contains(pattype.constValue())) {
log.error(c.pos(), "duplicate.case.label");
} else {
labels.add(pattype.constValue());
}
}
}
} else if (hasDefault) {
log.error(c.pos(), "duplicate.default.label");
} else {
hasDefault = true;
}
attribStats(c.stats, caseEnv);
} finally {
caseEnv.info.scope.leave();
@ -1429,21 +1429,28 @@ public class Attr extends JCTree.Visitor {
case APPLY:
JCMethodInvocation speculativeMethodTree =
(JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo);
Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType();
return types.unboxedTypeOrType(owntype).isPrimitive();
Symbol msym = TreeInfo.symbol(speculativeMethodTree.meth);
Type receiverType = speculativeMethodTree.meth.hasTag(IDENT) ?
env.enclClass.type :
((JCFieldAccess)speculativeMethodTree.meth).selected.type;
Type owntype = types.memberType(receiverType, msym).getReturnType();
return primitiveOrBoxed(owntype);
case NEWCLASS:
JCExpression className =
removeClassParams.translate(((JCNewClass)tree).clazz);
JCExpression speculativeNewClassTree =
(JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo);
return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive();
return primitiveOrBoxed(speculativeNewClassTree.type);
default:
Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
speculativeType = types.unboxedTypeOrType(speculativeType);
return speculativeType.isPrimitive();
return primitiveOrBoxed(speculativeType);
}
}
//where
boolean primitiveOrBoxed(Type t) {
return (!t.hasTag(TYPEVAR) && types.unboxedTypeOrType(t).isPrimitive());
}
TreeTranslator removeClassParams = new TreeTranslator() {
@Override
public void visitTypeApply(JCTypeApply tree) {

View File

@ -1213,7 +1213,10 @@ public class DeferredAttr extends JCTree.Visitor {
return;
}
scan(tree.falsepart);
result = reduce(ArgumentExpressionKind.PRIMITIVE);
result = reduce(ArgumentExpressionKind.PRIMITIVE).isPrimitive() ?
ArgumentExpressionKind.PRIMITIVE :
ArgumentExpressionKind.POLY;
}
@Override

View File

@ -2642,9 +2642,10 @@ public class Lower extends TreeTranslator {
syms.intType, tree.sym);
ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC;
tree.params = tree.params.prepend(ordParam).prepend(nameParam);
MethodSymbol m = tree.sym;
tree.params = tree.params.prepend(ordParam).prepend(nameParam);
incrementParamTypeAnnoIndexes(m, 2);
m.extraParams = m.extraParams.prepend(ordParam.sym);
m.extraParams = m.extraParams.prepend(nameParam.sym);
Type olderasure = m.erasure(types);
@ -2667,6 +2668,17 @@ public class Lower extends TreeTranslator {
}
}
//where
private void incrementParamTypeAnnoIndexes(MethodSymbol m,
int amount) {
for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) {
// Increment the parameter_index of any existing formal
// parameter annotations.
if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) {
anno.position.parameter_index += amount;
}
}
}
private void visitMethodDefInternal(JCMethodDecl tree) {
if (tree.name == names.init &&
(currentClass.isInner() || currentClass.isLocal())) {
@ -2697,8 +2709,10 @@ public class Lower extends TreeTranslator {
// Add this$n (if needed) in front of and free variables behind
// constructor parameter list.
tree.params = tree.params.appendList(fvdefs);
if (currentClass.hasOuterInstance())
if (currentClass.hasOuterInstance()) {
tree.params = tree.params.prepend(otdef);
incrementParamTypeAnnoIndexes(m, 1);
}
// If this is an initial constructor, i.e., it does not start with
// this(...), insert initializers for this$n and proxies

View File

@ -111,6 +111,8 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
Collection<String> args = formatArguments(d, l);
String msg = localize(l, d.getCode(), args.toArray());
String[] lines = msg.split("\n");
if (lines.length == 0) // will happen when msg only contains one or more separators: "\n", "\n\n", etc.
lines = new String[] { "" };
if (getConfiguration().getVisible().contains(DiagnosticPart.SUMMARY)) {
currentIndentation += getConfiguration().getIndentation(DiagnosticPart.SUMMARY);
buf.append(indent(lines[0], currentIndentation)); //summary

View File

@ -218,21 +218,21 @@ public class ClientMain {
// Collect the name of all compiled packages.
Set<String> recently_compiled = new HashSet<>();
boolean[] rc = new boolean[1];
Sjavac sjavac;
boolean background = Util.extractBooleanOption("background", options.getServerConf(), true);
Sjavac sjavac;
// Create an sjavac implementation to be used for compilation
if (background) {
sjavac = new SjavacClient(options);
} else {
int poolsize = Util.extractIntOption("poolsize", options.getServerConf());
if (poolsize <= 0)
poolsize = Runtime.getRuntime().availableProcessors();
sjavac = new PooledSjavac(new SjavacImpl(), poolsize);
}
do {
// Clean out artifacts in tainted packages.
javac_state.deleteClassArtifactsInTaintedPackages();
// Create an sjavac implementation to be used for compilation
if (background) {
sjavac = new SjavacClient(options);
} else {
int poolsize = Util.extractIntOption("poolsize", options.getServerConf());
if (poolsize <= 0)
poolsize = Runtime.getRuntime().availableProcessors();
sjavac = new PooledSjavac(new SjavacImpl(), poolsize);
}
again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc);
if (!rc[0]) break;
} while (again);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,8 @@
* @bug 6508981
* @summary cleanup file separator handling in JavacFileManager
* (This test is specifically to test the new impl of inferBinaryName)
* @build p.A
* @library /tools/lib
* @build ToolBox p.A
* @run main TestInferBinaryName
*/
@ -61,51 +62,75 @@ public class TestInferBinaryName {
//System.err.println(System.getProperties());
testDirectory();
testSymbolArchive();
testZipArchive();
testZipFileIndexArchive();
testZipFileIndexArchive2();
File testJar = createJar();
testZipArchive(testJar);
testZipFileIndexArchive(testJar);
testZipFileIndexArchive2(testJar);
if (errors > 0)
throw new Exception(errors + " error found");
}
File createJar() throws IOException {
File f = new File("test.jar");
try (JavaFileManager fm = new JavacFileManager(new Context(), false, null)) {
ToolBox tb = new ToolBox();
tb.new JarTask(f.getPath())
.files(fm, StandardLocation.PLATFORM_CLASS_PATH, "java.lang.*")
.run();
}
return f;
}
void testDirectory() throws IOException {
String testClassName = "p.A";
JavaFileManager fm =
getFileManager("test.classes", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
test("testDirectory",
fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
List<File> testClasses = Arrays.asList(new File(System.getProperty("test.classes")));
try (JavaFileManager fm =
getFileManager(testClasses, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
test("testDirectory",
fm, testClassName, "com.sun.tools.javac.file.RegularFileObject");
}
}
void testSymbolArchive() throws IOException {
String testClassName = "java.lang.String";
JavaFileManager fm =
getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
test("testSymbolArchive",
fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject");
List<File> path = getPath(System.getProperty("sun.boot.class.path"));
try (JavaFileManager fm =
getFileManager(path, USE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) {
test("testSymbolArchive",
fm, testClassName, "com.sun.tools.javac.file.SymbolArchive$SymbolFileObject");
}
}
void testZipArchive() throws IOException {
void testZipArchive(File testJar) throws IOException {
String testClassName = "java.lang.String";
JavaFileManager fm =
getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX);
test("testZipArchive",
fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
List<File> path = Arrays.asList(testJar);
try (JavaFileManager fm =
getFileManager(path, IGNORE_SYMBOL_FILE, DONT_USE_ZIP_FILE_INDEX)) {
test("testZipArchive",
fm, testClassName, "com.sun.tools.javac.file.ZipArchive$ZipFileObject");
}
}
void testZipFileIndexArchive() throws IOException {
void testZipFileIndexArchive(File testJar) throws IOException {
String testClassName = "java.lang.String";
JavaFileManager fm =
getFileManager("sun.boot.class.path", USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
test("testZipFileIndexArchive",
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
List<File> path = Arrays.asList(testJar);
try (JavaFileManager fm =
getFileManager(path, USE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
test("testZipFileIndexArchive",
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
}
}
void testZipFileIndexArchive2() throws IOException {
void testZipFileIndexArchive2(File testJar) throws IOException {
String testClassName = "java.lang.String";
JavaFileManager fm =
getFileManager("sun.boot.class.path", IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX);
test("testZipFileIndexArchive2",
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
List<File> path = Arrays.asList(testJar);
try (JavaFileManager fm =
getFileManager(path, IGNORE_SYMBOL_FILE, USE_ZIP_FILE_INDEX)) {
test("testZipFileIndexArchive2",
fm, testClassName, "com.sun.tools.javac.file.ZipFileIndexArchive$ZipFileIndexFileObject");
}
}
/**
@ -133,7 +158,7 @@ public class TestInferBinaryName {
System.err.println("OK");
}
JavaFileManager getFileManager(String classpathProperty,
JavaFileManager getFileManager(List<File> path,
boolean symFileKind,
boolean zipFileIndexKind)
throws IOException {
@ -145,7 +170,6 @@ public class TestInferBinaryName {
if (symFileKind == IGNORE_SYMBOL_FILE)
options.put("ignore.symbol.file", "true");
JavacFileManager fm = new JavacFileManager(ctx, false, null);
List<File> path = getPath(System.getProperty(classpathProperty));
fm.setLocation(CLASS_PATH, path);
return fm;
}

View File

@ -1,14 +1,16 @@
/*
* @test /nodynamiccopyright/
* @bug 4974927
* @bug 4974927 8064464
* @summary The compiler was allowing void types in its parsing of conditional expressions.
* @author tball
*
* @compile/fail/ref=ConditionalWithVoid.out -XDrawDiagnostics ConditionalWithVoid.java
*/
public class ConditionalWithVoid {
public int test(Object o) {
// Should fail to compile since Object.wait() has a void return type.
public void test(Object o) {
// Should fail to compile since Object.wait() has a void return type. Poly case.
System.out.println(o instanceof String ? o.hashCode() : o.wait());
// Should fail to compile since Object.wait() has a void return type. Standalone case.
(o instanceof String ? o.hashCode() : o.wait()).toString();
}
}

View File

@ -1,2 +1,3 @@
ConditionalWithVoid.java:12:48: compiler.err.neither.conditional.subtype: java.lang.Integer, void
1 error
ConditionalWithVoid.java:12:71: compiler.err.void.not.allowed.here
ConditionalWithVoid.java:14:30: compiler.err.neither.conditional.subtype: java.lang.Integer, void
2 errors

View File

@ -0,0 +1,950 @@
/*
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.annotation.*;
import java.io.*;
import java.net.URL;
import java.util.List;
import com.sun.tools.classfile.*;
/**
* A class providing utilities for writing tests that inspect class
* files directly, looking for specific type annotations.
*
* Note: this framework does not currently handle repeating
* annotations.
*/
public class ClassfileInspector {
/**
* A group of expected annotations to be found in a given class.
* If the class name is null, then the template will be applied to
* every class.
*/
public static class Expected {
/**
* The name of the class. If {@code null} this template will
* apply to every class; otherwise, it will only be applied to
* the named class.
*/
public final String classname;
/**
* The expected class annotations. These will be checked
* against the class' attributes.
*/
public final ExpectedTypeAnnotation[] classAnnos;
/**
* The expected method annotations. These will be checked
* against all methods in the class.
*/
public final ExpectedMethodTypeAnnotation[] methodAnnos;
/**
* The expected field annotations. These will be checked
* against all fields in the class.
*/
public final ExpectedFieldTypeAnnotation[] fieldAnnos;
/**
* Create an {@code Expected} from its components.
*
* @param classname The name of the class to match, or {@code
* null} for all classes.
* @param classAnnos The expected class annotations.
* @param methodAnnos The expected method annotations.
* @param fieldAnnos The expected field annotations.
*/
public Expected(String classname,
ExpectedTypeAnnotation[] classAnnos,
ExpectedMethodTypeAnnotation[] methodAnnos,
ExpectedFieldTypeAnnotation[] fieldAnnos) {
this.classname = classname;
this.classAnnos = classAnnos;
this.methodAnnos = methodAnnos;
this.fieldAnnos = fieldAnnos;
}
public String toString() {
final StringBuilder sb = new StringBuilder();
final String newline = System.lineSeparator();
sb.append("Expected on class ").append(classname);
if (null != classAnnos) {
sb.append(newline).append("Class annotations:").append(newline);
for(ExpectedTypeAnnotation anno : classAnnos) {
sb.append(anno).append(newline);
}
}
if (null != methodAnnos) {
sb.append(newline).append("Method annotations:").append(newline);
for(ExpectedTypeAnnotation anno : methodAnnos) {
sb.append(anno).append(newline);
}
}
if (null != fieldAnnos) {
sb.append(newline).append("Field annotations:").append(newline);
for(ExpectedTypeAnnotation anno : fieldAnnos) {
sb.append(anno).append(newline);
}
}
return sb.toString();
}
/**
* See if this template applies to a class.
*
* @param classname The classname to check.
* @return Whether or not this template should apply.
*/
public boolean matchClassName(String classname) {
return this.classname == null || this.classname.equals(classname);
}
/**
* After applying the template to all classes, check to see if
* any of the expected annotations weren't matched.
*
* @return The number of missed matches.
*/
public int check() {
int count = 0;
if (classAnnos != null) {
for(ExpectedTypeAnnotation expected : classAnnos) {
if (!expected.check()) {
count++;
}
}
}
if (methodAnnos != null) {
for(ExpectedMethodTypeAnnotation expected : methodAnnos) {
if (!expected.check()) {
count++;
}
}
}
if (fieldAnnos != null) {
for(ExpectedFieldTypeAnnotation expected : fieldAnnos) {
if (!expected.check()) {
count++;
}
}
}
return count;
}
}
/**
* An expected type annotation. This is both a superclass for
* method and field type annotations, as well as a class for type
* annotations on a class.
*/
public static class ExpectedTypeAnnotation {
private int count = 0;
protected final String expectedName;
protected final int expectedCount;
protected final TypeAnnotation.TargetType targetType;
protected final int bound_index;
protected final int parameter_index;
protected final int type_index;
protected final int exception_index;
protected final TypeAnnotation.Position.TypePathEntry[] typePath;
protected final boolean visibility;
/**
* Create an {@code ExpectedTypeAnnotation} from its
* components. It is usually a better idea to use a {@code
* Builder} to do this.
*
* @param expectedName The expected annotation name.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should
* be seen. If 0, this asserts that the
* described annotation is not present.
* @param targetType The expected target type.
* @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
* @param parameter_index The expected parameter index, or
* {@code Integer.MIN_VALUE}.
* @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
* @param exception_index The expected exception index, or
* {@code Integer.MIN_VALUE}.
* @param typePath The expected type path.
*/
public ExpectedTypeAnnotation(String expectedName,
boolean visibility,
int expectedCount,
TypeAnnotation.TargetType targetType,
int bound_index,
int parameter_index,
int type_index,
int exception_index,
TypeAnnotation.Position.TypePathEntry... typePath) {
this.expectedName = expectedName;
this.visibility = visibility;
this.expectedCount = expectedCount;
this.targetType = targetType;
this.bound_index = bound_index;
this.parameter_index = parameter_index;
this.type_index = type_index;
this.exception_index = exception_index;
this.typePath = typePath;
}
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Expected ");
sb.append(expectedCount);
sb.append(" annotation ");
sb.append(expectedName);
sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
sb.append(targetType);
sb.append(", bound_index = ");
sb.append(bound_index);
sb.append(", parameter_index = ");
sb.append(parameter_index);
sb.append(", type_index = ");
sb.append(type_index);
sb.append(", exception_index = ");
sb.append(exception_index);
sb.append(", type_path = [");
for(int i = 0; i < typePath.length; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(typePath[i]);
}
sb.append("]");
return sb.toString();
}
/**
* See if this template matches the given visibility.
*
* @param Whether or not the annotation is visible at runtime.
* @return Whether or not this template matches the visibility.
*/
public boolean matchVisibility(boolean visibility) {
return this.visibility == visibility;
}
/**
* Attempty to match this template against an annotation. If
* it does match, then the match count for the template will
* be incremented. Otherwise, nothing will be done.
*
* @param anno The annotation to attempt to match.
*/
public void matchAnnotation(TypeAnnotation anno) {
boolean matches = true;
try {
matches = anno.constant_pool.getUTF8Info(anno.annotation.type_index).value.equals("L" + expectedName + ";");
} catch(Exception e) {
matches = false;
}
matches = matches && anno.position.type == targetType;
matches = matches && anno.position.bound_index == bound_index;
matches = matches && anno.position.parameter_index == parameter_index;
matches = matches && anno.position.type_index == type_index;
matches = matches && anno.position.exception_index == exception_index;
matches = matches && anno.position.location.size() == typePath.length;
if (matches) {
int i = 0;
for(TypeAnnotation.Position.TypePathEntry entry :
anno.position.location) {
matches = matches && typePath[i++].equals(entry);
}
}
if (matches) {
count++;
}
}
/**
* After all matching, check to see if the expected number of
* matches equals the actual number. If not, then print a
* failure message and return {@code false}.
*
* @return Whether or not the expected number of matched
* equals the actual number.
*/
public boolean check() {
if (count != expectedCount) {
System.err.println(this + ", but saw " + count);
return false;
} else {
return true;
}
}
/**
* A builder class for creating {@code
* ExpectedTypeAnnotation}s in a more convenient fashion. The
* constructor for {@code ExpectedTypeAnnotation} takes a
* large number of parameters (by necessity). This class
* allows users to construct a {@code ExpectedTypeAnnotation}s
* using only the ones they need.
*/
public static class Builder {
protected final String expectedName;
protected final int expectedCount;
protected final TypeAnnotation.TargetType targetType;
protected final boolean visibility;
protected int bound_index = Integer.MIN_VALUE;
protected int parameter_index = Integer.MIN_VALUE;
protected int type_index = Integer.MIN_VALUE;
protected int exception_index = Integer.MIN_VALUE;
protected TypeAnnotation.Position.TypePathEntry[] typePath =
new TypeAnnotation.Position.TypePathEntry[0];
/**
* Create a {@code Builder} from the mandatory parameters.
*
* @param expectedName The expected annotation name.
* @param targetType The expected target type.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should be seen.
*/
public Builder(String expectedName,
TypeAnnotation.TargetType targetType,
boolean visibility,
int expectedCount) {
this.expectedName = expectedName;
this.visibility = visibility;
this.expectedCount = expectedCount;
this.targetType = targetType;
}
/**
* Create an {@code ExpectedTypeAnnotation} from all
* parameters that have been provided. The default values
* will be used for those that have not.
*
* @return The cretaed {@code ExpectedTypeAnnotation}.
*/
public ExpectedTypeAnnotation build() {
return new ExpectedTypeAnnotation(expectedName, visibility,
expectedCount, targetType,
bound_index, parameter_index,
type_index, exception_index,
typePath);
}
/**
* Provide a bound index parameter.
*
* @param bound_index The bound_index value.
*/
public Builder setBoundIndex(int bound_index) {
this.bound_index = bound_index;
return this;
}
/**
* Provide a parameter index parameter.
*
* @param bound_index The parameter_index value.
*/
public Builder setParameterIndex(int parameter_index) {
this.parameter_index = parameter_index;
return this;
}
/**
* Provide a type index parameter.
*
* @param type_index The type_index value.
*/
public Builder setTypeIndex(int type_index) {
this.type_index = type_index;
return this;
}
/**
* Provide an exception index parameter.
*
* @param exception_index The exception_index value.
*/
public Builder setExceptionIndex(int exception_index) {
this.exception_index = exception_index;
return this;
}
/**
* Provide a type path parameter.
*
* @param typePath The type path value.
*/
public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) {
this.typePath = typePath;
return this;
}
}
}
/**
* A type annotation found on a method.
*/
public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation {
private final String methodname;
/**
* Create an {@code ExpectedMethodTypeAnnotation} from its
* components. It is usually a better idea to use a {@code
* Builder} to do this.
*
* @param methodname The expected method name.
* @param expectedName The expected annotation name.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should be seen.
* @param targetType The expected target type.
* @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
* @param parameter_index The expected parameter index, or
* {@code Integer.MIN_VALUE}.
* @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
* @param exception_index The expected exception index, or
* {@code Integer.MIN_VALUE}.
* @param typePath The expected type path.
*/
public ExpectedMethodTypeAnnotation(String methodname,
String expectedName,
boolean visibility,
int expectedCount,
TypeAnnotation.TargetType targetType,
int bound_index,
int parameter_index,
int type_index,
int exception_index,
TypeAnnotation.Position.TypePathEntry... typePath) {
super(expectedName, visibility, expectedCount, targetType, bound_index,
parameter_index, type_index, exception_index, typePath);
this.methodname = methodname;
}
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Expected ");
sb.append(expectedCount);
sb.append(" annotation ");
sb.append(expectedName);
sb.append(visibility ? ", runtime visibile " : ", runtime invisibile ");
sb.append(targetType);
sb.append(", bound_index = ");
sb.append(bound_index);
sb.append(", parameter_index = ");
sb.append(parameter_index);
sb.append(", type_index = ");
sb.append(type_index);
sb.append(", exception_index = ");
sb.append(exception_index);
sb.append(", type_path = [");
for(int i = 0; i < typePath.length; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(typePath[i]);
}
sb.append("]");
sb.append(" on method ");
sb.append(methodname);
return sb.toString();
}
/**
* See if this template applies to a method.
*
* @param methodname The method name to check.
* @return Whether or not this template should apply.
*/
public boolean matchMethodName(String methodname) {
return this.methodname.equals(methodname);
}
/**
* A builder class for creating {@code
* ExpectedMethodTypeAnnotation}s in a more convenient fashion. The
* constructor for {@code ExpectedMethodTypeAnnotation} takes a
* large number of parameters (by necessity). This class
* allows users to construct a {@code ExpectedMethodTypeAnnotation}s
* using only the ones they need.
*/
public static class Builder extends ExpectedTypeAnnotation.Builder {
protected final String methodname;
/**
* Create a {@code Builder} from the mandatory parameters.
*
* @param methodname The expected method name.
* @param expectedName The expected annotation name.
* @param targetType The expected target type.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should be seen.
*/
public Builder(String methodname,
String expectedName,
TypeAnnotation.TargetType targetType,
boolean visibility,
int expectedCount) {
super(expectedName, targetType, visibility, expectedCount);
this.methodname = methodname;
}
/**
* Create an {@code ExpectedMethodTypeAnnotation} from all
* parameters that have been provided. The default values
* will be used for those that have not.
*
* @return The cretaed {@code ExpectedMethodTypeAnnotation}.
*/
public ExpectedMethodTypeAnnotation build() {
return new ExpectedMethodTypeAnnotation(methodname, expectedName,
visibility, expectedCount,
targetType, bound_index,
parameter_index, type_index,
exception_index, typePath);
}
}
}
/**
* A type annotation found on a field.
*/
public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation {
private final String fieldname;
/**
* Create an {@code ExpectedFieldTypeAnnotation} from its
* components. It is usually a better idea to use a {@code
* Builder} to do this.
*
* @param fieldname The expected field name.
* @param expectedName The expected annotation name.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should be seen.
* @param targetType The expected target type.
* @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}.
* @param parameter_index The expected parameter index, or
* {@code Integer.MIN_VALUE}.
* @param type_index The expected type index, or {@code Integer.MIN_VALUE}.
* @param exception_index The expected exception index, or
* {@code Integer.MIN_VALUE}.
* @param typePath The expected type path.
*/
public ExpectedFieldTypeAnnotation(String fieldname,
String expectedName,
boolean visibility,
int expectedCount,
TypeAnnotation.TargetType targetType,
int bound_index,
int parameter_index,
int type_index,
int exception_index,
TypeAnnotation.Position.TypePathEntry... typePath) {
super(expectedName, visibility, expectedCount, targetType, bound_index,
parameter_index, type_index, exception_index, typePath);
this.fieldname = fieldname;
}
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Expected ").append(expectedCount)
.append(" annotation ").append(expectedName)
.append(visibility ? ", runtime visibile " : ", runtime invisibile ")
.append(targetType)
.append(", bound_index = ").append(bound_index)
.append(", parameter_index = ").append(parameter_index)
.append(", type_index = ").append(type_index)
.append(", exception_index = ").append(exception_index)
.append(", type_path = [");
for(int i = 0; i < typePath.length; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(typePath[i]);
}
sb.append("]")
.append(" on field ").append(fieldname);
return sb.toString();
}
/**
* See if this template applies to a field.
*
* @param fieldname The field name to check.
* @return Whether or not this template should apply.
*/
public boolean matchFieldName(String fieldname) {
return this.fieldname.equals(fieldname);
}
/**
* A builder class for creating {@code
* ExpectedFieldTypeAnnotation}s in a more convenient fashion. The
* constructor for {@code ExpectedFieldTypeAnnotation} takes a
* large number of parameters (by necessity). This class
* allows users to construct a {@code ExpectedFieldTypeAnnotation}s
* using only the ones they need.
*/
public static class Builder extends ExpectedTypeAnnotation.Builder {
protected final String fieldname;
/**
* Create a {@code Builder} from the mandatory parameters.
*
* @param fieldname The expected field name.
* @param expectedName The expected annotation name.
* @param targetType The expected target type.
* @param visibility Whether this annotation should be runtime-visible.
* @param expectedCount The number of annotations that should be seen.
*/
public Builder(String fieldname,
String expectedName,
TypeAnnotation.TargetType targetType,
boolean visibility,
int expectedCount) {
super(expectedName, targetType, visibility, expectedCount);
this.fieldname = fieldname;
}
/**
* Create an {@code ExpectedFieldTypeAnnotation} from all
* parameters that have been provided. The default values
* will be used for those that have not.
*
* @return The cretaed {@code ExpectedFieldTypeAnnotation}.
*/
public ExpectedFieldTypeAnnotation build() {
return new ExpectedFieldTypeAnnotation(fieldname, expectedName,
visibility, expectedCount,
targetType, bound_index,
parameter_index, type_index,
exception_index, typePath);
}
}
}
private void matchClassTypeAnnotation(ClassFile classfile,
ExpectedTypeAnnotation expected)
throws ConstantPoolException {
for(Attribute attr : classfile.attributes) {
attr.accept(typeAnnoMatcher, expected);
}
}
private void matchMethodTypeAnnotation(ClassFile classfile,
ExpectedMethodTypeAnnotation expected)
throws ConstantPoolException {
for(Method meth : classfile.methods) {
if (expected.matchMethodName(meth.getName(classfile.constant_pool))) {
for(Attribute attr : meth.attributes) {
attr.accept(typeAnnoMatcher, expected);
}
}
}
}
private void matchFieldTypeAnnotation(ClassFile classfile,
ExpectedFieldTypeAnnotation expected)
throws ConstantPoolException {
for(Field field : classfile.fields) {
if (expected.matchFieldName(field.getName(classfile.constant_pool))) {
for(Attribute attr : field.attributes) {
attr.accept(typeAnnoMatcher, expected);
}
}
}
}
private void matchClassTypeAnnotations(ClassFile classfile,
ExpectedTypeAnnotation[] expected)
throws ConstantPoolException {
for(ExpectedTypeAnnotation one : expected) {
matchClassTypeAnnotation(classfile, one);
}
}
private void matchMethodTypeAnnotations(ClassFile classfile,
ExpectedMethodTypeAnnotation[] expected)
throws ConstantPoolException {
for(ExpectedMethodTypeAnnotation one : expected) {
matchMethodTypeAnnotation(classfile, one);
}
}
private void matchFieldTypeAnnotations(ClassFile classfile,
ExpectedFieldTypeAnnotation[] expected)
throws ConstantPoolException {
for(ExpectedFieldTypeAnnotation one : expected) {
matchFieldTypeAnnotation(classfile, one);
}
}
/**
* Run a template on a single {@code ClassFile}.
*
* @param classfile The {@code ClassFile} on which to run tests.
* @param expected The expected annotation template.
*/
public void run(ClassFile classfile,
Expected... expected)
throws ConstantPoolException {
run(new ClassFile[] { classfile }, expected);
}
/**
* Run a template on multiple {@code ClassFile}s.
*
* @param classfile The {@code ClassFile}s on which to run tests.
* @param expected The expected annotation template.
*/
public void run(ClassFile[] classfiles,
Expected... expected)
throws ConstantPoolException {
for(ClassFile classfile : classfiles) {
for(Expected one : expected) {
if (one.matchClassName(classfile.getName())) {
if (one.classAnnos != null)
matchClassTypeAnnotations(classfile, one.classAnnos);
if (one.methodAnnos != null)
matchMethodTypeAnnotations(classfile, one.methodAnnos);
if (one.fieldAnnos != null)
matchFieldTypeAnnotations(classfile, one.fieldAnnos);
}
}
}
int count = 0;
for (Expected one : expected) {
count += one.check();
}
if (count != 0) {
throw new RuntimeException(count + " errors occurred in test");
}
}
/**
* Get a {@code ClassFile} from its file name.
*
* @param name The class' file name.
* @return The {@code ClassFile}
*/
public static ClassFile getClassFile(String name)
throws IOException, ConstantPoolException {
final URL url = ClassfileInspector.class.getResource(name);
final InputStream in = url.openStream();
try {
return ClassFile.read(in);
} finally {
in.close();
}
}
private static final Attribute.Visitor<Void, ExpectedTypeAnnotation> typeAnnoMatcher =
new Attribute.Visitor<Void, ExpectedTypeAnnotation>() {
@Override
public Void visitBootstrapMethods(BootstrapMethods_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitDefault(DefaultAttribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitAnnotationDefault(AnnotationDefault_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitCode(Code_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitCompilationID(CompilationID_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitConstantValue(ConstantValue_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitDeprecated(Deprecated_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitEnclosingMethod(EnclosingMethod_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitExceptions(Exceptions_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitInnerClasses(InnerClasses_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitLineNumberTable(LineNumberTable_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitLocalVariableTable(LocalVariableTable_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitMethodParameters(MethodParameters_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitSignature(Signature_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitSourceFile(SourceFile_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitSourceID(SourceID_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitStackMap(StackMap_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitStackMapTable(StackMapTable_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitSynthetic(Synthetic_attribute attr,
ExpectedTypeAnnotation expected) {
return null;
}
@Override
public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
if (expected.matchVisibility(true)) {
for(TypeAnnotation anno : attr.annotations) {
expected.matchAnnotation(anno);
}
}
return null;
}
@Override
public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr,
ExpectedTypeAnnotation expected) {
if (expected.matchVisibility(false)) {
for(TypeAnnotation anno : attr.annotations) {
expected.matchAnnotation(anno);
}
}
return null;
}
};
}

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test SyntheticParameters
* @summary Test generation of annotations on inner class parameters.
* @build ClassfileInspector
* @run main SyntheticParameters
*/
import java.io.*;
import java.lang.annotation.*;
import com.sun.tools.classfile.*;
public class SyntheticParameters extends ClassfileInspector {
private static final String Inner_class = "SyntheticParameters$Inner.class";
private static final String Foo_class = "SyntheticParameters$Foo.class";
private static final Expected Inner_expected =
new Expected("SyntheticParameters$Inner",
null,
new ExpectedMethodTypeAnnotation[] {
(ExpectedMethodTypeAnnotation)
// Assert there is no annotation on the
// this$0 parameter.
new ExpectedMethodTypeAnnotation.Builder(
"<init>",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
0).setParameterIndex(0).build(),
(ExpectedMethodTypeAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedMethodTypeAnnotation.Builder(
"<init>",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
1).setParameterIndex(1).build(),
(ExpectedMethodTypeAnnotation)
new ExpectedMethodTypeAnnotation.Builder(
"foo",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
1).setParameterIndex(0).build(),
(ExpectedMethodTypeAnnotation)
new ExpectedMethodTypeAnnotation.Builder(
"foo",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
0).setParameterIndex(1).build()
},
null);
private static final Expected Foo_expected =
new Expected("SyntheticParameters$Foo",
null,
new ExpectedMethodTypeAnnotation[] {
(ExpectedMethodTypeAnnotation)
// Assert there is no annotation on the
// $enum$name parameter.
new ExpectedMethodTypeAnnotation.Builder(
"<init>",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
0).setParameterIndex(0).build(),
(ExpectedMethodTypeAnnotation)
// Assert there is no annotation on the
// $enum$ordinal parameter.
new ExpectedMethodTypeAnnotation.Builder(
"<init>",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
0).setParameterIndex(1).build(),
(ExpectedMethodTypeAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedMethodTypeAnnotation.Builder(
"<init>",
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
1).setParameterIndex(2).build()
},
null);
public static void main(String... args) throws Exception {
new SyntheticParameters().run(
new ClassFile[] { getClassFile(Inner_class), getClassFile(Foo_class) },
new Expected[] { Inner_expected, Foo_expected });
}
public class Inner {
public Inner(@A int a) {}
public void foo(@A int a, int b) {}
}
public static enum Foo {
ONE(null);
Foo(@A Object a) {}
}
}
@Target({ElementType.TYPE_USE})
@interface A {}

View File

@ -43,7 +43,7 @@ public class Constructors {
@TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@ -56,7 +56,7 @@ public class Constructors {
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TC", type = METHOD_RECEIVER)
@TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@ -70,7 +70,7 @@ public class Constructors {
@TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("Outer$Middle$Inner")
public String innerClass3() {
return "class Outer { class Middle { class Inner {" +
@ -89,7 +89,7 @@ public class Constructors {
@TADescription(annotation = "RTAs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@ -102,7 +102,7 @@ public class Constructors {
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTCs", type = METHOD_RECEIVER)
@TADescription(annotation = "RTDs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@ -116,7 +116,7 @@ public class Constructors {
@TADescription(annotation = "RTCs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "RTDs", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "RTEs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
@TestClass("Outer$Middle$Inner")
public String innerClassRepatableAnnotation3() {
return "class Outer { class Middle { class Inner {" +

View File

@ -0,0 +1,537 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8042931
* @summary Checking EnclosingMethod attribute of anonymous/local class.
* @library /tools/lib /tools/javac/lib ../lib
* @build EnclosingMethodTest TestBase TestResult InMemoryFileManager ToolBox
* @run main EnclosingMethodTest
*/
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.EnclosingMethod_attribute;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
/**
* The test checks the enclosing method attribute of anonymous/local classes.
* The top-level class contains the anonymous and local classes to be tested. The test examines
* each inner class and determine whether the class should have the EnclosingMethod attribute or not.
* Golden information about enclosing methods are held in annotation {@code ExpectedEnclosingMethod}.
*
* The test assumes that a class must have the EnclosingMethod attribute if the class is annotated or
* if its parent class is annotated in case of anonymous class. In addition, classes
* named {@code VariableInitializer} are introduced to test variable initializer cases. These classes
* must not have the enclosing method attribute, but its anonymous derived class must.
* After classification of classes, the test checks whether classes contain the correct enclosing
* method attribute in case of anonymous/local class, or checks whether classes do not contain
* the EnclosingMethod attribute, otherwise.
*
* Test cases:
* top-level class as enclosing class:
* 1. anonymous and local classes in static initializer;
* 2. anonymous and local classes in instance initializer;
* 3. anonymous and local classes in lambda;
* 4. anonymous and local classes in constructor;
* 5. anonymous and local classes in method;
* 6. static and instance variable initializer.
*
* inner class as enclosing class:
* 1. anonymous and local classes in static initializer;
* 2. anonymous and local classes in instance initializer;
* 3. anonymous and local classes in lambda;
* 4. anonymous and local classes in constructor;
* 5. anonymous and local classes in method;
* 6. static and instance variable initializer.
*
* enum as enclosing class:
* 1. anonymous and local classes in static initializer;
* 2. anonymous and local classes in instance initializer;
* 3. anonymous and local classes in lambda;
* 4. anonymous and local classes in constructor;
* 5. anonymous and local classes in method;
* 6. static and instance variable initializer.
*
* interface as enclosing class:
* 1. anonymous and local classes in lambda;
* 2. anonymous and local classes in static method;
* 3. anonymous and local classes in default method;
* 4. static variable initializer.
*
* annotation as enclosing class:
* 1. anonymous and local classes in lambda;
* 2. static variable initializer.
*/
public class EnclosingMethodTest extends TestResult {
private final Map<Class<?>, ExpectedEnclosingMethod> class2EnclosingMethod = new HashMap<>();
private final Set<Class<?>> noEnclosingMethod = new HashSet<>();
public EnclosingMethodTest() throws ClassNotFoundException {
Class<EnclosingMethodTest> outerClass = EnclosingMethodTest.class;
String outerClassName = outerClass.getSimpleName();
File testClasses = getClassDir();
FilenameFilter filter = (dir, name) -> name.matches(outerClassName + ".*\\.class");
for (File file : testClasses.listFiles(filter)) {
Class<?> clazz = Class.forName(file.getName().replace(".class", ""));
if (clazz.isAnonymousClass()) {
// anonymous class cannot be annotated, information is in its parent class.
ExpectedEnclosingMethod declaredAnnotation =
clazz.getSuperclass().getDeclaredAnnotation(ExpectedEnclosingMethod.class);
class2EnclosingMethod.put(clazz, declaredAnnotation);
} else {
ExpectedEnclosingMethod enclosingMethod = clazz.getDeclaredAnnotation(ExpectedEnclosingMethod.class);
// if class is annotated and it does not contain information for variable initializer cases,
// then it must have the enclosing method attribute.
if (enclosingMethod != null && !clazz.getSimpleName().contains("VariableInitializer")) {
class2EnclosingMethod.put(clazz, enclosingMethod);
} else {
noEnclosingMethod.add(clazz);
}
}
}
}
public void test() throws TestFailedException {
try {
testEnclosingMethodAttribute();
testLackOfEnclosingMethodAttribute();
} finally {
checkStatus();
}
}
private void testLackOfEnclosingMethodAttribute() {
for (Class<?> clazz : noEnclosingMethod) {
try {
addTestCase("Class should not have EnclosingMethod attribute : " + clazz);
ClassFile classFile = readClassFile(clazz);
checkEquals(countEnclosingMethodAttributes(classFile),
0l, "number of the EnclosingMethod attribute in the class is zero : "
+ classFile.getName());
} catch (Exception e) {
addFailure(e);
}
}
}
private void testEnclosingMethodAttribute() {
class2EnclosingMethod.forEach((clazz, enclosingMethod) -> {
try {
String info = enclosingMethod.info() + " "
+ (clazz.isAnonymousClass() ? "anonymous" : "local");
addTestCase(info);
printf("Testing test case : %s\n", info);
ClassFile classFile = readClassFile(clazz);
String className = clazz.getName();
checkEquals(countEnclosingMethodAttributes(classFile), 1l,
"number of the EnclosingMethod attribute in the class is one : "
+ clazz);
EnclosingMethod_attribute attr = (EnclosingMethod_attribute)
classFile.getAttribute(Attribute.EnclosingMethod);
if (!checkNotNull(attr, "the EnclosingMethod attribute is not null : " + className)) {
// stop checking, attr is null. test case failed
return;
}
checkEquals(classFile.constant_pool.getUTF8Value(attr.attribute_name_index),
"EnclosingMethod",
"attribute_name_index of EnclosingMethod attribute in the class : " + className);
checkEquals(attr.attribute_length, 4,
"attribute_length of EnclosingMethod attribute in the class : " + className);
String expectedClassName = enclosingMethod.enclosingClazz().getName();
checkEquals(classFile.constant_pool.getClassInfo(attr.class_index).getName(),
expectedClassName, String.format(
"enclosing class of EnclosingMethod attribute in the class %s is %s",
className, expectedClassName));
String expectedMethodName = enclosingMethod.enclosingMethod();
if (expectedMethodName.isEmpty()) {
// class does not have an enclosing method
checkEquals(attr.method_index, 0, String.format(
"enclosing method of EnclosingMethod attribute in the class %s is null", className));
} else {
String methodName = classFile.constant_pool.getNameAndTypeInfo(attr.method_index).getName();
checkTrue(methodName.startsWith(expectedMethodName), String.format(
"enclosing method of EnclosingMethod attribute in the class %s" +
" is method name %s" +
", actual method name is %s",
className, expectedMethodName, methodName));
}
} catch (Exception e) {
addFailure(e);
}
});
}
private long countEnclosingMethodAttributes(ClassFile classFile) {
return Stream.of(classFile.attributes.attrs)
.filter(x -> x instanceof EnclosingMethod_attribute)
.count();
}
@Retention(RetentionPolicy.RUNTIME)
public @interface ExpectedEnclosingMethod {
String info();
Class<?> enclosingClazz();
String enclosingMethod() default "";
}
public static void main(String[] args) throws ClassNotFoundException, TestFailedException {
new EnclosingMethodTest().test();
}
// Test cases: enclosing class is a top-level class
static {
// anonymous and local classes in static initializer
@ExpectedEnclosingMethod(
info = "EnclosingStaticInitialization in EnclosingMethodTest",
enclosingClazz = EnclosingMethodTest.class
)
class EnclosingStaticInitialization {
}
new EnclosingStaticInitialization() {
};
}
{
// anonymous and local classes in instance initializer
@ExpectedEnclosingMethod(
info = "EnclosingInitialization in EnclosingMethodTest",
enclosingClazz = EnclosingMethodTest.class
)
class EnclosingInitialization {
}
new EnclosingInitialization() {
};
}
Runnable lambda = () -> {
// anonymous and local classes in lambda
@ExpectedEnclosingMethod(
info = "EnclosingLambda in EnclosingMethodTest",
enclosingMethod = "lambda",
enclosingClazz = EnclosingMethodTest.class
)
class EnclosingLambda {
}
new EnclosingLambda() {
};
};
EnclosingMethodTest(int i) {
// anonymous and local classes in constructor
@ExpectedEnclosingMethod(
info = "EnclosingConstructor in EnclosingMethodTest",
enclosingMethod = "<init>",
enclosingClazz = EnclosingMethodTest.class
)
class EnclosingConstructor {
}
new EnclosingConstructor() {
};
}
void method() {
// anonymous and local classes in method
@ExpectedEnclosingMethod(
info = "EnclosingMethod in EnclosingMethodTest",
enclosingMethod = "method",
enclosingClazz = EnclosingMethodTest.class
)
class EnclosingMethod {
}
new EnclosingMethod() {
};
}
@ExpectedEnclosingMethod(
info = "VariableInitializer in EnclosingMethodTest",
enclosingClazz = EnclosingMethodTest.class
)
static class VariableInitializer {
}
// static variable initializer
private static final VariableInitializer cvi = new VariableInitializer() {
};
// instance variable initializer
private final VariableInitializer ivi = new VariableInitializer() {
};
// Test cases: enclosing class is an inner class
public static class notEnclosing01 {
static {
// anonymous and local classes in static initializer
@ExpectedEnclosingMethod(
info = "EnclosingStaticInitialization in notEnclosing01",
enclosingClazz = notEnclosing01.class
)
class EnclosingStaticInitialization {
}
new EnclosingStaticInitialization() {
};
}
{
// anonymous and local classes in instance initializer
@ExpectedEnclosingMethod(
info = "EnclosingInitialization in notEnclosing01",
enclosingClazz = notEnclosing01.class
)
class EnclosingInitialization {
}
new EnclosingInitialization() {
};
}
Runnable lambda = () -> {
// anonymous and local classes in lambda
@ExpectedEnclosingMethod(
info = "EnclosingLambda in notEnclosing01",
enclosingMethod = "lambda",
enclosingClazz = notEnclosing01.class
)
class EnclosingLambda {
}
new EnclosingLambda() {
};
};
notEnclosing01() {
// anonymous and local classes in constructor
@ExpectedEnclosingMethod(
info = "EnclosingConstructor in notEnclosing01",
enclosingMethod = "<init>",
enclosingClazz = notEnclosing01.class
)
class EnclosingConstructor {
}
new EnclosingConstructor() {
};
}
void method() {
// anonymous and local classes in method
@ExpectedEnclosingMethod(
info = "EnclosingMethod in notEnclosing01",
enclosingMethod = "method",
enclosingClazz = notEnclosing01.class
)
class EnclosingMethod {
}
new EnclosingMethod() {
};
}
@ExpectedEnclosingMethod(
info = "VariableInitializer in notEnclosing01",
enclosingClazz = notEnclosing01.class
)
static class VariableInitializer {
}
// static variable initializer
private static final VariableInitializer cvi = new VariableInitializer() {
};
// instance variable initializer
private final VariableInitializer ivi = new VariableInitializer() {
};
}
// Test cases: enclosing class is an interface
public interface notEnclosing02 {
Runnable lambda = () -> {
// anonymous and local classes in lambda
@ExpectedEnclosingMethod(
info = "EnclosingLambda in notEnclosing02",
enclosingMethod = "lambda",
enclosingClazz = notEnclosing02.class
)
class EnclosingLambda {
}
new EnclosingLambda() {
};
};
static void staticMethod() {
// anonymous and local classes in static method
@ExpectedEnclosingMethod(
info = "EnclosingMethod in notEnclosing02",
enclosingMethod = "staticMethod",
enclosingClazz = notEnclosing02.class
)
class EnclosingMethod {
}
new EnclosingMethod() {
};
}
default void defaultMethod() {
// anonymous and local classes in default method
@ExpectedEnclosingMethod(
info = "EnclosingMethod in notEnclosing02",
enclosingMethod = "defaultMethod",
enclosingClazz = notEnclosing02.class
)
class EnclosingMethod {
}
new EnclosingMethod() {
};
}
@ExpectedEnclosingMethod(
info = "VariableInitializer in notEnclosing02",
enclosingClazz = notEnclosing02.class
)
static class VariableInitializer {
}
// static variable initializer
VariableInitializer cvi = new VariableInitializer() {
};
}
// Test cases: enclosing class is an enum
public enum notEnclosing03 {;
static {
// anonymous and local classes in static initializer
@ExpectedEnclosingMethod(
info = "EnclosingStaticInitialization in notEnclosing03",
enclosingClazz = notEnclosing03.class
)
class EnclosingStaticInitialization {
}
new EnclosingStaticInitialization() {
};
}
{
// anonymous and local classes in instance initializer
@ExpectedEnclosingMethod(
info = "EnclosingInitialization in notEnclosing03",
enclosingClazz = notEnclosing03.class
)
class EnclosingInitialization {
}
new EnclosingInitialization() {
};
}
Runnable lambda = () -> {
// anonymous and local classes in lambda
@ExpectedEnclosingMethod(
info = "EnclosingLambda in notEnclosing03",
enclosingMethod = "lambda",
enclosingClazz = notEnclosing03.class
)
class EnclosingLambda {
}
new EnclosingLambda() {
};
};
notEnclosing03() {
// anonymous and local classes in constructor
@ExpectedEnclosingMethod(
info = "EnclosingConstructor in notEnclosing03",
enclosingMethod = "<init>",
enclosingClazz = notEnclosing03.class
)
class EnclosingConstructor {
}
new EnclosingConstructor() {
};
}
void method() {
// anonymous and local classes in method
@ExpectedEnclosingMethod(
info = "EnclosingMethod in notEnclosing03",
enclosingMethod = "method",
enclosingClazz = notEnclosing03.class
)
class EnclosingMethod {
}
new EnclosingMethod() {
};
}
@ExpectedEnclosingMethod(
info = "VariableInitializer in notEnclosing03",
enclosingClazz = notEnclosing03.class
)
static class VariableInitializer {
}
// static variable initializer
private static final VariableInitializer cvi = new VariableInitializer() {
};
// instance variable initializer
private final VariableInitializer ivi = new VariableInitializer() {
};
}
// Test cases: enclosing class is an annotation
public @interface notEnclosing04 {
Runnable lambda = () -> {
// anonymous and local classes in lambda
@ExpectedEnclosingMethod(
info = "EnclosingLambda in notEnclosing04",
enclosingMethod = "lambda",
enclosingClazz = notEnclosing04.class
)
class EnclosingLambda {
}
new EnclosingLambda() {
};
};
@ExpectedEnclosingMethod(
info = "VariableInitializer in notEnclosing04",
enclosingClazz = notEnclosing04.class
)
static class VariableInitializer {
}
// static variable initializer
VariableInitializer cvi = new VariableInitializer() {
};
}
}

View File

@ -74,13 +74,13 @@ public class DeprecatedPackageTest extends TestResult {
addTestCase(src);
printf("Testing test case: \n%s\n", src);
try {
ClassFile cf = ClassFile.read(compile(
ClassFile cf = readClassFile(compile(
new String[]{"package-info.java", package_info},
new String[]{"notDeprecated.java", src})
.getClasses().get(CLASS_NAME).openInputStream());
.getClasses().get(CLASS_NAME));
Deprecated_attribute attr =
(Deprecated_attribute) cf.getAttribute(Attribute.Deprecated);
assertNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
checkNull(attr, "Class can not have deprecated attribute : " + CLASS_NAME);
} catch (Exception e) {
addFailure(e);
}

View File

@ -240,7 +240,7 @@ public class DeprecatedTest extends TestResult {
? "deprecated"
: "notDeprecated";
echo("Testing outer class : " + outerClassName);
ClassFile cf = ClassFile.read(classes.get(outerClassName).openInputStream());
ClassFile cf = readClassFile(classes.get(outerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
cf.getAttribute(Attribute.Deprecated);
testAttribute(outerClassName, attr, cf);
@ -260,7 +260,7 @@ public class DeprecatedTest extends TestResult {
String innerClassName = cf.constant_pool.
getClassInfo(innerClass.inner_class_info_index).getName();
echo("Testing inner class : " + innerClassName);
ClassFile innerCf = ClassFile.read(classes.get(innerClassName).openInputStream());
ClassFile innerCf = readClassFile(classes.get(innerClassName));
Deprecated_attribute attr = (Deprecated_attribute)
innerCf.getAttribute(Attribute.Deprecated);
String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool);
@ -298,17 +298,18 @@ public class DeprecatedTest extends TestResult {
if (name.contains("deprecated")) {
testDeprecatedAttribute(name, attr, cf);
} else {
assertNull(attr, name + " should not have deprecated attribute");
checkNull(attr, name + " should not have deprecated attribute");
}
}
private void testDeprecatedAttribute(String name, Deprecated_attribute attr, ClassFile cf)
throws ConstantPoolException {
assertNotNull(attr, name + " must have deprecated attribute");
assertEquals(0, attr.attribute_length,
"attribute_length should equal to 0");
assertEquals("Deprecated",
cf.constant_pool.getUTF8Value(attr.attribute_name_index),
name + " attribute_name_index");
if (checkNotNull(attr, name + " must have deprecated attribute")) {
checkEquals(0, attr.attribute_length,
"attribute_length should equal to 0");
checkEquals("Deprecated",
cf.constant_pool.getUTF8Value(attr.attribute_name_index),
name + " attribute_name_index");
}
}
}

View File

@ -96,21 +96,21 @@ public class InnerClassesHierarchyTest extends TestResult {
ClassFile cf = readClassFile(currentClassName);
InnerClasses_attribute attr = (InnerClasses_attribute)
cf.getAttribute(Attribute.InnerClasses);
assertNotNull(attr, "Class should not contain "
checkNotNull(attr, "Class should not contain "
+ "inner classes attribute : " + currentClassName);
assertTrue(innerClasses.containsKey(currentClassName),
checkTrue(innerClasses.containsKey(currentClassName),
"map contains class name : " + currentClassName);
Set<String> setClasses = innerClasses.get(currentClassName);
if (setClasses == null) {
continue;
}
assertEquals(attr.number_of_classes,
checkEquals(attr.number_of_classes,
setClasses.size(),
"Check number of inner classes : " + setClasses);
for (Info info : attr.classes) {
String innerClassName = info
.getInnerClassInfo(cf.constant_pool).getBaseName();
assertTrue(setClasses.contains(innerClassName),
checkTrue(setClasses.contains(innerClassName),
currentClassName + " contains inner class : "
+ innerClassName);
if (visitedClasses.add(innerClassName)) {
@ -124,10 +124,10 @@ public class InnerClassesHierarchyTest extends TestResult {
Set<String> a_b = removeAll(visitedClasses, allClasses);
Set<String> b_a = removeAll(allClasses, visitedClasses);
assertEquals(visitedClasses, allClasses,
checkEquals(visitedClasses, allClasses,
"All classes are found\n"
+ "visited - all classes : " + a_b
+ "\nall classes - visited : " + b_a);
+ "visited - all classes : " + a_b
+ "\nall classes - visited : " + b_a);
} catch (Exception e) {
addFailure(e);
} finally {

View File

@ -78,16 +78,16 @@ public class InnerClassesIndexTest extends TestResult {
continue;
}
foundClasses.add(innerName);
assertEquals(info.outer_class_info_index, 0,
checkEquals(info.outer_class_info_index, 0,
"outer_class_info_index of " + innerName);
if (innerName.matches("\\$\\d+")) {
assertEquals(info.inner_name_index, 0,
checkEquals(info.inner_name_index, 0,
"inner_name_index of anonymous class");
}
}
Set<String> expectedClasses = getInnerClasses();
expectedClasses.remove("InnerClassesIndexTest$Inner");
assertEquals(foundClasses, expectedClasses, "All classes are found");
checkEquals(foundClasses, expectedClasses, "All classes are found");
} catch (Exception e) {
addFailure(e);
} finally {

View File

@ -202,44 +202,44 @@ public abstract class InnerClassesTestBase extends TestResult {
++count;
}
}
assertEquals(1, count, "Number of inner classes attribute");
if (innerClasses == null) {
checkEquals(1, count, "Number of inner classes attribute");
if (!checkNotNull(innerClasses, "InnerClasses attribute should not be null")) {
return;
}
assertEquals(cf.constant_pool.
checkEquals(cf.constant_pool.
getUTF8Info(innerClasses.attribute_name_index).value, "InnerClasses",
"innerClasses.attribute_name_index");
// Inner Classes attribute consists of length (2 bytes)
// and 8 bytes for each inner class's entry.
assertEquals(innerClasses.attribute_length,
checkEquals(innerClasses.attribute_length,
2 + 8 * class2Flags.size(), "innerClasses.attribute_length");
assertEquals(innerClasses.number_of_classes,
checkEquals(innerClasses.number_of_classes,
class2Flags.size(), "innerClasses.number_of_classes");
Set<String> visitedClasses = new HashSet<>();
for (Info e : innerClasses.classes) {
String baseName = cf.constant_pool.getClassInfo(
e.inner_class_info_index).getBaseName();
if (cf.major_version >= 51 && e.inner_name_index == 0) {
assertEquals(e.outer_class_info_index, 0,
"outer_class_info_index "
+ "in case of inner_name_index is zero : "
+ baseName);
checkEquals(e.outer_class_info_index, 0,
"outer_class_info_index "
+ "in case of inner_name_index is zero : "
+ baseName);
}
String className = baseName.replaceFirst(".*\\$", "");
assertTrue(class2Flags.containsKey(className),
checkTrue(class2Flags.containsKey(className),
className);
assertTrue(visitedClasses.add(className),
checkTrue(visitedClasses.add(className),
"there are no duplicates in attribute : " + className);
assertEquals(e.inner_class_access_flags.getInnerClassFlags(),
checkEquals(e.inner_class_access_flags.getInnerClassFlags(),
class2Flags.get(className),
"inner_class_access_flags " + className);
if (!Arrays.asList(skipClasses).contains(className)) {
assertEquals(
cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
classToTest + "$" + className,
"inner_class_info_index of " + className);
checkEquals(
cf.constant_pool.getClassInfo(e.inner_class_info_index).getBaseName(),
classToTest + "$" + className,
"inner_class_info_index of " + className);
if (e.outer_class_info_index > 0) {
assertEquals(
checkEquals(
cf.constant_pool.getClassInfo(e.outer_class_info_index).getName(),
classToTest,
"outer_class_info_index of " + className);

View File

@ -25,10 +25,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -78,8 +75,8 @@ public class TestBase {
/**
* Compiles sources in memory.
*
* @param sources to compile.
* @return memory file manager which contains class files and class loader.
* @param sources to compile
* @return in-memory file manager which contains class files and class loader
*/
public InMemoryFileManager compile(String... sources)
throws IOException, CompilationException {
@ -91,7 +88,7 @@ public class TestBase {
*
* @param options compiler options.
* @param sources sources to compile.
* @return map where key is className, value is corresponding ClassFile.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String... sources)
throws IOException, CompilationException {
@ -102,7 +99,7 @@ public class TestBase {
* Compiles sources in memory.
*
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
* @return map where key is className, value is corresponding ClassFile.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(String[]... sources) throws IOException,
CompilationException {
@ -114,7 +111,7 @@ public class TestBase {
*
* @param options compiler options
* @param sources sources[i][0] - name of file, sources[i][1] - sources.
* @return map where key is className, value is corresponding ClassFile.
* @return in-memory file manager which contains class files and class loader.
*/
public InMemoryFileManager compile(List<String> options, String[]... sources)
throws IOException, CompilationException {
@ -142,7 +139,9 @@ public class TestBase {
* @throws ConstantPoolException if constant pool error occurs
*/
public ClassFile readClassFile(JavaFileObject fileObject) throws IOException, ConstantPoolException {
return readClassFile(fileObject.openInputStream());
try (InputStream is = fileObject.openInputStream()) {
return readClassFile(is);
}
}
/**
@ -205,6 +204,12 @@ public class TestBase {
assertEquals(actual, false, message);
}
public void assertContains(Set<?> found, Set<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
assertTrue(found.containsAll(expected), message + " : " + copy);
}
public File getSourceDir() {
return new File(System.getProperty("test.src", "."));
}

View File

@ -24,10 +24,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
import java.util.stream.Stream;
import static java.lang.String.format;
import static java.util.stream.Collectors.joining;
import java.util.stream.Collectors;
/**
* This class accumulates test results. Test results can be checked with method @{code checkStatus}.
@ -52,39 +49,46 @@ public class TestResult extends TestBase {
private String errorMessage() {
return testCases.stream().filter(Info::isFailed)
.map(tc -> format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
.collect(joining("\n"));
.map(tc -> String.format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage()))
.collect(Collectors.joining("\n"));
}
@Override
public void assertEquals(Object actual, Object expected, String message) {
getLastTestCase().assertEquals(actual, expected, message);
public boolean checkEquals(Object actual, Object expected, String message) {
echo("Testing : " + message);
if (!Objects.equals(actual, expected)) {
getLastTestCase().addAssert(new AssertionFailedException(
String.format("%s%nGot: %s, Expected: %s", message, actual, expected)));
return false;
}
return true;
}
@Override
public void assertNull(Object actual, String message) {
getLastTestCase().assertEquals(actual, null, message);
public boolean checkNull(Object actual, String message) {
return checkEquals(actual, null, message);
}
@Override
public void assertNotNull(Object actual, String message) {
getLastTestCase().assertNotNull(actual, message);
public boolean checkNotNull(Object actual, String message) {
echo("Testing : " + message);
if (Objects.isNull(actual)) {
getLastTestCase().addAssert(new AssertionFailedException(
message + " : Expected not null value"));
return false;
}
return true;
}
@Override
public void assertFalse(boolean actual, String message) {
getLastTestCase().assertEquals(actual, false, message);
public boolean checkFalse(boolean actual, String message) {
return checkEquals(actual, false, message);
}
@Override
public void assertTrue(boolean actual, String message) {
getLastTestCase().assertEquals(actual, true, message);
public boolean checkTrue(boolean actual, String message) {
return checkEquals(actual, true, message);
}
public void assertContains(Set<?> found, Set<?> expected, String message) {
public boolean checkContains(Set<?> found, Set<?> expected, String message) {
Set<?> copy = new HashSet<>(expected);
copy.removeAll(found);
assertTrue(found.containsAll(expected), message + " : " + copy);
return checkTrue(found.containsAll(expected), message + " : " + copy);
}
public void addFailure(Throwable th) {
@ -99,10 +103,10 @@ public class TestResult extends TestBase {
}
/**
* Throws {@code TestFailedException} if one of the asserts are failed
* Throws {@code TestFailedException} if one of the checks are failed
* or an exception occurs. Prints error message of failed test cases.
*
* @throws TestFailedException if one of the asserts are failed
* @throws TestFailedException if one of the checks are failed
* or an exception occurs
*/
public void checkStatus() throws TestFailedException {
@ -115,7 +119,7 @@ public class TestResult extends TestBase {
private class Info {
private final String info;
private final List<String> asserts;
private final List<AssertionFailedException> asserts;
private final List<Throwable> errors;
private Info(String info) {
@ -137,45 +141,20 @@ public class TestResult extends TestBase {
printf("[ERROR] : %s\n", getStackTrace(th));
}
public void addFailure(String message) {
String stackTrace = Stream.of(Thread.currentThread().getStackTrace())
// just to get stack trace without TestResult and Thread
.filter(e -> !"TestResult.java".equals(e.getFileName()) &&
!"java.lang.Thread".equals(e.getClassName()))
.map(e -> "\tat " + e)
.collect(joining("\n"));
asserts.add(format("%s\n%s", message, stackTrace));
printf("[ASSERT] : %s\n", message);
}
public void assertEquals(Object actual, Object expected, String message) {
echo("Testing : " + message);
if (!Objects.equals(actual, expected)) {
addFailure(message + ": Got: " + actual + ", " + "Expected: " + expected);
}
}
public void assertNotNull(Object actual, String message) {
echo("Testing : " + message);
if (actual == null) {
addFailure(message + " : Expected not null value");
}
public void addAssert(AssertionFailedException e) {
asserts.add(e);
printf("[ASSERT] : %s\n", getStackTrace(e));
}
public String getMessage() {
return (asserts.size() > 0 ? getAssertMessage() + "\n" : "") + getErrorMessage();
return (asserts.size() > 0 ? getErrorMessage("[ASSERT]", asserts) + "\n" : "")
+ getErrorMessage("[ERROR]", errors);
}
public String getAssertMessage() {
return asserts.stream()
.map(failure -> "[ASSERT] : " + failure)
.collect(joining("\n"));
}
public String getErrorMessage() {
return errors.stream()
.map(throwable -> format("[ERROR] : %s", getStackTrace(throwable)))
.collect(joining("\n"));
public String getErrorMessage(String header, List<? extends Throwable> list) {
return list.stream()
.map(throwable -> String.format("%s : %s", header, getStackTrace(throwable)))
.collect(Collectors.joining("\n"));
}
public String getStackTrace(Throwable throwable) {

View File

@ -0,0 +1,23 @@
/*
* @test /nodynamiccopyright/
* @bug 8064464
* @summary regression with type inference of conditional expression
* @compile/fail/ref=T8064464.out -XDrawDiagnostics T8064464.java
*/
import java.util.List;
class T8064464 {
String f(Object o) { return null; }
Integer f(int i) { return null; }
<X extends Integer> X id() { return null; }
void m(List<Integer> lx) {
Integer i1 = f(!lx.isEmpty() ? 0 : lx.get(0)); //ok --> f(int)
Integer i2 = f(!lx.isEmpty() ? lx.get(0) : 0); //ok --> f(int)
f(!lx.isEmpty() ? id() : 0); // ambiguous
f(!lx.isEmpty() ? 0 : id()); // ambiguous
}
}

View File

@ -0,0 +1,3 @@
T8064464.java:20:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464
T8064464.java:21:5: compiler.err.ref.ambiguous: f, kindname.method, f(java.lang.Object), T8064464, kindname.method, f(int), T8064464
2 errors

View File

@ -24,9 +24,9 @@
// key: compiler.err.neither.conditional.subtype
class NeitherConditionalSubtype {
public int test(Object o) {
public int test(boolean cond, Object o) {
// Should fail to compile since Object.wait() has a void return type.
System.out.println(o instanceof String ? o.hashCode() : o.wait());
(o instanceof String ? o.hashCode() : o.wait()).toString();
return 0;
}
}

View File

@ -25,7 +25,6 @@
* @test
* @bug 6499673
* @library /tools/javac/lib
* @ignore 8062245 Test executes incorrect class
* @build JavacTestingAbstractProcessor BoundsTest
* @run main BoundsTest
* @summary Assertion check for TypeVariable.getUpperBound() fails
@ -86,8 +85,8 @@ public class BoundsTest {
};
private static final String[] NoBounds_supers = {};
private HashSet<CharSequence> expected_bounds;
private HashSet<CharSequence> expected_supers;
private HashSet<String> expected_bounds;
private HashSet<String> expected_supers;
private static final File classesdir = new File("intersectionproperties");
private static final JavaCompiler comp =
@ -99,8 +98,8 @@ public class BoundsTest {
final String[] Test_bounds, final String[] Test_supers)
throws IOException {
System.err.println("Testing " + Test_name);
expected_bounds = new HashSet<CharSequence>(Arrays.asList(Test_bounds));
expected_supers = new HashSet<CharSequence>(Arrays.asList(Test_supers));
expected_bounds = new HashSet<>(Arrays.asList(Test_bounds));
expected_supers = new HashSet<>(Arrays.asList(Test_supers));
final Iterable<? extends JavaFileObject> files =
fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents)));
final JavacTask ct =
@ -130,7 +129,7 @@ public class BoundsTest {
}
public static void main(String... args) throws IOException {
new IntersectionPropertiesTest().run();
new BoundsTest().run();
}
private static File writeFile(File dir, String path, String body)
@ -166,18 +165,17 @@ public class BoundsTest {
final List<? extends TypeMirror> bounds = typeParameterElement.getBounds();
final List<? extends TypeMirror> supers = processingEnv.getTypeUtils().directSupertypes(upperBound);
final HashSet<CharSequence> actual_bounds = new HashSet<CharSequence>();
final HashSet<CharSequence> actual_supers = new HashSet<CharSequence>();
final HashSet<String> actual_bounds = new HashSet<>();
final HashSet<String> actual_supers = new HashSet<>();
for(TypeMirror ty : bounds) {
actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName());
actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString());
}
for(TypeMirror ty : supers) {
actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName());
actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName().toString());
}
if (!expected_bounds.equals(actual_bounds)) {
System.err.println("Mismatched expected and actual bounds.");
System.err.println("Expected:");
@ -190,7 +188,7 @@ public class BoundsTest {
}
if (!expected_supers.equals(actual_supers)) {
System.err.println("Mismatched expected and actual bounds.");
System.err.println("Mismatched expected and actual supers.");
System.err.println("Expected:");
for(CharSequence tm : expected_supers)
System.err.println(" " + tm);

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @summary WriteableScope.dupUnshared not working properly for shared Scopes.
*/
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.file.JavacFileManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Objects;
import java.util.Set;
public class DupUnsharedTest {
public static void main(String... args) throws Exception {
new DupUnsharedTest().run();
}
Context context;
Names names;
Symtab symtab;
Name a;
Name b;
int errors;
public DupUnsharedTest() {
context = new Context();
JavacFileManager.preRegister(context); // required by ClassReader which is required by Symtab
names = Names.instance(context);
symtab = Symtab.instance(context);
a = names.fromString("a");
b = names.fromString("b");
}
void run() throws Exception {
runScopeContentTest();
runClashTest();
if (errors > 0)
throw new AssertionError("Errors detected (" + errors + ").");
}
void runScopeContentTest() throws Exception {
Set<Symbol> expected = Collections.newSetFromMap(new IdentityHashMap<>());
Set<Symbol> notExpected = Collections.newSetFromMap(new IdentityHashMap<>());
WriteableScope s1 = WriteableScope.create(symtab.rootPackage);
ClassSymbol acceptSym = symtab.arrayClass;
s1.enter(acceptSym);
expected.add(acceptSym);
WriteableScope s2 = s1.dup();
fillScope(s2, notExpected, a);
WriteableScope s3 = s2.dup();
fillScope(s3, notExpected, b);
WriteableScope s4 = s1.dupUnshared();
assertEquals(toSet(s4.getSymbols()), expected);
assertEquals(toSet(s4.getSymbolsByName(a)), Collections.emptySet());
assertEquals(toSet(s4.getSymbolsByName(b)), Collections.emptySet());
assertEquals(toSet(s4.getSymbolsByName(acceptSym.name)), expected);
for (Symbol sym : notExpected) {
try {
s4.remove(sym);
} catch (Exception ex) {
System.err.println("s4.remove(" + sym + "); crashes with exception:");
ex.printStackTrace();
errors++;
}
}
}
void fillScope(WriteableScope scope, Set<Symbol> notExpected, Name name) {
VarSymbol var1 = new VarSymbol(0, name, Type.noType, symtab.arrayClass);
VarSymbol var2 = new VarSymbol(0, name, Type.noType, symtab.autoCloseableClose.owner);
scope.enter(var1);
scope.enter(var2);
scope.remove(var1);
notExpected.add(var1);
notExpected.add(var2);
}
Set<Symbol> toSet(Iterable<Symbol> it) {
Set<Symbol> result = Collections.newSetFromMap(new IdentityHashMap<>());
for (Symbol sym : it) {
result.add(sym);
}
return result;
}
void assertEquals(Set<Symbol> set1, Set<Symbol> set2) {
if (!Objects.equals(set1, set2)) {
System.err.println("Sets are not equals: s1=" + set1 + "; s2=" + set2);
errors++;
}
}
/**
* This tests tests the following situation.
* - consider empty Scope S1
* - a Symbol with name 'A' is added into S1
* - S1 is dupped into S2
* - a Symbol with name 'B', clashing with 'A', is added into S2
* - so the table now looks like: [..., A, ..., B, ...]
* - S2 is doubled. As a consequence, the table is re-hashed, and looks like:
* [..., B, ..., A, ...] (note that re-hashing goes from the end, hence the original order).
* - B has been chosen so that it clashes in the doubled scope as well. So when looking up 'A',
* B is found (and rejected) first, and only then the A's bucket is tested.
* - S2 is dupUshared - the resulting table needs to look like: [..., /sentinel/, ..., A, ...], not
* [..., null, ..., A, ...], as in the latter case lookups would see 'null' while looking for
* 'A' and would stop the search prematurely.
*/
void runClashTest() throws Exception {
WriteableScope emptyScope = WriteableScope.create(symtab.unnamedPackage);
Field tableField = emptyScope.getClass().getDeclaredField("table");
tableField.setAccessible(true);
Method dble = emptyScope.getClass().getDeclaredMethod("dble");
dble.setAccessible(true);
Method getIndex = emptyScope.getClass().getDeclaredMethod("getIndex", Name.class);
getIndex.setAccessible(true);
int tries = 0;
//find a name that will be in the first bucket in table (so that a conflicting name
//will be in placed in a bucket after this one).
Name first = names.fromString("a");
while ((Integer) getIndex.invoke(emptyScope, first) != 0) {
if (tries++ > MAX_TRIES) {
System.err.println("could not find a name that would be placed in the first bucket");
errors++;
return ;
}
first = names.fromString("a" + first.toString());
}
System.out.println("first name: " + first);
//now, find another name, that will clash with the first one both in the empty and a doubled scope:
Scope doubledEmptyScope = WriteableScope.create(symtab.unnamedPackage);
dble.invoke(doubledEmptyScope);
Integer firstNameTestScopeIndex = (Integer) getIndex.invoke(emptyScope, first);
Integer firstNameDoubleScopeIndex = (Integer) getIndex.invoke(doubledEmptyScope, first);
Name other = names.fromString("b");
while (!Objects.equals(firstNameTestScopeIndex, getIndex.invoke(emptyScope, other)) ||
!Objects.equals(firstNameDoubleScopeIndex, getIndex.invoke(doubledEmptyScope, other))) {
if (tries++ > MAX_TRIES) {
System.err.println("could not find a name that would properly clash with the first chosen name");
errors++;
return ;
}
other = names.fromString("b" + other);
}
System.out.println("other name: " + other);
Symbol firstSymbol = new VarSymbol(0, first, Type.noType, null);
Symbol otherSymbol = new VarSymbol(0, other, Type.noType, null);
//test the situation described above:
WriteableScope testScope1 = WriteableScope.create(symtab.unnamedPackage);
testScope1.enter(firstSymbol);
WriteableScope dupped1 = testScope1.dup();
dupped1.enter(otherSymbol);
dble.invoke(dupped1);
if (testScope1.dupUnshared().findFirst(first) != firstSymbol) {
System.err.println("cannot find the Symbol in the dupUnshared scope (1)");
errors++;
}
//also check a situation where the clashing Symbol is removed from the dupped scope:
WriteableScope testScope2 = WriteableScope.create(symtab.unnamedPackage);
testScope2.enter(firstSymbol);
WriteableScope dupped2 = testScope2.dup();
dupped2.enter(otherSymbol);
dble.invoke(dupped2);
dupped2.remove(otherSymbol);
if (testScope2.dupUnshared().findFirst(first) != firstSymbol) {
System.err.println("cannot find the Symbol in the dupUnshared scope (2)");
errors++;
}
}
int MAX_TRIES = 100; // max tries to find a hash clash before giving up.
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import javax.annotation.processing.*;
import javax.tools.Diagnostic.Kind;
import javax.lang.model.element.TypeElement;
import java.util.Set;
/*
* @test
* @bug 8060448
* @summary Test that javac doesn't throw ArrayIndexOutOfBoundsException
* when logging the message "\n"
* @library /tools/javac/lib
* @build JavacTestingAbstractProcessor NewlineOnlyDiagnostic
* @compile -processor NewlineOnlyDiagnostic NewlineOnlyDiagnostic.java
*/
public class NewlineOnlyDiagnostic extends JavacTestingAbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> types,RoundEnvironment rEnv) {
processingEnv.getMessager().printMessage(Kind.NOTE,"\n");
return true;
}
}

View File

@ -21,6 +21,7 @@
* questions.
*/
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
@ -28,6 +29,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.FilterWriter;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -49,12 +51,15 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@ -64,18 +69,20 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.JavaFileManager.Location;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.api.JavacTool;
import java.io.IOError;
/**
* Utility methods and classes for writing jtreg tests for
@ -233,7 +240,7 @@ public class ToolBox {
public void createDirectories(String... paths) throws IOException {
if (paths.length == 0)
throw new IllegalArgumentException("no directories specified");
for (String p: paths)
for (String p : paths)
Files.createDirectories(Paths.get(p));
}
@ -248,7 +255,7 @@ public class ToolBox {
public void createDirectories(Path... paths) throws IOException {
if (paths.length == 0)
throw new IllegalArgumentException("no directories specified");
for (Path p: paths)
for (Path p : paths)
Files.createDirectories(p);
}
@ -262,7 +269,7 @@ public class ToolBox {
public void deleteFiles(String... files) throws IOException {
if (files.length == 0)
throw new IllegalArgumentException("no files specified");
for (String file: files)
for (String file : files)
Files.delete(Paths.get(file));
}
@ -392,7 +399,7 @@ public class ToolBox {
public void writeJavaFiles(Path dir, String... contents) throws IOException {
if (contents.length == 0)
throw new IllegalArgumentException("no content specified for any files");
for (String c: contents) {
for (String c : contents) {
new JavaSource(c).write(dir);
}
}
@ -1090,7 +1097,7 @@ public class ToolBox {
private List<File> toFiles(String path) {
List<File> result = new ArrayList<>();
for (String s: path.split(File.pathSeparator)) {
for (String s : path.split(File.pathSeparator)) {
if (!s.isEmpty())
result.add(new File(s));
}
@ -1108,7 +1115,7 @@ public class ToolBox {
if (fileObjects == null)
return filesAsFileObjects;
List<JavaFileObject> combinedList = new ArrayList<>();
for (JavaFileObject o: filesAsFileObjects)
for (JavaFileObject o : filesAsFileObjects)
combinedList.add(o);
combinedList.addAll(fileObjects);
return combinedList;
@ -1308,6 +1315,7 @@ public class ToolBox {
private String mainClass;
private Path baseDir;
private List<Path> paths;
private Set<FileObject> fileObjects;
/**
* Creates a task to write jar files, using API mode.
@ -1315,6 +1323,7 @@ public class ToolBox {
public JarTask() {
super(Mode.API);
paths = Collections.emptyList();
fileObjects = new LinkedHashSet<>();
}
/**
@ -1391,6 +1400,53 @@ public class ToolBox {
return this;
}
/**
* Adds a set of file objects to be written into the jar file, by copying them
* from a Location in a JavaFileManager.
* The file objects to be written are specified by a series of paths;
* each path can be in one of the following forms:
* <ul>
* <li>The name of a class. For example, java.lang.Object.
* In this case, the corresponding .class file will be written to the jar file.
* <li>the name of a package followed by {@code .*}. For example, {@code java.lang.*}.
* In this case, all the class files in the specified package will be written to
* the jar file.
* <li>the name of a package followed by {@code .**}. For example, {@code java.lang.**}.
* In this case, all the class files in the specified package, and any subpackages
* will be written to the jar file.
* </ul>
*
* @param fm the file manager in which to find the file objects
* @param l the location in which to find the file objects
* @param paths the paths specifying the file objects to be copied
* @return this task object
* @throws IOException if errors occur while determining the set of file objects
*/
public JarTask files(JavaFileManager fm, Location l, String... paths)
throws IOException {
for (String p : paths) {
if (p.endsWith(".**"))
addPackage(fm, l, p.substring(0, p.length() - 3), true);
else if (p.endsWith(".*"))
addPackage(fm, l, p.substring(0, p.length() - 2), false);
else
addFile(fm, l, p);
}
return this;
}
private void addPackage(JavaFileManager fm, Location l, String pkg, boolean recurse)
throws IOException {
for (JavaFileObject fo : fm.list(l, pkg, EnumSet.allOf(JavaFileObject.Kind.class), recurse)) {
fileObjects.add(fo);
}
}
private void addFile(JavaFileManager fm, Location l, String path) throws IOException {
JavaFileObject fo = fm.getJavaFileForInput(l, path, Kind.CLASS);
fileObjects.add(fo);
}
/**
* Provides limited jar command-like functionality.
* The supported commands are:
@ -1464,42 +1520,19 @@ public class ToolBox {
StreamOutput sysOut = new StreamOutput(System.out, System::setOut);
StreamOutput sysErr = new StreamOutput(System.err, System::setErr);
int rc;
Map<OutputKind, String> outputMap = new HashMap<>();
try (OutputStream os = Files.newOutputStream(jar);
JarOutputStream jos = openJar(os, m)) {
Path base = (baseDir == null) ? currDir : baseDir;
for (Path path: paths) {
Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
try {
String p = base.relativize(file)
.normalize()
.toString()
.replace(File.separatorChar, '/');
JarEntry e = new JarEntry(p);
jos.putNextEntry(e);
jos.write(Files.readAllBytes(file));
jos.closeEntry();
return FileVisitResult.CONTINUE;
} catch (IOException e) {
System.err.println("Error adding " + file + " to jar file: " + e);
return FileVisitResult.TERMINATE;
}
}
});
}
rc = 0;
writeFiles(jos);
writeFileObjects(jos);
} catch (IOException e) {
System.err.println("Error opening " + jar + ": " + e);
rc = 1;
error("Exception while opening " + jar, e);
} finally {
outputMap.put(OutputKind.STDOUT, sysOut.close());
outputMap.put(OutputKind.STDERR, sysErr.close());
}
return checkExit(new Result(this, rc, outputMap));
return checkExit(new Result(this, (errors == 0) ? 0 : 1, outputMap));
}
private JarOutputStream openJar(OutputStream os, Manifest m) throws IOException {
@ -1512,6 +1545,79 @@ public class ToolBox {
}
}
private void writeFiles(JarOutputStream jos) throws IOException {
Path base = (baseDir == null) ? currDir : baseDir;
for (Path path : paths) {
Files.walkFileTree(base.resolve(path), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
try {
String p = base.relativize(file)
.normalize()
.toString()
.replace(File.separatorChar, '/');
JarEntry e = new JarEntry(p);
jos.putNextEntry(e);
try {
jos.write(Files.readAllBytes(file));
} finally {
jos.closeEntry();
}
return FileVisitResult.CONTINUE;
} catch (IOException e) {
error("Exception while adding " + file + " to jar file", e);
return FileVisitResult.TERMINATE;
}
}
});
}
}
private void writeFileObjects(JarOutputStream jos) throws IOException {
for (FileObject fo : fileObjects) {
String p = guessPath(fo);
JarEntry e = new JarEntry(p);
jos.putNextEntry(e);
try {
byte[] buf = new byte[1024];
try (BufferedInputStream in = new BufferedInputStream(fo.openInputStream())) {
int n;
while ((n = in.read(buf)) > 0)
jos.write(buf, 0, n);
} catch (IOException ex) {
error("Exception while adding " + fo.getName() + " to jar file", ex);
}
} finally {
jos.closeEntry();
}
}
}
/*
* A jar: URL is of the form jar:URL!/entry where URL is a URL for the .jar file itself.
* In Symbol files (i.e. ct.sym) the underlying entry is prefixed META-INF/sym/<base>.
*/
private final Pattern jarEntry = Pattern.compile(".*!/(?:META-INF/sym/[^/]+/)?(.*)");
private String guessPath(FileObject fo) {
URI u = fo.toUri();
switch (u.getScheme()) {
case "jar":
Matcher m = jarEntry.matcher(u.getSchemeSpecificPart());
if (m.matches()) {
return m.group(1);
}
break;
}
throw new IllegalArgumentException(fo.getName());
}
private void error(String message, Throwable t) {
out.println("Error: " + message + ": " + t);
errors++;
}
private int errors;
}
/**