This commit is contained in:
Lana Steuck 2013-01-16 12:07:32 -08:00
commit 7026f02404
106 changed files with 6141 additions and 1131 deletions
.hgtags.hgtags-top-repo
common/bin
corba
hotspot
jaxp
jaxws
jdk
.hgtags
src/share/classes/javax/swing
test/javax/swing/JTable/8005019
langtools
.hgtags
make
makefiles
src/share/classes
test

@ -192,3 +192,5 @@ a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65
cb33628d4e8f11e879c371959e5948b66a53376f jdk8-b68
adb5171c554e14cd86f618b5584f6e3d693d5889 jdk8-b69
0d625373c69e2ad6f546fd88ab50c6c9aad01271 jdk8-b70
a41ada2ed4ef735449531c6ebe6cec593d890a1c jdk8-b71
6725b3961f987cf40f446d1c11cd324a3bec545f jdk8-b72

@ -192,3 +192,5 @@ b772de306dc24c17f7bd1398531ddeb58723b804 jdk8-b65
cdb401a60cea6ad5ef3f498725ed1decf8dda1ea jdk8-b68
6ee8080a6efe0639fcd00627a5e0f839bf010481 jdk8-b69
105a25ffa4a4f0af70188d4371b4a0385009b7ce jdk8-b70
51ad2a34342055333eb5f36e2fb514b027895708 jdk8-b71
c1be681d80a1f1c848dc671d664fccb19e046a12 jdk8-b72

@ -80,6 +80,7 @@ ACCEPTED_BIN_DIFF="
./bin/javadoc
./bin/javah
./bin/javap
./bin/jdeps
./bin/jcmd
./bin/jconsole
./bin/jdb
@ -167,6 +168,7 @@ ACCEPTED_BIN_DIFF="
./bin/javadoc
./bin/javah
./bin/javap
./bin/jdeps
./bin/jcmd
./bin/jconsole
./bin/jdb
@ -309,6 +311,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/javadoc
./bin/javah
./bin/javap
./bin/jdeps
./bin/javaws
./bin/jcmd
./bin/jconsole
@ -449,6 +452,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/amd64/javadoc
./bin/amd64/javah
./bin/amd64/javap
./bin/amd64/jdeps
./bin/amd64/jcmd
./bin/amd64/jconsole
./bin/amd64/jdb
@ -606,6 +610,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/javadoc
./bin/javah
./bin/javap
./bin/jdeps
./bin/javaws
./bin/jcmd
./bin/jconsole
@ -751,6 +756,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/sparcv9/javadoc
./bin/sparcv9/javah
./bin/sparcv9/javap
./bin/sparcv9/jdeps
./bin/sparcv9/jcmd
./bin/sparcv9/jconsole
./bin/sparcv9/jdb
@ -826,6 +832,7 @@ ACCEPTED_SMALL_SIZE_DIFF="
./bin/javadoc.exe
./bin/javah.exe
./bin/javap.exe
./bin/jdeps.exe
./bin/javaw.exe
./bin/jcmd.exe
./bin/jconsole.exe
@ -910,6 +917,7 @@ ACCEPTED_BIN_DIFF="
./bin/javadoc
./bin/javah
./bin/javap
./bin/jdeps
./bin/jcmd
./bin/jconsole
./bin/jdb

@ -192,3 +192,5 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59
82000531feaa7baef76b6406099e5cd88943d635 jdk8-b68
22ddcac208a8dea894a16887d04f3ca4d3c5d267 jdk8-b69
603cceb495c8133d47b26a7502d51c7d8a67d76b jdk8-b70
8171d23e914d758836527b80b06debcfdb718f2d jdk8-b71
cb40427f47145b01b7e53c3e02b38ff7625efbda jdk8-b72

@ -304,3 +304,5 @@ b6c9c0109a608eedbb6b868d260952990e3c91fe hs25-b13
cb8a4e04bc8c104de8a2f67463c7e31232bf8d68 jdk8-b69
990bbd393c239d95310ccc38094e57923bbf1d4a hs25-b14
e94068d4ff52849c8aa0786a53a59b63d1312a39 jdk8-b70
0847210f85480bf3848dc90bc2ab23c0a4791b55 jdk8-b71
d5cb5830f570d1304ea4b196dde672a291b55f29 jdk8-b72

@ -192,3 +192,5 @@ e6af1ad464e3d9b1154b9f9ed9a5373b97d129fc jdk8-b66
b854e70084214e9dcf1b37373f6e4b1a68760e03 jdk8-b68
789a855de959f7e9600e57759c6c3dbb0b24d78b jdk8-b69
6ec9edffc286c9c9ac96c9cd2050b01cb5d514a8 jdk8-b70
499be952a291cec1dc774a84a238941d6faf772d jdk8-b71
bdf2af722a6b54fca47d8c51d17a1b8f41dd7a3e jdk8-b72

@ -192,3 +192,5 @@ eb06aa51dfc225614dba2d89ae7ca6cedddff982 jdk8-b67
d3fe408f3a9ad250bc9a4e9365bdfc3f28c1d3f4 jdk8-b68
756323c990115a9c0341d67b10f2d52c6370e35d jdk8-b69
3b1c2733d47ee9f8c530925df4041c59f9ee5a31 jdk8-b70
f577a39c9fb3d5820248c13c2cc74a192a9313e0 jdk8-b71
d9707230294d54e695e745a90de6112909100f12 jdk8-b72

@ -192,3 +192,5 @@ ce9b02a3a17edd1983201002cfa0f364e4ab7524 jdk8-b67
53fb43e4d614c92310e1fb00ec41d1960fd9facf jdk8-b68
a8012d8d7e9c5035de0bdd4887dc9f7c54008f21 jdk8-b69
a996b57e554198f4592a5f3c30f2f9f4075e545d jdk8-b70
2a5af0f766d0acd68a81fb08fe11fd66795f86af jdk8-b71
32a57e645e012a1f0665c075969ca598e0dbb948 jdk8-b72

@ -3953,7 +3953,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
break;
case TableModelEvent.INSERT:
modelSelection.insertIndexInterval(change.startModelIndex,
change.endModelIndex,
change.length,
true);
break;
default:

@ -0,0 +1,103 @@
/*
* Copyright (c) 2010, 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 8005019
* @summary JTable passes row index instead of length when inserts selection interval
* @author Alexander Scherbatiy
* @run main bug8005019
*/
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class bug8005019 {
public static void main(String[] args) throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
testSelectionWithFilterTable();
}
});
}
private static void testSelectionWithFilterTable() {
DefaultTableModel model = new DefaultTableModel(0, 1);
// a model with 3 elements is the minimum to demonstrate
// the bug
int last = 2;
for (int i = 0; i <= last; i++) {
model.addRow(new Object[]{i});
}
JTable table = new JTable(model);
table.setAutoCreateRowSorter(true);
// set selection at the end
table.setRowSelectionInterval(last, last);
// exclude rows based on identifier
RowFilter filter = new GeneralFilter(new int[]{0});
((DefaultRowSorter) table.getRowSorter()).setRowFilter(filter);
// insertRow _before or at_ selected model index, such that
// endIndex (in event) > 1
model.insertRow(2, new Object[]{"x"});
}
private static class GeneralFilter extends RowFilter<Object, Object> {
private int[] columns;
List excludes = Arrays.asList(0);
GeneralFilter(int[] columns) {
this.columns = columns;
}
public boolean include(RowFilter.Entry<? extends Object, ? extends Object> value) {
int count = value.getValueCount();
if (columns.length > 0) {
for (int i = columns.length - 1; i >= 0; i--) {
int index = columns[i];
if (index < count) {
if (include(value, index)) {
return true;
}
}
}
} else {
while (--count >= 0) {
if (include(value, count)) {
return true;
}
}
}
return false;
}
protected boolean include(
Entry<? extends Object, ? extends Object> entry,
int index) {
return !excludes.contains(entry.getIdentifier());
}
}
}

@ -192,3 +192,5 @@ e6ee43b3e2473798b17a556e9f11eebe25ab81d4 jdk8-b64
014a6a11dfe5ddc23ec8c76bb42ac998dbf49acb jdk8-b68
d7360bf35ee1f40ff78c2e83a22b5446ee464346 jdk8-b69
47f71d7c124f24c2fe2dfc49865b332345b458ed jdk8-b70
467e4d9281bcf119eaec42af1423c96bd401871c jdk8-b71
6f0986ed9b7e11d6eb06618f27e20b18f19fb797 jdk8-b72

@ -153,6 +153,7 @@ javah.tests = \
javap.includes = \
com/sun/tools/classfile/ \
com/sun/tools/javap/ \
com/sun/tools/jdeps/ \
sun/tools/javap/
javap.tests = \

@ -75,6 +75,7 @@ $(LANGTOOLS_OUTPUTDIR)/gensrc/_the_props.d : $(PROPSOURCES) $(BUILD_TOOLS)
printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties
printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javap/resources/version.properties
printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties
printf "jdk=$(JDK_VERSION)\nfull=$(FULL_VERSION)\nrelease=$(RELEASE)\n" > $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.properties
echo Compiling $(words $(PROPSOURCES) v1 v2 v3) properties into resource bundles
$(TOOL_COMPILEPROPS_CMD) $(PROPCMDLINE) \
-compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javah/resources/version.properties \
@ -85,6 +86,9 @@ $(LANGTOOLS_OUTPUTDIR)/gensrc/_the_props.d : $(PROPSOURCES) $(BUILD_TOOLS)
java.util.ListResourceBundle \
-compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.properties \
$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/javac/resources/version.java \
java.util.ListResourceBundle \
-compile $(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.properties \
$(LANGTOOLS_OUTPUTDIR)/gensrc/com/sun/tools/jdeps/resources/version.java \
java.util.ListResourceBundle
echo PROPS_ARE_CREATED=yes > $@

@ -52,6 +52,12 @@ public interface AnnotationDesc {
*/
ElementValuePair[] elementValues();
/**
* Check for the synthesized bit on the annotation.
*
* @return true if the annotation is synthesized.
*/
boolean isSynthesized();
/**
* Represents an association between an annotation type element

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2012, 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
@ -51,6 +51,7 @@ public abstract class Attribute {
public static final String LineNumberTable = "LineNumberTable";
public static final String LocalVariableTable = "LocalVariableTable";
public static final String LocalVariableTypeTable = "LocalVariableTypeTable";
public static final String MethodParameters = "MethodParameters";
public static final String RuntimeVisibleAnnotations = "RuntimeVisibleAnnotations";
public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
@ -113,6 +114,7 @@ public abstract class Attribute {
standardAttributes.put(LocalVariableTypeTable, LocalVariableTypeTable_attribute.class);
if (!compat) { // old javap does not recognize recent attributes
standardAttributes.put(MethodParameters, MethodParameters_attribute.class);
standardAttributes.put(CompilationID, CompilationID_attribute.class);
standardAttributes.put(RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations_attribute.class);
standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
@ -171,6 +173,7 @@ public abstract class Attribute {
R visitLineNumberTable(LineNumberTable_attribute attr, P p);
R visitLocalVariableTable(LocalVariableTable_attribute attr, P p);
R visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, P p);
R visitMethodParameters(MethodParameters_attribute attr, P p);
R visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, P p);
R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);

@ -1,6 +1,6 @@
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2012, 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
@ -479,6 +479,15 @@ public class ClassWriter {
out.writeShort(entry.index);
}
public Void visitMethodParameters(MethodParameters_attribute attr, ClassOutputStream out) {
out.writeByte(attr.method_parameter_table.length);
for (MethodParameters_attribute.Entry e : attr.method_parameter_table) {
out.writeShort(e.name_index);
out.writeInt(e.flags);
}
return null;
}
public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, ClassOutputStream out) {
annotationWriter.write(attr.annotations, out);
return null;

@ -141,6 +141,15 @@ public class Dependencies {
return new APIDependencyFinder(access);
}
/**
* Get a finder to do class dependency analysis.
*
* @return a Class dependency finder
*/
public static Finder getClassDependencyFinder() {
return new ClassDependencyFinder();
}
/**
* Get the finder used to locate the dependencies for a class.
* @return the finder
@ -246,8 +255,6 @@ public class Dependencies {
return results;
}
/**
* Find the dependencies of a class, using the current
* {@link Dependencies#getFinder finder} and
@ -306,38 +313,44 @@ public class Dependencies {
* A location identifying a class.
*/
static class SimpleLocation implements Location {
public SimpleLocation(String className) {
this.className = className;
public SimpleLocation(String name) {
this.name = name;
this.className = name.replace('/', '.').replace('$', '.');
}
public String getName() {
return name;
}
/**
* Get the name of the class being depended on. This name will be used to
* locate the class file for transitive dependency analysis.
* @return the name of the class being depended on
*/
public String getClassName() {
return className;
}
public String getPackageName() {
int i = name.lastIndexOf('/');
return (i > 0) ? name.substring(0, i).replace('/', '.') : "";
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
if (!(other instanceof SimpleLocation))
return false;
return (className.equals(((SimpleLocation) other).className));
return (name.equals(((SimpleLocation) other).name));
}
@Override
public int hashCode() {
return className.hashCode();
return name.hashCode();
}
@Override
public String toString() {
return className;
return name;
}
private String name;
private String className;
}
@ -431,9 +444,7 @@ public class Dependencies {
}
public boolean accepts(Dependency dependency) {
String cn = dependency.getTarget().getClassName();
int lastSep = cn.lastIndexOf("/");
String pn = (lastSep == -1 ? "" : cn.substring(0, lastSep));
String pn = dependency.getTarget().getPackageName();
if (packageNames.contains(pn))
return true;
@ -451,8 +462,6 @@ public class Dependencies {
private final boolean matchSubpackages;
}
/**
* This class identifies class names directly or indirectly in the constant pool.
*/
@ -462,6 +471,26 @@ public class Dependencies {
for (CPInfo cpInfo: classfile.constant_pool.entries()) {
v.scan(cpInfo);
}
try {
v.addClass(classfile.super_class);
v.addClasses(classfile.interfaces);
v.scan(classfile.attributes);
for (Field f : classfile.fields) {
v.scan(f.descriptor, f.attributes);
}
for (Method m : classfile.methods) {
v.scan(m.descriptor, m.attributes);
Exceptions_attribute e =
(Exceptions_attribute)m.attributes.get(Attribute.Exceptions);
if (e != null) {
v.addClasses(e.exception_index_table);
}
}
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
return v.deps;
}
}
@ -558,9 +587,7 @@ public class Dependencies {
void scan(Descriptor d, Attributes attrs) {
try {
scan(new Signature(d.index).getType(constant_pool));
Signature_attribute sa = (Signature_attribute) attrs.get(Attribute.Signature);
if (sa != null)
scan(new Signature(sa.signature_index).getType(constant_pool));
scan(attrs);
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
@ -574,6 +601,43 @@ public class Dependencies {
t.accept(this, null);
}
void scan(Attributes attrs) {
try {
Signature_attribute sa = (Signature_attribute)attrs.get(Attribute.Signature);
if (sa != null)
scan(sa.getParsedSignature().getType(constant_pool));
scan((RuntimeVisibleAnnotations_attribute)
attrs.get(Attribute.RuntimeVisibleAnnotations));
scan((RuntimeVisibleParameterAnnotations_attribute)
attrs.get(Attribute.RuntimeVisibleParameterAnnotations));
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
}
private void scan(RuntimeAnnotations_attribute attr) throws ConstantPoolException {
if (attr == null) {
return;
}
for (int i = 0; i < attr.annotations.length; i++) {
int index = attr.annotations[i].type_index;
scan(new Signature(index).getType(constant_pool));
}
}
private void scan(RuntimeParameterAnnotations_attribute attr) throws ConstantPoolException {
if (attr == null) {
return;
}
for (int param = 0; param < attr.parameter_annotations.length; param++) {
for (int i = 0; i < attr.parameter_annotations[param].length; i++) {
int index = attr.parameter_annotations[param][i].type_index;
scan(new Signature(index).getType(constant_pool));
}
}
}
void addClass(int index) throws ConstantPoolException {
if (index != 0) {
String name = constant_pool.getClassInfo(index).getBaseName();
@ -698,6 +762,7 @@ public class Dependencies {
findDependencies(type.paramTypes);
findDependencies(type.returnType);
findDependencies(type.throwsTypes);
findDependencies(type.typeParamTypes);
return null;
}
@ -709,7 +774,7 @@ public class Dependencies {
public Void visitClassType(ClassType type, Void p) {
findDependencies(type.outerType);
addDependency(type.name);
addDependency(type.getBinaryName());
findDependencies(type.typeArgs);
return null;
}

@ -71,7 +71,19 @@ public interface Dependency {
* dependency analysis.
* @return the name of the class containing the location.
*/
String getName();
/**
* Get the fully-qualified name of the class containing the location.
* @return the fully-qualified name of the class containing the location.
*/
String getClassName();
/**
* Get the package name of the class containing the location.
* @return the package name of the class containing the location.
*/
String getPackageName();
}

@ -0,0 +1,87 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.classfile;
import java.io.IOException;
/**
* See JVMS, section 4.8.13.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class MethodParameters_attribute extends Attribute {
public final int method_parameter_table_length;
public final Entry[] method_parameter_table;
MethodParameters_attribute(ClassReader cr,
int name_index,
int length)
throws IOException {
super(name_index, length);
method_parameter_table_length = cr.readUnsignedByte();
method_parameter_table = new Entry[method_parameter_table_length];
for (int i = 0; i < method_parameter_table_length; i++)
method_parameter_table[i] = new Entry(cr);
}
public MethodParameters_attribute(ConstantPool constant_pool,
Entry[] method_parameter_table)
throws ConstantPoolException {
this(constant_pool.getUTF8Index(Attribute.MethodParameters),
method_parameter_table);
}
public MethodParameters_attribute(int name_index,
Entry[] method_parameter_table) {
super(name_index, 1 + method_parameter_table.length * Entry.length());
this.method_parameter_table_length = method_parameter_table.length;
this.method_parameter_table = method_parameter_table;
}
public <R, D> R accept(Visitor<R, D> visitor, D data) {
return visitor.visitMethodParameters(this, data);
}
public static class Entry {
Entry(ClassReader cr) throws IOException {
name_index = cr.readUnsignedShort();
flags = cr.readInt();
}
public static int length() {
return 6;
}
public final int name_index;
public final int flags;
}
}

@ -321,7 +321,8 @@ public abstract class AbstractMemberWriter {
code.addContent(" ");
}
if (member.isMethod()) {
if (((MethodDoc)member).isAbstract()) {
if (!(member.containingClass().isInterface()) &&
((MethodDoc)member).isAbstract()) {
code.addContent("abstract ");
}
// This check for isDefault() and the default modifier needs to be
@ -329,7 +330,7 @@ public abstract class AbstractMemberWriter {
// method summary section. Once the default modifier is added
// to the Modifier list on DocEnv and once it is updated to use the
// javax.lang.model.element.Modifier, we will need to remove this.
else if (((MethodDoc)member).isDefault()) {
if (((MethodDoc)member).isDefault()) {
code.addContent("default ");
}
}
@ -561,11 +562,14 @@ public abstract class AbstractMemberWriter {
if (member instanceof MethodDoc && !member.isAnnotationTypeElement()) {
int methodType = (member.isStatic()) ? MethodTypes.STATIC.value() :
MethodTypes.INSTANCE.value();
methodType = (classdoc.isInterface() || ((MethodDoc)member).isAbstract()) ?
methodType | MethodTypes.ABSTRACT.value() :
methodType | MethodTypes.CONCRETE.value();
if (((MethodDoc)member).isDefault()) {
methodType = methodType | MethodTypes.DEFAULT.value();
if (member.containingClass().isInterface()) {
methodType = (((MethodDoc) member).isAbstract())
? methodType | MethodTypes.ABSTRACT.value()
: methodType | MethodTypes.DEFAULT.value();
} else {
methodType = (((MethodDoc) member).isAbstract())
? methodType | MethodTypes.ABSTRACT.value()
: methodType | MethodTypes.CONCRETE.value();
}
if (Util.isDeprecated(member) || Util.isDeprecated(classdoc)) {
methodType = methodType | MethodTypes.DEPRECATED.value();

@ -89,6 +89,16 @@ public class HtmlDocletWriter extends HtmlDocWriter {
*/
protected boolean printedAnnotationHeading = false;
/**
* To check whether the repeated annotations is documented or not.
*/
private boolean isAnnotationDocumented = false;
/**
* To check whether the container annotations is documented or not.
*/
private boolean isContainerDocumented = false;
/**
* Constructor to construct the HtmlStandardWriter object.
*
@ -1793,50 +1803,66 @@ public class HtmlDocletWriter extends HtmlDocWriter {
StringBuilder annotation;
for (int i = 0; i < descList.length; i++) {
AnnotationTypeDoc annotationDoc = descList[i].annotationType();
if (! Util.isDocumentedAnnotation(annotationDoc)){
// If an annotation is not documented, do not add it to the list. If
// the annotation is of a repeatable type, and if it is not documented
// and also if its container annotation is not documented, do not add it
// to the list. If an annotation of a repeatable type is not documented
// but its container is documented, it will be added to the list.
if (! Util.isDocumentedAnnotation(annotationDoc) &&
(!isAnnotationDocumented && !isContainerDocumented)) {
continue;
}
annotation = new StringBuilder();
isAnnotationDocumented = false;
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
LinkInfoImpl.CONTEXT_ANNOTATION, annotationDoc);
linkInfo.label = "@" + annotationDoc.name();
annotation.append(getLink(linkInfo));
AnnotationDesc.ElementValuePair[] pairs = descList[i].elementValues();
if (pairs.length > 0) {
annotation.append('(');
// If the annotation is synthesized, do not print the container.
if (descList[i].isSynthesized()) {
for (int j = 0; j < pairs.length; j++) {
if (j > 0) {
annotation.append(",");
if (linkBreak) {
annotation.append(DocletConstants.NL);
int spaces = annotationDoc.name().length() + 2;
for (int k = 0; k < (spaces + indent); k++) {
annotation.append(' ');
}
}
}
annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
pairs[j].element(), pairs[j].element().name(), false));
annotation.append('=');
AnnotationValue annotationValue = pairs[j].value();
List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
if (annotationValue.value() instanceof AnnotationValue[]) {
AnnotationValue[] annotationArray =
(AnnotationValue[]) annotationValue.value();
for (int k = 0; k < annotationArray.length; k++) {
annotationTypeValues.add(annotationArray[k]);
}
(AnnotationValue[]) annotationValue.value();
annotationTypeValues.addAll(Arrays.asList(annotationArray));
} else {
annotationTypeValues.add(annotationValue);
}
annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
for (Iterator<AnnotationValue> iter = annotationTypeValues.iterator(); iter.hasNext(); ) {
annotation.append(annotationValueToString(iter.next()));
annotation.append(iter.hasNext() ? "," : "");
String sep = "";
for (AnnotationValue av : annotationTypeValues) {
annotation.append(sep);
annotation.append(annotationValueToString(av));
sep = " ";
}
annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
}
annotation.append(")");
}
else if (isAnnotationArray(pairs)) {
// If the container has 1 or more value defined and if the
// repeatable type annotation is not documented, do not print
// the container.
if (pairs.length == 1 && isAnnotationDocumented) {
AnnotationValue[] annotationArray =
(AnnotationValue[]) (pairs[0].value()).value();
List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
annotationTypeValues.addAll(Arrays.asList(annotationArray));
String sep = "";
for (AnnotationValue av : annotationTypeValues) {
annotation.append(sep);
annotation.append(annotationValueToString(av));
sep = " ";
}
}
// If the container has 1 or more value defined and if the
// repeatable type annotation is not documented, print the container.
else {
addAnnotations(annotationDoc, linkInfo, annotation, pairs,
indent, false);
}
}
else {
addAnnotations(annotationDoc, linkInfo, annotation, pairs,
indent, linkBreak);
}
annotation.append(linkBreak ? DocletConstants.NL : "");
results.add(annotation.toString());
@ -1844,6 +1870,91 @@ public class HtmlDocletWriter extends HtmlDocWriter {
return results;
}
/**
* Add annotation to the annotation string.
*
* @param annotationDoc the annotation being documented
* @param linkInfo the information about the link
* @param annotation the annotation string to which the annotation will be added
* @param pairs annotation type element and value pairs
* @param indent the number of extra spaces to indent the annotations.
* @param linkBreak if true, add new line between each member value
*/
private void addAnnotations(AnnotationTypeDoc annotationDoc, LinkInfoImpl linkInfo,
StringBuilder annotation, AnnotationDesc.ElementValuePair[] pairs,
int indent, boolean linkBreak) {
linkInfo.label = "@" + annotationDoc.name();
annotation.append(getLink(linkInfo));
if (pairs.length > 0) {
annotation.append('(');
for (int j = 0; j < pairs.length; j++) {
if (j > 0) {
annotation.append(",");
if (linkBreak) {
annotation.append(DocletConstants.NL);
int spaces = annotationDoc.name().length() + 2;
for (int k = 0; k < (spaces + indent); k++) {
annotation.append(' ');
}
}
}
annotation.append(getDocLink(LinkInfoImpl.CONTEXT_ANNOTATION,
pairs[j].element(), pairs[j].element().name(), false));
annotation.append('=');
AnnotationValue annotationValue = pairs[j].value();
List<AnnotationValue> annotationTypeValues = new ArrayList<AnnotationValue>();
if (annotationValue.value() instanceof AnnotationValue[]) {
AnnotationValue[] annotationArray =
(AnnotationValue[]) annotationValue.value();
annotationTypeValues.addAll(Arrays.asList(annotationArray));
} else {
annotationTypeValues.add(annotationValue);
}
annotation.append(annotationTypeValues.size() == 1 ? "" : "{");
String sep = "";
for (AnnotationValue av : annotationTypeValues) {
annotation.append(sep);
annotation.append(annotationValueToString(av));
sep = ",";
}
annotation.append(annotationTypeValues.size() == 1 ? "" : "}");
isContainerDocumented = false;
}
annotation.append(")");
}
}
/**
* Check if the annotation contains an array of annotation as a value. This
* check is to verify if a repeatable type annotation is present or not.
*
* @param pairs annotation type element and value pairs
*
* @return true if the annotation contains an array of annotation as a value.
*/
private boolean isAnnotationArray(AnnotationDesc.ElementValuePair[] pairs) {
AnnotationValue annotationValue;
for (int j = 0; j < pairs.length; j++) {
annotationValue = pairs[j].value();
if (annotationValue.value() instanceof AnnotationValue[]) {
AnnotationValue[] annotationArray =
(AnnotationValue[]) annotationValue.value();
if (annotationArray.length > 1) {
if (annotationArray[0].value() instanceof AnnotationDesc) {
AnnotationTypeDoc annotationDoc =
((AnnotationDesc) annotationArray[0].value()).annotationType();
isContainerDocumented = true;
if (Util.isDocumentedAnnotation(annotationDoc)) {
isAnnotationDocumented = true;
}
return true;
}
}
}
}
return false;
}
private String annotationValueToString(AnnotationValue annotationValue) {
if (annotationValue.value() instanceof Type) {
Type type = (Type) annotationValue.value();

@ -1283,8 +1283,9 @@ public abstract class Symbol implements Element {
List<Name> paramNames = savedParameterNames;
savedParameterNames = null;
// discard the provided names if the list of names is the wrong size.
if (paramNames == null || paramNames.size() != type.getParameterTypes().size())
if (paramNames == null || paramNames.size() != type.getParameterTypes().size()) {
paramNames = List.nil();
}
ListBuffer<VarSymbol> buf = new ListBuffer<VarSymbol>();
List<Name> remaining = paramNames;
// assert: remaining and paramNames are both empty or both

@ -38,6 +38,7 @@ import com.sun.tools.javac.tree.JCTree.*;
import javax.tools.JavaFileObject;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Queue;
@ -177,29 +178,19 @@ public class DeferredAttr extends JCTree.Visitor {
* attribution round must follow one or more speculative rounds.
*/
Type check(ResultInfo resultInfo) {
return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
}
Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
DeferredAttrContext deferredAttrContext =
resultInfo.checkContext.deferredAttrContext();
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
List<Type> stuckVars = stuckVars(tree, env, resultInfo);
if (stuckVars.nonEmpty()) {
deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
return Type.noType;
} else {
try {
switch (deferredAttrContext.mode) {
case SPECULATIVE:
Assert.check(mode == null ||
(mode == AttrMode.SPECULATIVE &&
speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
JCTree speculativeTree = attribSpeculative(tree, env, resultInfo);
speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
return speculativeTree.type;
case CHECK:
Assert.check(mode == AttrMode.SPECULATIVE);
return attr.attribTree(tree, env, resultInfo);
}
Assert.error();
return null;
return deferredTypeCompleter.complete(this, resultInfo, deferredAttrContext);
} finally {
mode = deferredAttrContext.mode;
}
@ -207,6 +198,43 @@ public class DeferredAttr extends JCTree.Visitor {
}
}
/**
* A completer for deferred types. Defines an entry point for type-checking
* a deferred type.
*/
interface DeferredTypeCompleter {
/**
* Entry point for type-checking a deferred type. Depending on the
* circumstances, type-checking could amount to full attribution
* or partial structural check (aka potential applicability).
*/
Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
}
/**
* A basic completer for deferred types. This completer type-checks a deferred type
* using attribution; depending on the attribution mode, this could be either standard
* or speculative attribution.
*/
DeferredTypeCompleter basicCompleter = new DeferredTypeCompleter() {
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
switch (deferredAttrContext.mode) {
case SPECULATIVE:
Assert.check(dt.mode == null ||
(dt.mode == AttrMode.SPECULATIVE &&
dt.speculativeType(deferredAttrContext.msym, deferredAttrContext.phase).hasTag(NONE)));
JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
return speculativeTree.type;
case CHECK:
Assert.check(dt.mode == AttrMode.SPECULATIVE);
return attr.attribTree(dt.tree, dt.env, resultInfo);
}
Assert.error();
return null;
}
};
/**
* The 'mode' in which the deferred type is to be type-checked
*/
@ -498,10 +526,80 @@ public class DeferredAttr extends JCTree.Visitor {
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
return List.nil();
} else {
StuckChecker sc = new StuckChecker(resultInfo, env);
return stuckVarsInternal(tree, resultInfo.pt, resultInfo.checkContext.inferenceContext());
}
}
//where
private List<Type> stuckVarsInternal(JCTree tree, Type pt, Infer.InferenceContext inferenceContext) {
StuckChecker sc = new StuckChecker(pt, inferenceContext);
sc.scan(tree);
return List.from(sc.stuckVars);
}
/**
* A special tree scanner that would only visit portions of a given tree.
* The set of nodes visited by the scanner can be customized at construction-time.
*/
abstract static class FilterScanner extends TreeScanner {
final Filter<JCTree> treeFilter;
FilterScanner(final Set<JCTree.Tag> validTags) {
this.treeFilter = new Filter<JCTree>() {
public boolean accepts(JCTree t) {
return validTags.contains(t.getTag());
}
};
}
@Override
public void scan(JCTree tree) {
if (tree != null) {
if (treeFilter.accepts(tree)) {
super.scan(tree);
} else {
skip(tree);
}
}
}
/**
* handler that is executed when a node has been discarded
*/
abstract void skip(JCTree tree);
}
/**
* A tree scanner suitable for visiting the target-type dependent nodes of
* a given argument expression.
*/
static class PolyScanner extends FilterScanner {
PolyScanner() {
super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE));
}
@Override
void skip(JCTree tree) {
//do nothing
}
}
/**
* A tree scanner suitable for visiting the target-type dependent nodes nested
* within a lambda expression body.
*/
static class LambdaReturnScanner extends FilterScanner {
LambdaReturnScanner() {
super(EnumSet.of(BLOCK, CASE, CATCH, DOLOOP, FOREACHLOOP,
FORLOOP, RETURN, SYNCHRONIZED, SWITCH, TRY, WHILELOOP));
}
@Override
void skip(JCTree tree) {
//do nothing
}
}
/**
@ -510,83 +608,32 @@ public class DeferredAttr extends JCTree.Visitor {
* inferring types that make some of the nested expressions incompatible
* with their corresponding instantiated target
*/
class StuckChecker extends TreeScanner {
class StuckChecker extends PolyScanner {
Type pt;
Filter<JCTree> treeFilter;
Infer.InferenceContext inferenceContext;
Set<Type> stuckVars = new LinkedHashSet<Type>();
Env<AttrContext> env;
final Filter<JCTree> argsFilter = new Filter<JCTree>() {
public boolean accepts(JCTree t) {
switch (t.getTag()) {
case CONDEXPR:
case LAMBDA:
case PARENS:
case REFERENCE:
return true;
default:
return false;
}
}
};
final Filter<JCTree> lambdaBodyFilter = new Filter<JCTree>() {
public boolean accepts(JCTree t) {
switch (t.getTag()) {
case BLOCK: case CASE: case CATCH: case DOLOOP:
case FOREACHLOOP: case FORLOOP: case RETURN:
case SYNCHRONIZED: case SWITCH: case TRY: case WHILELOOP:
return true;
default:
return false;
}
}
};
StuckChecker(ResultInfo resultInfo, Env<AttrContext> env) {
this.pt = resultInfo.pt;
this.inferenceContext = resultInfo.checkContext.inferenceContext();
this.treeFilter = argsFilter;
this.env = env;
}
@Override
public void scan(JCTree tree) {
if (tree != null && treeFilter.accepts(tree)) {
super.scan(tree);
}
StuckChecker(Type pt, Infer.InferenceContext inferenceContext) {
this.pt = pt;
this.inferenceContext = inferenceContext;
}
@Override
public void visitLambda(JCLambda tree) {
Type prevPt = pt;
Filter<JCTree> prevFilter = treeFilter;
try {
if (inferenceContext.inferenceVars().contains(pt)) {
stuckVars.add(pt);
}
if (!types.isFunctionalInterface(pt.tsym)) {
return;
}
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
if (!TreeInfo.isExplicitLambda(tree) &&
freeArgVars.nonEmpty()) {
stuckVars.addAll(freeArgVars);
}
pt = descType.getReturnType();
if (tree.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
scan(tree.getBody());
} else {
treeFilter = lambdaBodyFilter;
super.visitLambda(tree);
}
} finally {
pt = prevPt;
treeFilter = prevFilter;
if (inferenceContext.inferenceVars().contains(pt)) {
stuckVars.add(pt);
}
if (!types.isFunctionalInterface(pt.tsym)) {
return;
}
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
if (!TreeInfo.isExplicitLambda(tree) &&
freeArgVars.nonEmpty()) {
stuckVars.addAll(freeArgVars);
}
scanLambdaBody(tree, descType.getReturnType());
}
@Override
@ -605,16 +652,19 @@ public class DeferredAttr extends JCTree.Visitor {
stuckVars.addAll(freeArgVars);
}
@Override
public void visitReturn(JCReturn tree) {
Filter<JCTree> prevFilter = treeFilter;
try {
treeFilter = argsFilter;
if (tree.expr != null) {
scan(tree.expr);
}
} finally {
treeFilter = prevFilter;
void scanLambdaBody(JCLambda lambda, final Type pt) {
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
stuckVars.addAll(stuckVarsInternal(lambda.body, pt, inferenceContext));
} else {
LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
@Override
public void visitReturn(JCReturn tree) {
if (tree.expr != null) {
stuckVars.addAll(stuckVarsInternal(tree.expr, pt, inferenceContext));
}
}
};
lambdaScanner.scan(lambda.body);
}
}
}

@ -114,7 +114,7 @@ public class Infer {
}
}
private final InferenceException inferenceException;
final InferenceException inferenceException;
/***************************************************************************
* Mini/Maximization of UndetVars
@ -271,15 +271,19 @@ public class Infer {
boolean allowBoxing,
boolean useVarargs,
Resolve.MethodResolutionContext resolveContext,
Resolve.MethodCheck methodCheck,
Warner warn) throws InferenceException {
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
final InferenceContext inferenceContext = new InferenceContext(tvars, this, true);
inferenceException.clear();
DeferredAttr.DeferredAttrContext deferredAttrContext =
resolveContext.deferredAttrContext(msym, inferenceContext);
try {
rs.checkRawArgumentsAcceptable(env, msym, resolveContext.attrMode(), inferenceContext,
argtypes, mt.getParameterTypes(), allowBoxing, useVarargs, warn,
new InferenceCheckHandler(inferenceContext));
methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
deferredAttrContext.complete();
// minimize as yet undetermined type variables
for (Type t : inferenceContext.undetvars) {
@ -309,32 +313,6 @@ public class Infer {
inferenceContext.notifyChange(types);
}
}
//where
/** inference check handler **/
class InferenceCheckHandler implements Resolve.MethodCheckHandler {
InferenceContext inferenceContext;
public InferenceCheckHandler(InferenceContext inferenceContext) {
this.inferenceContext = inferenceContext;
}
public InapplicableMethodException arityMismatch() {
return inferenceException.setMessage("infer.arg.length.mismatch", inferenceContext.inferenceVars());
}
public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
String key = varargs ?
"infer.varargs.argument.mismatch" :
"infer.no.conforming.assignment.exists";
return inferenceException.setMessage(key,
inferenceContext.inferenceVars(), details);
}
public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
return inferenceException.setMessage("inaccessible.varargs.type",
expected, Kinds.kindName(location), location);
}
}
/** check that type parameters are within their bounds.
*/

@ -506,6 +506,7 @@ public class Resolve {
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
MethodCheck methodCheck,
Warner warn) throws Infer.InferenceException {
Type mt = types.memberType(site, m);
@ -558,10 +559,11 @@ public class Resolve {
allowBoxing,
useVarargs,
currentResolutionContext,
methodCheck,
warn);
checkRawArgumentsAcceptable(env, m, argtypes, mt.getParameterTypes(),
allowBoxing, useVarargs, warn);
methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
argtypes, mt.getParameterTypes(), warn);
return mt;
}
@ -578,7 +580,7 @@ public class Resolve {
currentResolutionContext.attrMode = DeferredAttr.AttrMode.CHECK;
MethodResolutionPhase step = currentResolutionContext.step = env.info.pendingResolutionPhase;
return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
step.isBoxingRequired(), step.isVarargsRequired(), warn);
step.isBoxingRequired(), step.isVarargsRequired(), resolveMethodCheck, warn);
}
finally {
currentResolutionContext = prevContext;
@ -595,81 +597,66 @@ public class Resolve {
List<Type> typeargtypes,
boolean allowBoxing,
boolean useVarargs,
MethodCheck methodCheck,
Warner warn) {
try {
return rawInstantiate(env, site, m, resultInfo, argtypes, typeargtypes,
allowBoxing, useVarargs, warn);
allowBoxing, useVarargs, methodCheck, warn);
} catch (InapplicableMethodException ex) {
return null;
}
}
/** Check if a parameter list accepts a list of args.
/**
* This interface defines an entry point that should be used to perform a
* method check. A method check usually consist in determining as to whether
* a set of types (actuals) is compatible with another set of types (formals).
* Since the notion of compatibility can vary depending on the circumstances,
* this interfaces allows to easily add new pluggable method check routines.
*/
boolean argumentsAcceptable(Env<AttrContext> env,
Symbol msym,
interface MethodCheck {
/**
* Main method check routine. A method check usually consist in determining
* as to whether a set of types (actuals) is compatible with another set of
* types (formals). If an incompatibility is found, an unchecked exception
* is assumed to be thrown.
*/
void argumentsAcceptable(Env<AttrContext> env,
DeferredAttrContext deferredAttrContext,
List<Type> argtypes,
List<Type> formals,
boolean allowBoxing,
boolean useVarargs,
Warner warn) {
try {
checkRawArgumentsAcceptable(env, msym, argtypes, formals, allowBoxing, useVarargs, warn);
return true;
} catch (InapplicableMethodException ex) {
return false;
Warner warn);
}
/**
* Helper enum defining all method check diagnostics (used by resolveMethodCheck).
*/
enum MethodCheckDiag {
/**
* Actuals and formals differs in length.
*/
ARITY_MISMATCH("arg.length.mismatch", "infer.arg.length.mismatch"),
/**
* An actual is incompatible with a formal.
*/
ARG_MISMATCH("no.conforming.assignment.exists", "infer.no.conforming.assignment.exists"),
/**
* An actual is incompatible with the varargs element type.
*/
VARARG_MISMATCH("varargs.argument.mismatch", "infer.varargs.argument.mismatch"),
/**
* The varargs element type is inaccessible.
*/
INACCESSIBLE_VARARGS("inaccessible.varargs.type", "inaccessible.varargs.type");
final String basicKey;
final String inferKey;
MethodCheckDiag(String basicKey, String inferKey) {
this.basicKey = basicKey;
this.inferKey = inferKey;
}
}
/**
* A check handler is used by the main method applicability routine in order
* to handle specific method applicability failures. It is assumed that a class
* implementing this interface should throw exceptions that are a subtype of
* InapplicableMethodException (see below). Such exception will terminate the
* method applicability check and propagate important info outwards (for the
* purpose of generating better diagnostics).
*/
interface MethodCheckHandler {
/* The number of actuals and formals differ */
InapplicableMethodException arityMismatch();
/* An actual argument type does not conform to the corresponding formal type */
InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details);
/* The element type of a varargs is not accessible in the current context */
InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected);
}
/**
* Basic method check handler used within Resolve - all methods end up
* throwing InapplicableMethodException; a diagnostic fragment that describes
* the cause as to why the method is not applicable is set on the exception
* before it is thrown.
*/
MethodCheckHandler resolveHandler = new MethodCheckHandler() {
public InapplicableMethodException arityMismatch() {
return inapplicableMethodException.setMessage("arg.length.mismatch");
}
public InapplicableMethodException argumentMismatch(boolean varargs, JCDiagnostic details) {
String key = varargs ?
"varargs.argument.mismatch" :
"no.conforming.assignment.exists";
return inapplicableMethodException.setMessage(key,
details);
}
public InapplicableMethodException inaccessibleVarargs(Symbol location, Type expected) {
return inapplicableMethodException.setMessage("inaccessible.varargs.type",
expected, Kinds.kindName(location), location);
}
};
void checkRawArgumentsAcceptable(Env<AttrContext> env,
Symbol msym,
List<Type> argtypes,
List<Type> formals,
boolean allowBoxing,
boolean useVarargs,
Warner warn) {
checkRawArgumentsAcceptable(env, msym, currentResolutionContext.attrMode(), infer.emptyContext, argtypes, formals,
allowBoxing, useVarargs, warn, resolveHandler);
}
/**
* Main method applicability routine. Given a list of actual types A,
@ -689,68 +676,94 @@ public class Resolve {
*
* A method check handler (see above) is used in order to report errors.
*/
void checkRawArgumentsAcceptable(final Env<AttrContext> env,
Symbol msym,
DeferredAttr.AttrMode mode,
final Infer.InferenceContext inferenceContext,
List<Type> argtypes,
List<Type> formals,
boolean allowBoxing,
boolean useVarargs,
Warner warn,
final MethodCheckHandler handler) {
Type varargsFormal = useVarargs ? formals.last() : null;
MethodCheck resolveMethodCheck = new MethodCheck() {
@Override
public void argumentsAcceptable(final Env<AttrContext> env,
DeferredAttrContext deferredAttrContext,
List<Type> argtypes,
List<Type> formals,
Warner warn) {
//should we expand formals?
boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
throw handler.arityMismatch(); // not enough args
}
//inference context used during this method check
InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
DeferredAttr.DeferredAttrContext deferredAttrContext =
deferredAttr.new DeferredAttrContext(mode, msym, currentResolutionContext.step, inferenceContext);
Type varargsFormal = useVarargs ? formals.last() : null;
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
ResultInfo mresult = methodCheckResult(formals.head, allowBoxing, false, inferenceContext, deferredAttrContext, handler, warn);
mresult.check(null, argtypes.head);
argtypes = argtypes.tail;
formals = formals.tail;
}
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
if (formals.head != varargsFormal) {
throw handler.arityMismatch(); // not enough args
}
if (useVarargs) {
//note: if applicability check is triggered by most specific test,
//the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
final Type elt = types.elemtype(varargsFormal);
ResultInfo mresult = methodCheckResult(elt, allowBoxing, true, inferenceContext, deferredAttrContext, handler, warn);
while (argtypes.nonEmpty()) {
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn);
mresult.check(null, argtypes.head);
argtypes = argtypes.tail;
formals = formals.tail;
}
//check varargs element type accessibility
varargsAccessible(env, elt, handler, inferenceContext);
}
deferredAttrContext.complete();
}
if (formals.head != varargsFormal) {
report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
void varargsAccessible(final Env<AttrContext> env, final Type t, final Resolve.MethodCheckHandler handler, final InferenceContext inferenceContext) {
if (inferenceContext.free(t)) {
inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
varargsAccessible(env, inferenceContext.asInstType(t, types), handler, inferenceContext);
if (useVarargs) {
//note: if applicability check is triggered by most specific test,
//the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5)
final Type elt = types.elemtype(varargsFormal);
ResultInfo mresult = methodCheckResult(true, elt, deferredAttrContext, warn);
while (argtypes.nonEmpty()) {
mresult.check(null, argtypes.head);
argtypes = argtypes.tail;
}
});
} else {
if (!isAccessible(env, t)) {
Symbol location = env.enclClass.sym;
throw handler.inaccessibleVarargs(location, t);
//check varargs element type accessibility
varargsAccessible(env, elt, inferenceContext);
}
}
}
private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
boolean inferDiag = inferenceContext != infer.emptyContext;
InapplicableMethodException ex = inferDiag ?
infer.inferenceException : inapplicableMethodException;
if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
Object[] args2 = new Object[args.length + 1];
System.arraycopy(args, 0, args2, 1, args.length);
args2[0] = inferenceContext.inferenceVars();
args = args2;
}
throw ex.setMessage(inferDiag ? diag.inferKey : diag.basicKey, args);
}
private void varargsAccessible(final Env<AttrContext> env, final Type t, final InferenceContext inferenceContext) {
if (inferenceContext.free(t)) {
inferenceContext.addFreeTypeListener(List.of(t), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
varargsAccessible(env, inferenceContext.asInstType(t, types), inferenceContext);
}
});
} else {
if (!isAccessible(env, t)) {
Symbol location = env.enclClass.sym;
report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
}
}
}
private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
final DeferredAttr.DeferredAttrContext deferredAttrContext, Warner rsWarner) {
CheckContext checkContext = new MethodCheckContext(!deferredAttrContext.phase.isBoxingRequired(), deferredAttrContext, rsWarner) {
MethodCheckDiag methodDiag = varargsCheck ?
MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
report(methodDiag, deferredAttrContext.inferenceContext, details);
}
};
return new MethodResultInfo(to, checkContext);
}
};
/**
* Check context to be used during method applicability checks. A method check
@ -758,23 +771,24 @@ public class Resolve {
*/
abstract class MethodCheckContext implements CheckContext {
MethodCheckHandler handler;
boolean useVarargs;
Infer.InferenceContext inferenceContext;
boolean strict;
DeferredAttrContext deferredAttrContext;
Warner rsWarner;
public MethodCheckContext(MethodCheckHandler handler, boolean useVarargs,
Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
this.handler = handler;
this.useVarargs = useVarargs;
this.inferenceContext = inferenceContext;
this.deferredAttrContext = deferredAttrContext;
this.rsWarner = rsWarner;
public MethodCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
this.strict = strict;
this.deferredAttrContext = deferredAttrContext;
this.rsWarner = rsWarner;
}
public boolean compatible(Type found, Type req, Warner warn) {
return strict ?
types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asFree(req, types), warn) :
types.isConvertible(found, deferredAttrContext.inferenceContext.asFree(req, types), warn);
}
public void report(DiagnosticPosition pos, JCDiagnostic details) {
throw handler.argumentMismatch(useVarargs, details);
throw inapplicableMethodException.setMessage(details);
}
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
@ -782,7 +796,7 @@ public class Resolve {
}
public InferenceContext inferenceContext() {
return inferenceContext;
return deferredAttrContext.inferenceContext;
}
public DeferredAttrContext deferredAttrContext() {
@ -791,56 +805,13 @@ public class Resolve {
}
/**
* Subclass of method check context class that implements strict method conversion.
* Strict method conversion checks compatibility between types using subtyping tests.
* ResultInfo class to be used during method applicability checks. Check
* for deferred types goes through special path.
*/
class StrictMethodContext extends MethodCheckContext {
public StrictMethodContext(MethodCheckHandler handler, boolean useVarargs,
Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
}
public boolean compatible(Type found, Type req, Warner warn) {
return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn);
}
}
/**
* Subclass of method check context class that implements loose method conversion.
* Loose method conversion checks compatibility between types using method conversion tests.
*/
class LooseMethodContext extends MethodCheckContext {
public LooseMethodContext(MethodCheckHandler handler, boolean useVarargs,
Infer.InferenceContext inferenceContext, DeferredAttrContext deferredAttrContext, Warner rsWarner) {
super(handler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
}
public boolean compatible(Type found, Type req, Warner warn) {
return types.isConvertible(found, inferenceContext.asFree(req, types), warn);
}
}
/**
* Create a method check context to be used during method applicability check
*/
ResultInfo methodCheckResult(Type to, boolean allowBoxing, boolean useVarargs,
Infer.InferenceContext inferenceContext, DeferredAttr.DeferredAttrContext deferredAttrContext,
MethodCheckHandler methodHandler, Warner rsWarner) {
MethodCheckContext checkContext = allowBoxing ?
new LooseMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner) :
new StrictMethodContext(methodHandler, useVarargs, inferenceContext, deferredAttrContext, rsWarner);
return new MethodResultInfo(to, checkContext, deferredAttrContext);
}
class MethodResultInfo extends ResultInfo {
DeferredAttr.DeferredAttrContext deferredAttrContext;
public MethodResultInfo(Type pt, CheckContext checkContext, DeferredAttr.DeferredAttrContext deferredAttrContext) {
public MethodResultInfo(Type pt, CheckContext checkContext) {
attr.super(VAL, pt, checkContext);
this.deferredAttrContext = deferredAttrContext;
}
@Override
@ -855,12 +826,12 @@ public class Resolve {
@Override
protected MethodResultInfo dup(Type newPt) {
return new MethodResultInfo(newPt, checkContext, deferredAttrContext);
return new MethodResultInfo(newPt, checkContext);
}
@Override
protected ResultInfo dup(CheckContext newContext) {
return new MethodResultInfo(pt, newContext, deferredAttrContext);
return new MethodResultInfo(pt, newContext);
}
}
@ -1071,7 +1042,7 @@ public class Resolve {
Assert.check(sym.kind < AMBIGUOUS);
try {
Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
allowBoxing, useVarargs, types.noWarnings);
allowBoxing, useVarargs, resolveMethodCheck, types.noWarnings);
if (!operator)
currentResolutionContext.addApplicableCandidate(sym, mt);
} catch (InapplicableMethodException ex) {
@ -1151,52 +1122,20 @@ public class Resolve {
if (m1Abstract && !m2Abstract) return m2;
if (m2Abstract && !m1Abstract) return m1;
// both abstract or both concrete
if (!m1Abstract && !m2Abstract)
return ambiguityError(m1, m2);
// check that both signatures have the same erasure
if (!types.isSameTypes(m1.erasure(types).getParameterTypes(),
m2.erasure(types).getParameterTypes()))
return ambiguityError(m1, m2);
// both abstract, neither overridden; merge throws clause and result type
Type mst = mostSpecificReturnType(mt1, mt2);
if (mst == null) {
// Theoretically, this can't happen, but it is possible
// due to error recovery or mixing incompatible class files
return ambiguityError(m1, m2);
}
Symbol mostSpecific = mst == mt1 ? m1 : m2;
List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
MethodSymbol result = new MethodSymbol(
mostSpecific.flags(),
mostSpecific.name,
newSig,
mostSpecific.owner) {
@Override
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
if (origin == site.tsym)
return this;
else
return super.implementation(origin, types, checkResult);
}
};
return result;
return ambiguityError(m1, m2);
}
if (m1SignatureMoreSpecific) return m1;
if (m2SignatureMoreSpecific) return m2;
return ambiguityError(m1, m2);
case AMBIGUOUS:
//check if m1 is more specific than all ambiguous methods in m2
AmbiguityError e = (AmbiguityError)m2;
Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs);
Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs);
if (err1 == err2) return err1;
if (err1 == e.sym && err2 == e.sym2) return m2;
if (err1 instanceof AmbiguityError &&
err2 instanceof AmbiguityError &&
((AmbiguityError)err1).sym == ((AmbiguityError)err2).sym)
return ambiguityError(m1, m2);
else
return ambiguityError(err1, err2);
for (Symbol s : e.ambiguousSyms) {
if (mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs) != m1) {
return e.addAmbiguousSymbol(m1);
}
}
return m1;
default:
throw new AssertionError();
}
@ -1274,12 +1213,19 @@ public class Resolve {
}
//where
private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
noteWarner.clear();
Type mst = instantiate(env, site, m2, null,
types.lowerBounds(argtypes1), null,
allowBoxing, false, noteWarner);
return mst != null &&
!noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
MethodResolutionContext prevContext = currentResolutionContext;
try {
currentResolutionContext = new MethodResolutionContext();
currentResolutionContext.step = allowBoxing ? BOX : BASIC;
noteWarner.clear();
Type mst = instantiate(env, site, m2, null,
types.lowerBounds(argtypes1), null,
allowBoxing, false, resolveMethodCheck, noteWarner);
return mst != null &&
!noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
} finally {
currentResolutionContext = prevContext;
}
}
//where
private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
@ -2366,9 +2312,11 @@ public class Resolve {
try {
currentResolutionContext = new MethodResolutionContext();
Name name = treeinfo.operatorName(optag);
env.info.pendingResolutionPhase = currentResolutionContext.step = BASIC;
Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
null, false, false, true);
if (boxingEnabled && sym.kind >= WRONG_MTHS)
env.info.pendingResolutionPhase = currentResolutionContext.step = BOX;
sym = findMethod(env, syms.predefClass.type, name, argtypes,
null, true, false, true);
return accessMethod(sym, pos, env.enclClass.sym.type, name,
@ -2524,6 +2472,10 @@ public class Resolve {
@Override
Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
if (sym.kind == AMBIGUOUS) {
AmbiguityError a_err = (AmbiguityError)sym;
sym = a_err.mergeAbstracts(site);
}
if (sym.kind >= AMBIGUOUS) {
//if nothing is found return the 'first' error
sym = accessMethod(sym, pos, location, site, name, true, argtypes, typeargtypes);
@ -2579,6 +2531,10 @@ public class Resolve {
abstract JCMemberReference.ReferenceKind referenceKind(Symbol sym);
Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
if (sym.kind == AMBIGUOUS) {
AmbiguityError a_err = (AmbiguityError)sym;
sym = a_err.mergeAbstracts(site);
}
//skip error reporting
return sym;
}
@ -3014,9 +2970,7 @@ public class Resolve {
@Override
public Symbol access(Name name, TypeSymbol location) {
if (sym.kind >= AMBIGUOUS)
return ((ResolveError)sym).access(name, location);
else if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
if ((sym.kind & ERRONEOUS) == 0 && (sym.kind & TYP) != 0)
return types.createErrorType(name, location, sym.type).tsym;
else
return sym;
@ -3338,14 +3292,32 @@ public class Resolve {
* (either methods, constructors or operands) are ambiguous
* given an actual arguments/type argument list.
*/
class AmbiguityError extends InvalidSymbolError {
class AmbiguityError extends ResolveError {
/** The other maximally specific symbol */
Symbol sym2;
List<Symbol> ambiguousSyms = List.nil();
@Override
public boolean exists() {
return true;
}
AmbiguityError(Symbol sym1, Symbol sym2) {
super(AMBIGUOUS, sym1, "ambiguity error");
this.sym2 = sym2;
super(AMBIGUOUS, "ambiguity error");
ambiguousSyms = flatten(sym2).appendList(flatten(sym1));
}
private List<Symbol> flatten(Symbol sym) {
if (sym.kind == AMBIGUOUS) {
return ((AmbiguityError)sym).ambiguousSyms;
} else {
return List.of(sym);
}
}
AmbiguityError addAmbiguousSymbol(Symbol s) {
ambiguousSyms = ambiguousSyms.prepend(s);
return this;
}
@Override
@ -3356,24 +3328,60 @@ public class Resolve {
Name name,
List<Type> argtypes,
List<Type> typeargtypes) {
AmbiguityError pair = this;
while (true) {
if (pair.sym.kind == AMBIGUOUS)
pair = (AmbiguityError)pair.sym;
else if (pair.sym2.kind == AMBIGUOUS)
pair = (AmbiguityError)pair.sym2;
else break;
}
Name sname = pair.sym.name;
if (sname == names.init) sname = pair.sym.owner.name;
List<Symbol> diagSyms = ambiguousSyms.reverse();
Symbol s1 = diagSyms.head;
Symbol s2 = diagSyms.tail.head;
Name sname = s1.name;
if (sname == names.init) sname = s1.owner.name;
return diags.create(dkind, log.currentSource(),
pos, "ref.ambiguous", sname,
kindName(pair.sym),
pair.sym,
pair.sym.location(site, types),
kindName(pair.sym2),
pair.sym2,
pair.sym2.location(site, types));
kindName(s1),
s1,
s1.location(site, types),
kindName(s2),
s2,
s2.location(site, types));
}
/**
* If multiple applicable methods are found during overload and none of them
* is more specific than the others, attempt to merge their signatures.
*/
Symbol mergeAbstracts(Type site) {
Symbol fst = ambiguousSyms.last();
Symbol res = fst;
for (Symbol s : ambiguousSyms.reverse()) {
Type mt1 = types.memberType(site, res);
Type mt2 = types.memberType(site, s);
if ((s.flags() & ABSTRACT) == 0 ||
!types.overrideEquivalent(mt1, mt2) ||
!types.isSameTypes(fst.erasure(types).getParameterTypes(),
s.erasure(types).getParameterTypes())) {
//ambiguity cannot be resolved
return this;
} else {
Type mst = mostSpecificReturnType(mt1, mt2);
if (mst == null) {
// Theoretically, this can't happen, but it is possible
// due to error recovery or mixing incompatible class files
return this;
}
Symbol mostSpecific = mst == mt1 ? res : s;
List<Type> allThrown = chk.intersect(mt1.getThrownTypes(), mt2.getThrownTypes());
Type newSig = types.createMethodTypeWithThrown(mostSpecific.type, allThrown);
res = new MethodSymbol(
mostSpecific.flags(),
mostSpecific.name,
newSig,
mostSpecific.owner);
}
}
return res;
}
@Override
protected Symbol access(Name name, TypeSymbol location) {
return ambiguousSyms.last();
}
}
@ -3450,6 +3458,10 @@ public class Resolve {
candidates = candidates.append(c);
}
DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
}
/**
* This class represents an overload resolution candidate. There are two
* kinds of candidates: applicable methods and inapplicable methods;

@ -217,6 +217,13 @@ public class ClassReader implements Completer {
*/
boolean haveParameterNameIndices;
/** Set this to false every time we start reading a method
* and are saving parameter names. Set it to true when we see
* MethodParameters, if it's set when we see a LocalVariableTable,
* then we ignore the parameter names from the LVT.
*/
boolean sawMethodParameters;
/**
* The set of attribute names for which warnings have been generated for the current class
*/
@ -984,7 +991,7 @@ public class ClassReader implements Completer {
new AttributeReader(names.LocalVariableTable, V45_3, CLASS_OR_MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
int newbp = bp + attrLen;
if (saveParameterNames) {
if (saveParameterNames && !sawMethodParameters) {
// Pick up parameter names from the variable table.
// Parameter names are not explicitly identified as such,
// but all parameter name entries in the LocalVariableTable
@ -1017,6 +1024,25 @@ public class ClassReader implements Completer {
}
},
new AttributeReader(names.MethodParameters, V52, MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrlen) {
int newbp = bp + attrlen;
if (saveParameterNames) {
sawMethodParameters = true;
int numEntries = nextByte();
parameterNameIndices = new int[numEntries];
haveParameterNameIndices = true;
for (int i = 0; i < numEntries; i++) {
int nameIndex = nextChar();
int flags = nextInt();
parameterNameIndices[i] = nameIndex;
}
}
bp = newbp;
}
},
new AttributeReader(names.SourceFile, V45_3, CLASS_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
ClassSymbol c = (ClassSymbol) sym;
@ -1826,6 +1852,7 @@ public class ClassReader implements Completer {
} else
Arrays.fill(parameterNameIndices, 0);
haveParameterNameIndices = false;
sawMethodParameters = false;
}
/**
@ -1845,12 +1872,16 @@ public class ClassReader implements Completer {
// if no names were found in the class file, there's nothing more to do
if (!haveParameterNameIndices)
return;
int firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
// the code in readMethod may have skipped the first parameter when
// setting up the MethodType. If so, we make a corresponding allowance
// here for the position of the first parameter. Note that this
// assumes the skipped parameter has a width of 1 -- i.e. it is not
// If we get parameter names from MethodParameters, then we
// don't need to skip.
int firstParam = 0;
if (!sawMethodParameters) {
firstParam = ((sym.flags() & STATIC) == 0) ? 1 : 0;
// the code in readMethod may have skipped the first
// parameter when setting up the MethodType. If so, we
// make a corresponding allowance here for the position of
// the first parameter. Note that this assumes the
// skipped parameter has a width of 1 -- i.e. it is not
// a double width type (long or double.)
if (sym.name == names.init && currentOwner.hasOuterInstance()) {
// Sometimes anonymous classes don't have an outer
@ -1861,17 +1892,20 @@ public class ClassReader implements Completer {
}
if (sym.type != jvmType) {
// reading the method attributes has caused the symbol's type to
// be changed. (i.e. the Signature attribute.) This may happen if
// there are hidden (synthetic) parameters in the descriptor, but
// not in the Signature. The position of these hidden parameters
// is unspecified; for now, assume they are at the beginning, and
// so skip over them. The primary case for this is two hidden
// parameters passed into Enum constructors.
// reading the method attributes has caused the
// symbol's type to be changed. (i.e. the Signature
// attribute.) This may happen if there are hidden
// (synthetic) parameters in the descriptor, but not
// in the Signature. The position of these hidden
// parameters is unspecified; for now, assume they are
// at the beginning, and so skip over them. The
// primary case for this is two hidden parameters
// passed into Enum constructors.
int skip = Code.width(jvmType.getParameterTypes())
- Code.width(sym.type.getParameterTypes());
firstParam += skip;
}
}
List<Name> paramNames = List.nil();
int index = firstParam;
for (Type t: sym.type.getParameterTypes()) {

@ -725,6 +725,28 @@ public class ClassWriter extends ClassFile {
return acount;
}
/**
* Write method parameter names attribute.
*/
int writeMethodParametersAttr(MethodSymbol m) {
if (m.params != null && 0 != m.params.length()) {
int attrIndex = writeAttr(names.MethodParameters);
databuf.appendByte(m.params.length());
for (VarSymbol s : m.params) {
// TODO: expand to cover synthesized, once we figure out
// how to represent that.
final int flags = (int) s.flags() & (FINAL | SYNTHETIC);
// output parameter info
databuf.appendChar(pool.put(s.name));
databuf.appendInt(flags);
}
endAttr(attrIndex);
return 1;
} else
return 0;
}
/** Write method parameter annotations;
* return number of attributes written.
*/
@ -1034,6 +1056,8 @@ public class ClassWriter extends ClassFile {
endAttr(alenIdx);
acount++;
}
if (options.isSet(PARAMETERS))
acount += writeMethodParametersAttr(m);
acount += writeMemberAttrs(m);
acount += writeParameterAttrs(m);
endAttrs(acountIdx, acount);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2013, 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
@ -176,6 +176,8 @@ public enum Option {
PROCESSORPATH("-processorpath", "opt.arg.path", "opt.processorpath", STANDARD, FILEMANAGER),
PARAMETERS("-parameters","opt.parameters", STANDARD, BASIC),
D("-d", "opt.arg.directory", "opt.d", STANDARD, FILEMANAGER),
S("-s", "opt.arg.directory", "opt.sourceDest", STANDARD, FILEMANAGER),
@ -309,7 +311,7 @@ public enum Option {
// This option exists only for the purpose of documenting itself.
// It's actually implemented by the launcher.
J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO) {
J("-J", "opt.arg.flag", "opt.J", STANDARD, INFO, true) {
@Override
public boolean process(OptionHelper helper, String option) {
throw new AssertionError
@ -414,7 +416,7 @@ public enum Option {
// This option exists only for the purpose of documenting itself.
// It's actually implemented by the CommandLine class.
AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO) {
AT("@", "opt.arg.file", "opt.AT", STANDARD, INFO, true) {
@Override
public boolean process(OptionHelper helper, String option) {
throw new AssertionError("the @ flag should be caught by CommandLine.");

@ -55,6 +55,8 @@ javac.opt.processorpath=\
Specify where to find annotation processors
javac.opt.processor=\
Names of the annotation processors to run; bypasses default discovery process
javac.opt.parameters=\
Generate metadata for reflection on method parameters
javac.opt.proc.none.only=\
Control whether annotation processing and/or compilation is done.
javac.opt.d=\

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -154,12 +154,13 @@ public class Pretty extends JCTree.Visitor {
}
//we need to (i) replace all line terminators with a space and (ii) remove
//occurrences of 'missing' in the Pretty output (generated when types are missing)
String res = s.toString().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
String res = s.toString().trim().replaceAll("\\s+", " ").replaceAll("/\\*missing\\*/", "");
if (res.length() < maxLength) {
return res;
} else {
int split = (maxLength - trimSequence.length()) * 2 / 3;
return res.substring(0, split) + trimSequence + res.substring(split);
int head = (maxLength - trimSequence.length()) * 2 / 3;
int tail = maxLength - trimSequence.length() - head;
return res.substring(0, head) + trimSequence + res.substring(res.length() - tail);
}
}

@ -132,6 +132,7 @@ public class Names {
public final Name LineNumberTable;
public final Name LocalVariableTable;
public final Name LocalVariableTypeTable;
public final Name MethodParameters;
public final Name RuntimeInvisibleAnnotations;
public final Name RuntimeInvisibleParameterAnnotations;
public final Name RuntimeInvisibleTypeAnnotations;
@ -265,6 +266,7 @@ public class Names {
LineNumberTable = fromString("LineNumberTable");
LocalVariableTable = fromString("LocalVariableTable");
LocalVariableTypeTable = fromString("LocalVariableTypeTable");
MethodParameters = fromString("MethodParameters");
RuntimeInvisibleAnnotations = fromString("RuntimeInvisibleAnnotations");
RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations");
RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations");

@ -88,6 +88,15 @@ public class AnnotationDescImpl implements AnnotationDesc {
return res;
}
/**
* Check for the synthesized bit on the annotation.
*
* @return true if the annotation is synthesized.
*/
public boolean isSynthesized() {
return annotation.isSynthesized();
}
/**
* Returns a string representation of this annotation.
* String is of one of the forms:

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -133,16 +133,6 @@ public class Messager extends Log implements DocErrorReporter {
this.programName = programName;
}
@Override
protected int getDefaultMaxErrors() {
return Integer.MAX_VALUE;
}
@Override
protected int getDefaultMaxWarnings() {
return Integer.MAX_VALUE;
}
public void setLocale(Locale locale) {
this.locale = locale;
}

@ -86,16 +86,7 @@ public class MethodDocImpl
* Return true if this method is abstract
*/
public boolean isAbstract() {
//### This is dubious, but old 'javadoc' apparently does it.
//### I regard this as a bug and an obstacle to treating the
//### doclet API as a proper compile-time reflection facility.
//### (maddox 09/26/2000)
if (containingClass().isInterface()) {
//### Don't force creation of ClassDocImpl for super here.
// Abstract modifier is implicit. Strip/canonicalize it.
return false;
}
return Modifier.isAbstract(getModifiers());
return (Modifier.isAbstract(getModifiers()) && !isDefault());
}
/**

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2012, 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
@ -46,6 +46,7 @@ import com.sun.tools.classfile.InnerClasses_attribute;
import com.sun.tools.classfile.LineNumberTable_attribute;
import com.sun.tools.classfile.LocalVariableTable_attribute;
import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
import com.sun.tools.classfile.MethodParameters_attribute;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
@ -386,6 +387,28 @@ public class AttributeWriter extends BasicWriter
return null;
}
private static final String format = "%-31s%s";
public Void visitMethodParameters(MethodParameters_attribute attr,
Void ignore) {
final String header = String.format(format, "Name", "Flags");
println("MethodParameters:");
indent(+1);
println(header);
for (MethodParameters_attribute.Entry entry :
attr.method_parameter_table) {
String flagstr =
(0 != (entry.flags & ACC_FINAL) ? " final" : "") +
(0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : "");
println(String.format(format,
constantWriter.stringValue(entry.name_index),
flagstr));
}
indent(-1);
return null;
}
public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) {
println("RuntimeVisibleAnnotations:");
indent(+1);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, 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
@ -206,7 +206,7 @@ public class ClassWriter extends BasicWriter {
println("minor version: " + cf.minor_version);
println("major version: " + cf.major_version);
if (!options.compat)
writeList("flags: ", flags.getClassFlags(), NEWLINE);
writeList("flags: ", flags.getClassFlags(), "\n");
indent(-1);
constantWriter.writeConstantPool();
} else {
@ -383,7 +383,7 @@ public class ClassWriter extends BasicWriter {
println("Signature: " + getValue(f.descriptor));
if (options.verbose && !options.compat)
writeList("flags: ", flags.getFieldFlags(), NEWLINE);
writeList("flags: ", flags.getFieldFlags(), "\n");
if (options.showAllAttrs) {
for (Attribute attr: f.attributes)
@ -480,7 +480,7 @@ public class ClassWriter extends BasicWriter {
}
if (options.verbose && !options.compat) {
writeList("flags: ", flags.getMethodFlags(), NEWLINE);
writeList("flags: ", flags.getMethodFlags(), "\n");
}
Code_attribute code = null;
@ -749,5 +749,4 @@ public class ClassWriter extends BasicWriter {
private int size;
private ConstantPool constant_pool;
private Method method;
private static final String NEWLINE = System.getProperty("line.separator", "\n");
}

@ -0,0 +1,173 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jdeps;
import com.sun.tools.classfile.Dependency;
import com.sun.tools.classfile.Dependency.Location;
import java.io.File;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* Represents the source of the class files.
*/
public class Archive {
private static Map<String,Archive> archiveForClass = new HashMap<String,Archive>();
public static Archive find(Location loc) {
return archiveForClass.get(loc.getName());
}
private final File file;
private final String filename;
private final DependencyRecorder recorder;
private final ClassFileReader reader;
public Archive(String name) {
this.file = null;
this.filename = name;
this.recorder = new DependencyRecorder();
this.reader = null;
}
public Archive(File f, ClassFileReader reader) {
this.file = f;
this.filename = f.getName();
this.recorder = new DependencyRecorder();
this.reader = reader;
}
public ClassFileReader reader() {
return reader;
}
public String getFileName() {
return filename;
}
public void addClass(String classFileName) {
Archive a = archiveForClass.get(classFileName);
assert(a == null || a == this); // ## issue warning?
if (!archiveForClass.containsKey(classFileName)) {
archiveForClass.put(classFileName, this);
}
}
public void addDependency(Dependency d) {
recorder.addDependency(d);
}
/**
* Returns a sorted map of a class to its dependencies.
*/
public SortedMap<Location, SortedSet<Location>> getDependencies() {
DependencyRecorder.Filter filter = new DependencyRecorder.Filter() {
public boolean accept(Location origin, Location target) {
return (archiveForClass.get(origin.getName()) !=
archiveForClass.get(target.getName()));
}};
SortedMap<Location, SortedSet<Location>> result =
new TreeMap<Location, SortedSet<Location>>(locationComparator);
for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) {
Location o = e.getKey();
for (Location t : e.getValue()) {
if (filter.accept(o, t)) {
SortedSet<Location> odeps = result.get(o);
if (odeps == null) {
odeps = new TreeSet<Location>(locationComparator);
result.put(o, odeps);
}
odeps.add(t);
}
}
}
return result;
}
/**
* Returns the set of archives this archive requires.
*/
public Set<Archive> getRequiredArchives() {
SortedSet<Archive> deps = new TreeSet<Archive>(new Comparator<Archive>() {
public int compare(Archive a1, Archive a2) {
return a1.toString().compareTo(a2.toString());
}
});
for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) {
Location o = e.getKey();
Archive origin = Archive.find(o);
for (Location t : e.getValue()) {
Archive target = Archive.find(t);
assert(origin != null && target != null);
if (origin != target) {
if (!deps.contains(target)) {
deps.add(target);
}
}
}
}
return deps;
}
public String toString() {
return file != null ? file.getPath() : filename;
}
private static class DependencyRecorder {
static interface Filter {
boolean accept(Location origin, Location target);
}
public void addDependency(Dependency d) {
Set<Location> odeps = map.get(d.getOrigin());
if (odeps == null) {
odeps = new HashSet<Location>();
map.put(d.getOrigin(), odeps);
}
odeps.add(d.getTarget());
}
public Map<Location, Set<Location>> dependencies() {
return map;
}
private final Map<Location, Set<Location>> map =
new HashMap<Location, Set<Location>>();
}
private static Comparator<Location> locationComparator =
new Comparator<Location>() {
public int compare(Location o1, Location o2) {
return o1.toString().compareTo(o2.toString());
}
};
}

@ -0,0 +1,326 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jdeps;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Dependencies.ClassFileError;
import java.io.*;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* ClassFileReader reads ClassFile(s) of a given path that can be
* a .class file, a directory, or a JAR file.
*/
public class ClassFileReader {
/**
* Returns a ClassFileReader instance of a given path.
*/
public static ClassFileReader newInstance(File path) throws IOException {
if (!path.exists()) {
throw new FileNotFoundException(path.getAbsolutePath());
}
if (path.isDirectory()) {
return new DirectoryReader(path.toPath());
} else if (path.getName().endsWith(".jar")) {
return new JarFileReader(path.toPath());
} else {
return new ClassFileReader(path.toPath());
}
}
protected final Path path;
protected final String baseFileName;
private ClassFileReader(Path path) {
this.path = path;
this.baseFileName = path.getFileName() != null
? path.getFileName().toString()
: path.toString();
}
public String getFileName() {
return baseFileName;
}
/**
* Returns the ClassFile matching the given binary name
* or a fully-qualified class name.
*/
public ClassFile getClassFile(String name) throws IOException {
if (name.indexOf('.') > 0) {
int i = name.lastIndexOf('.');
String pathname = name.replace('.', File.separatorChar) + ".class";
if (baseFileName.equals(pathname) ||
baseFileName.equals(pathname.substring(0, i) + "$" +
pathname.substring(i+1, pathname.length()))) {
return readClassFile(path);
}
} else {
if (baseFileName.equals(name.replace('/', File.separatorChar) + ".class")) {
return readClassFile(path);
}
}
return null;
}
public Iterable<ClassFile> getClassFiles() throws IOException {
return new Iterable<ClassFile>() {
public Iterator<ClassFile> iterator() {
return new FileIterator();
}
};
}
protected ClassFile readClassFile(Path p) throws IOException {
InputStream is = null;
try {
is = Files.newInputStream(p);
return ClassFile.read(is);
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
} finally {
if (is != null) {
is.close();
}
}
}
class FileIterator implements Iterator<ClassFile> {
int count;
FileIterator() {
this.count = 0;
}
public boolean hasNext() {
return count == 0 && baseFileName.endsWith(".class");
}
public ClassFile next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
ClassFile cf = readClassFile(path);
count++;
return cf;
} catch (IOException e) {
throw new ClassFileError(e);
}
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
public String toString() {
return path.toString();
}
private static class DirectoryReader extends ClassFileReader {
DirectoryReader(Path path) throws IOException {
super(path);
}
public ClassFile getClassFile(String name) throws IOException {
if (name.indexOf('.') > 0) {
int i = name.lastIndexOf('.');
String pathname = name.replace('.', File.separatorChar) + ".class";
Path p = path.resolve(pathname);
if (!p.toFile().exists()) {
p = path.resolve(pathname.substring(0, i) + "$" +
pathname.substring(i+1, pathname.length()));
}
if (p.toFile().exists()) {
return readClassFile(p);
}
} else {
Path p = path.resolve(name + ".class");
if (p.toFile().exists()) {
return readClassFile(p);
}
}
return null;
}
public Iterable<ClassFile> getClassFiles() throws IOException {
final Iterator<ClassFile> iter = new DirectoryIterator();
return new Iterable<ClassFile>() {
public Iterator<ClassFile> iterator() {
return iter;
}
};
}
private List<Path> walkTree(Path dir) throws IOException {
final List<Path> files = new ArrayList<Path>();
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException {
if (file.toFile().getName().endsWith(".class")) {
files.add(file);
}
return FileVisitResult.CONTINUE;
}
});
return files;
}
class DirectoryIterator implements Iterator<ClassFile> {
private List<Path> entries;
private int index = 0;
DirectoryIterator() throws IOException {
entries = walkTree(path);
index = 0;
}
public boolean hasNext() {
return index != entries.size();
}
public ClassFile next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Path path = entries.get(index++);
try {
return readClassFile(path);
} catch (IOException e) {
throw new ClassFileError(e);
}
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
private static class JarFileReader extends ClassFileReader {
final JarFile jarfile;
JarFileReader(Path path) throws IOException {
super(path);
this.jarfile = new JarFile(path.toFile());
}
public ClassFile getClassFile(String name) throws IOException {
if (name.indexOf('.') > 0) {
int i = name.lastIndexOf('.');
String entryName = name.replace('.', '/') + ".class";
JarEntry e = jarfile.getJarEntry(entryName);
if (e == null) {
e = jarfile.getJarEntry(entryName.substring(0, i) + "$"
+ entryName.substring(i + 1, entryName.length()));
}
if (e != null) {
return readClassFile(e);
}
} else {
JarEntry e = jarfile.getJarEntry(name + ".class");
if (e != null) {
return readClassFile(e);
}
}
return null;
}
private ClassFile readClassFile(JarEntry e) throws IOException {
InputStream is = null;
try {
is = jarfile.getInputStream(e);
return ClassFile.read(is);
} catch (ConstantPoolException ex) {
throw new ClassFileError(ex);
} finally {
if (is != null)
is.close();
}
}
public Iterable<ClassFile> getClassFiles() throws IOException {
final Iterator<ClassFile> iter = new JarFileIterator();
return new Iterable<ClassFile>() {
public Iterator<ClassFile> iterator() {
return iter;
}
};
}
class JarFileIterator implements Iterator<ClassFile> {
private Enumeration<JarEntry> entries;
private JarEntry nextEntry;
JarFileIterator() {
this.entries = jarfile.entries();
while (entries.hasMoreElements()) {
JarEntry e = entries.nextElement();
String name = e.getName();
if (name.endsWith(".class")) {
this.nextEntry = e;
break;
}
}
}
public boolean hasNext() {
return nextEntry != null;
}
public ClassFile next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
ClassFile cf;
try {
cf = readClassFile(nextEntry);
} catch (IOException ex) {
throw new ClassFileError(ex);
}
JarEntry entry = nextEntry;
nextEntry = null;
while (entries.hasMoreElements()) {
JarEntry e = entries.nextElement();
String name = e.getName();
if (name.endsWith(".class")) {
nextEntry = e;
break;
}
}
return cf;
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
}

@ -0,0 +1,650 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jdeps;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Dependencies;
import com.sun.tools.classfile.Dependencies.ClassFileError;
import com.sun.tools.classfile.Dependency;
import com.sun.tools.classfile.Dependency.Location;
import java.io.*;
import java.text.MessageFormat;
import java.util.*;
import java.util.regex.Pattern;
/**
* Implementation for the jdeps tool for static class dependency analysis.
*/
class JdepsTask {
class BadArgs extends Exception {
static final long serialVersionUID = 8765093759964640721L;
BadArgs(String key, Object... args) {
super(JdepsTask.this.getMessage(key, args));
this.key = key;
this.args = args;
}
BadArgs showUsage(boolean b) {
showUsage = b;
return this;
}
final String key;
final Object[] args;
boolean showUsage;
}
static abstract class Option {
Option(boolean hasArg, String... aliases) {
this.hasArg = hasArg;
this.aliases = aliases;
}
boolean isHidden() {
return false;
}
boolean matches(String opt) {
for (String a : aliases) {
if (a.equals(opt)) {
return true;
} else if (opt.startsWith("--") && hasArg && opt.startsWith(a + "=")) {
return true;
}
}
return false;
}
boolean ignoreRest() {
return false;
}
abstract void process(JdepsTask task, String opt, String arg) throws BadArgs;
final boolean hasArg;
final String[] aliases;
}
static abstract class HiddenOption extends Option {
HiddenOption(boolean hasArg, String... aliases) {
super(hasArg, aliases);
}
boolean isHidden() {
return true;
}
}
static Option[] recognizedOptions = {
new Option(false, "-h", "-?", "--help") {
void process(JdepsTask task, String opt, String arg) {
task.options.help = true;
}
},
new Option(false, "-s", "--summary") {
void process(JdepsTask task, String opt, String arg) {
task.options.showSummary = true;
task.options.verbose = Options.Verbose.SUMMARY;
}
},
new Option(false, "-v", "--verbose") {
void process(JdepsTask task, String opt, String arg) {
task.options.verbose = Options.Verbose.VERBOSE;
}
},
new Option(true, "-V", "--verbose-level") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
switch (arg) {
case "package":
task.options.verbose = Options.Verbose.PACKAGE;
break;
case "class":
task.options.verbose = Options.Verbose.CLASS;
break;
default:
throw task.new BadArgs("err.invalid.arg.for.option", opt);
}
}
},
new Option(true, "-c", "--classpath") {
void process(JdepsTask task, String opt, String arg) {
task.options.classpath = arg;
}
},
new Option(true, "-p", "--package") {
void process(JdepsTask task, String opt, String arg) {
task.options.packageNames.add(arg);
}
},
new Option(true, "-e", "--regex") {
void process(JdepsTask task, String opt, String arg) {
task.options.regex = arg;
}
},
new Option(false, "-P", "--profile") {
void process(JdepsTask task, String opt, String arg) {
task.options.showProfile = true;
}
},
new Option(false, "-R", "--recursive") {
void process(JdepsTask task, String opt, String arg) {
task.options.depth = 0;
}
},
new HiddenOption(true, "-d", "--depth") {
void process(JdepsTask task, String opt, String arg) throws BadArgs {
try {
task.options.depth = Integer.parseInt(arg);
} catch (NumberFormatException e) {
throw task.new BadArgs("err.invalid.arg.for.option", opt);
}
}
},
new Option(false, "--version") {
void process(JdepsTask task, String opt, String arg) {
task.options.version = true;
}
},
new HiddenOption(false, "--fullversion") {
void process(JdepsTask task, String opt, String arg) {
task.options.fullVersion = true;
}
},
};
private static final String PROGNAME = "jdeps";
private final Options options = new Options();
private final List<String> classes = new ArrayList<String>();
private PrintWriter log;
void setLog(PrintWriter out) {
log = out;
}
/**
* Result codes.
*/
static final int EXIT_OK = 0, // Completed with no errors.
EXIT_ERROR = 1, // Completed but reported errors.
EXIT_CMDERR = 2, // Bad command-line arguments
EXIT_SYSERR = 3, // System error or resource exhaustion.
EXIT_ABNORMAL = 4;// terminated abnormally
int run(String[] args) {
if (log == null) {
log = new PrintWriter(System.out);
}
try {
handleOptions(args);
if (options.help) {
showHelp();
}
if (options.version || options.fullVersion) {
showVersion(options.fullVersion);
}
if (classes.isEmpty() && !options.wildcard) {
if (options.help || options.version || options.fullVersion) {
return EXIT_OK;
} else {
showHelp();
return EXIT_CMDERR;
}
}
if (options.regex != null && options.packageNames.size() > 0) {
showHelp();
return EXIT_CMDERR;
}
if (options.showSummary && options.verbose != Options.Verbose.SUMMARY) {
showHelp();
return EXIT_CMDERR;
}
boolean ok = run();
return ok ? EXIT_OK : EXIT_ERROR;
} catch (BadArgs e) {
reportError(e.key, e.args);
if (e.showUsage) {
log.println(getMessage("main.usage.summary", PROGNAME));
}
return EXIT_CMDERR;
} catch (IOException e) {
return EXIT_ABNORMAL;
} finally {
log.flush();
}
}
private final List<Archive> sourceLocations = new ArrayList<Archive>();
private final Archive NOT_FOUND = new Archive(getMessage("artifact.not.found"));
private boolean run() throws IOException {
findDependencies();
switch (options.verbose) {
case VERBOSE:
case CLASS:
printClassDeps(log);
break;
case PACKAGE:
printPackageDeps(log);
break;
case SUMMARY:
for (Archive origin : sourceLocations) {
for (Archive target : origin.getRequiredArchives()) {
log.format("%-30s -> %s%n", origin, target);
}
}
break;
default:
throw new InternalError("Should not reach here");
}
return true;
}
private boolean isValidClassName(String name) {
if (!Character.isJavaIdentifierStart(name.charAt(0))) {
return false;
}
for (int i=1; i < name.length(); i++) {
char c = name.charAt(i);
if (c != '.' && !Character.isJavaIdentifierPart(c)) {
return false;
}
}
return true;
}
private void findDependencies() throws IOException {
Dependency.Finder finder = Dependencies.getClassDependencyFinder();
Dependency.Filter filter;
if (options.regex != null) {
filter = Dependencies.getRegexFilter(Pattern.compile(options.regex));
} else if (options.packageNames.size() > 0) {
filter = Dependencies.getPackageFilter(options.packageNames, false);
} else {
filter = new Dependency.Filter() {
public boolean accepts(Dependency dependency) {
return !dependency.getOrigin().equals(dependency.getTarget());
}
};
}
List<Archive> archives = new ArrayList<Archive>();
Deque<String> roots = new LinkedList<String>();
for (String s : classes) {
File f = new File(s);
if (f.exists()) {
archives.add(new Archive(f, ClassFileReader.newInstance(f)));
} else {
if (isValidClassName(s)) {
roots.add(s);
} else {
warning("warn.invalid.arg", s);
}
}
}
List<Archive> classpaths = new ArrayList<Archive>(); // for class file lookup
if (options.wildcard) {
// include all archives from classpath to the initial list
archives.addAll(getClassPathArchives(options.classpath));
} else {
classpaths.addAll(getClassPathArchives(options.classpath));
}
classpaths.addAll(PlatformClassPath.getArchives());
// add all archives to the source locations for reporting
sourceLocations.addAll(archives);
sourceLocations.addAll(classpaths);
// Work queue of names of classfiles to be searched.
// Entries will be unique, and for classes that do not yet have
// dependencies in the results map.
Deque<String> deque = new LinkedList<String>();
Set<String> doneClasses = new HashSet<String>();
// get the immediate dependencies of the input files
for (Archive a : archives) {
for (ClassFile cf : a.reader().getClassFiles()) {
String classFileName;
try {
classFileName = cf.getName();
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
a.addClass(classFileName);
if (!doneClasses.contains(classFileName)) {
doneClasses.add(classFileName);
}
for (Dependency d : finder.findDependencies(cf)) {
if (filter.accepts(d)) {
String cn = d.getTarget().getName();
if (!doneClasses.contains(cn) && !deque.contains(cn)) {
deque.add(cn);
}
a.addDependency(d);
}
}
}
}
// add Archive for looking up classes from the classpath
// for transitive dependency analysis
Deque<String> unresolved = roots;
int depth = options.depth > 0 ? options.depth : Integer.MAX_VALUE;
do {
String name;
while ((name = unresolved.poll()) != null) {
if (doneClasses.contains(name)) {
continue;
}
ClassFile cf = null;
for (Archive a : classpaths) {
cf = a.reader().getClassFile(name);
if (cf != null) {
String classFileName;
try {
classFileName = cf.getName();
} catch (ConstantPoolException e) {
throw new ClassFileError(e);
}
a.addClass(classFileName);
if (!doneClasses.contains(classFileName)) {
// if name is a fully-qualified class name specified
// from command-line, this class might already be parsed
doneClasses.add(classFileName);
if (depth > 0) {
for (Dependency d : finder.findDependencies(cf)) {
if (filter.accepts(d)) {
String cn = d.getTarget().getName();
if (!doneClasses.contains(cn) && !deque.contains(cn)) {
deque.add(cn);
}
a.addDependency(d);
}
}
}
}
break;
}
}
if (cf == null) {
NOT_FOUND.addClass(name);
}
}
unresolved = deque;
deque = new LinkedList<String>();
} while (!unresolved.isEmpty() && depth-- > 0);
}
private void printPackageDeps(PrintWriter out) {
for (Archive source : sourceLocations) {
SortedMap<Location, SortedSet<Location>> deps = source.getDependencies();
if (deps.isEmpty())
continue;
for (Archive target : source.getRequiredArchives()) {
out.format("%s -> %s%n", source, target);
}
Map<String, Archive> pkgs = new TreeMap<String, Archive>();
SortedMap<String, Archive> targets = new TreeMap<String, Archive>();
String pkg = "";
for (Map.Entry<Location, SortedSet<Location>> e : deps.entrySet()) {
String cn = e.getKey().getClassName();
String p = packageOf(e.getKey());
Archive origin = Archive.find(e.getKey());
assert origin != null;
if (!pkgs.containsKey(p)) {
pkgs.put(p, origin);
} else if (pkgs.get(p) != origin) {
warning("warn.split.package", p, origin, pkgs.get(p));
}
if (!p.equals(pkg)) {
printTargets(out, targets);
pkg = p;
targets.clear();
out.format(" %s (%s)%n", p, origin.getFileName());
}
for (Location t : e.getValue()) {
p = packageOf(t);
Archive target = Archive.find(t);
if (!targets.containsKey(p)) {
targets.put(p, target);
}
}
}
printTargets(out, targets);
out.println();
}
}
private void printTargets(PrintWriter out, Map<String, Archive> targets) {
for (Map.Entry<String, Archive> t : targets.entrySet()) {
String pn = t.getKey();
out.format(" -> %-40s %s%n", pn, getPackageInfo(pn, t.getValue()));
}
}
private String getPackageInfo(String pn, Archive source) {
if (PlatformClassPath.contains(source)) {
String name = PlatformClassPath.getProfileName(pn);
if (name.isEmpty()) {
return "JDK internal API (" + source.getFileName() + ")";
}
return options.showProfile ? name : "";
}
return source.getFileName();
}
private static String packageOf(Location loc) {
String pkg = loc.getPackageName();
return pkg.isEmpty() ? "<unnamed>" : pkg;
}
private void printClassDeps(PrintWriter out) {
for (Archive source : sourceLocations) {
SortedMap<Location, SortedSet<Location>> deps = source.getDependencies();
if (deps.isEmpty())
continue;
for (Archive target : source.getRequiredArchives()) {
out.format("%s -> %s%n", source, target);
}
out.format("%s%n", source);
for (Map.Entry<Location, SortedSet<Location>> e : deps.entrySet()) {
String cn = e.getKey().getClassName();
Archive origin = Archive.find(e.getKey());
out.format(" %s (%s)%n", cn, origin.getFileName());
for (Location t : e.getValue()) {
cn = t.getClassName();
Archive target = Archive.find(t);
out.format(" -> %-60s %s%n", cn, getPackageInfo(t.getPackageName(), target));
}
}
out.println();
}
}
public void handleOptions(String[] args) throws BadArgs {
// process options
for (int i=0; i < args.length; i++) {
if (args[i].charAt(0) == '-') {
String name = args[i];
Option option = getOption(name);
String param = null;
if (option.hasArg) {
if (name.startsWith("--") && name.indexOf('=') > 0) {
param = name.substring(name.indexOf('=') + 1, name.length());
} else if (i + 1 < args.length) {
param = args[++i];
}
if (param == null || param.isEmpty() || param.charAt(0) == '-') {
throw new BadArgs("err.missing.arg", name).showUsage(true);
}
}
option.process(this, name, param);
if (option.ignoreRest()) {
i = args.length;
}
} else {
// process rest of the input arguments
for (; i < args.length; i++) {
String name = args[i];
if (name.charAt(0) == '-') {
throw new BadArgs("err.option.after.class", name).showUsage(true);
}
if (name.equals("*") || name.equals("\"*\"")) {
options.wildcard = true;
} else {
classes.add(name);
}
}
}
}
}
private Option getOption(String name) throws BadArgs {
for (Option o : recognizedOptions) {
if (o.matches(name)) {
return o;
}
}
throw new BadArgs("err.unknown.option", name).showUsage(true);
}
private void reportError(String key, Object... args) {
log.println(getMessage("error.prefix") + " " + getMessage(key, args));
}
private void warning(String key, Object... args) {
log.println(getMessage("warn.prefix") + " " + getMessage(key, args));
}
private void showHelp() {
log.println(getMessage("main.usage", PROGNAME));
for (Option o : recognizedOptions) {
String name = o.aliases[0].substring(1); // there must always be at least one name
name = name.charAt(0) == '-' ? name.substring(1) : name;
if (o.isHidden() || name.equals("h")) {
continue;
}
log.println(getMessage("main.opt." + name));
}
}
private void showVersion(boolean full) {
log.println(version(full ? "full" : "release"));
}
private String version(String key) {
// key=version: mm.nn.oo[-milestone]
// key=full: mm.mm.oo[-milestone]-build
if (ResourceBundleHelper.versionRB == null) {
return System.getProperty("java.version");
}
try {
return ResourceBundleHelper.versionRB.getString(key);
} catch (MissingResourceException e) {
return getMessage("version.unknown", System.getProperty("java.version"));
}
}
public String getMessage(String key, Object... args) {
try {
return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
} catch (MissingResourceException e) {
throw new InternalError("Missing message: " + key);
}
}
private static class Options {
enum Verbose {
CLASS,
PACKAGE,
SUMMARY,
VERBOSE
};
boolean help;
boolean version;
boolean fullVersion;
boolean showFlags;
boolean showProfile;
boolean showSummary;
boolean wildcard;
String regex;
String classpath = "";
int depth = 1;
Verbose verbose = Verbose.PACKAGE;
Set<String> packageNames = new HashSet<String>();
}
private static class ResourceBundleHelper {
static final ResourceBundle versionRB;
static final ResourceBundle bundle;
static {
Locale locale = Locale.getDefault();
try {
bundle = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdeps", locale);
} catch (MissingResourceException e) {
throw new InternalError("Cannot find jdeps resource bundle for locale " + locale);
}
try {
versionRB = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.version");
} catch (MissingResourceException e) {
throw new InternalError("version.resource.missing");
}
}
}
private List<Archive> getArchives(List<String> filenames) throws IOException {
List<Archive> result = new ArrayList<Archive>();
for (String s : filenames) {
File f = new File(s);
if (f.exists()) {
result.add(new Archive(f, ClassFileReader.newInstance(f)));
} else {
warning("warn.file.not.exist", s);
}
}
return result;
}
private List<Archive> getClassPathArchives(String paths) throws IOException {
List<Archive> result = new ArrayList<Archive>();
if (paths.isEmpty()) {
return result;
}
for (String p : paths.split(File.pathSeparator)) {
if (p.length() > 0) {
File f = new File(p);
if (f.exists()) {
result.add(new Archive(f, ClassFileReader.newInstance(f)));
}
}
}
return result;
}
}

@ -0,0 +1,66 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jdeps;
import java.io.*;
/**
*
* Usage:
* jdeps [options] files ...
* where options include:
* -p package-name restrict analysis to classes in this package
* (may be given multiple times)
* -e regex restrict analysis to packages matching pattern
* (-p and -e are exclusive)
* -v show class-level dependencies
* default: package-level dependencies
* -r --recursive transitive dependencies analysis
* -classpath paths Classpath to locate class files
* -all process all class files in the given classpath
*/
public class Main {
public static void main(String... args) throws Exception {
JdepsTask t = new JdepsTask();
int rc = t.run(args);
System.exit(rc);
}
/**
* Entry point that does <i>not</i> call System.exit.
*
* @param args command line arguments
* @param out output stream
* @return an exit code. 0 means success, non-zero means an error occurred.
*/
public static int run(String[] args, PrintWriter out) {
JdepsTask t = new JdepsTask();
t.setLog(out);
return t.run(args);
}
}

@ -0,0 +1,169 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jdeps;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
/**
* ClassPath for Java SE and JDK
*/
class PlatformClassPath {
/*
* Profiles for Java SE
*
* This is a temporary workaround until a common API is defined for langtools
* to determine which profile a given classname belongs to. The list of
* packages and profile names are hardcoded in jdk.properties and
* split packages are not supported.
*/
static class Profile {
final String name;
final Set<String> packages;
Profile(String name) {
this.name = name;
this.packages = new HashSet<String>();
}
}
private final static String JAVAFX = "javafx";
private final static Map<String,Profile> map = getProfilePackages();
static String getProfileName(String packageName) {
Profile profile = map.get(packageName);
if (packageName.startsWith(JAVAFX + ".")) {
profile = map.get(JAVAFX);
}
return profile != null ? profile.name : "";
}
private final static List<Archive> javaHomeArchives = init();
static List<Archive> getArchives() {
return javaHomeArchives;
}
static boolean contains(Archive archive) {
return javaHomeArchives.contains(archive);
}
private static List<Archive> init() {
List<Archive> result = new ArrayList<Archive>();
String javaHome = System.getProperty("java.home");
List<File> files = new ArrayList<File>();
File jre = new File(javaHome, "jre");
File lib = new File(javaHome, "lib");
try {
if (jre.exists() && jre.isDirectory()) {
result.addAll(addJarFiles(new File(jre, "lib")));
result.addAll(addJarFiles(lib));
} else if (lib.exists() && lib.isDirectory()) {
// either a JRE or a jdk build image
File classes = new File(javaHome, "classes");
if (classes.exists() && classes.isDirectory()) {
// jdk build outputdir
result.add(new Archive(classes, ClassFileReader.newInstance(classes)));
}
// add other JAR files
result.addAll(addJarFiles(lib));
} else {
throw new RuntimeException("\"" + javaHome + "\" not a JDK home");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
// add a JavaFX profile if there is jfxrt.jar
for (Archive archive : result) {
if (archive.getFileName().equals("jfxrt.jar")) {
map.put(JAVAFX, new Profile("jfxrt.jar"));
}
}
return result;
}
private static List<Archive> addJarFiles(File f) throws IOException {
final List<Archive> result = new ArrayList<Archive>();
final Path root = f.toPath();
final Path ext = root.resolve("ext");
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
throws IOException
{
if (dir.equals(root) || dir.equals(ext)) {
return FileVisitResult.CONTINUE;
} else {
// skip other cobundled JAR files
return FileVisitResult.SKIP_SUBTREE;
}
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException
{
File f = file.toFile();
String fn = f.getName();
if (fn.endsWith(".jar") && !fn.equals("alt-rt.jar")) {
result.add(new Archive(f, ClassFileReader.newInstance(f)));
}
return FileVisitResult.CONTINUE;
}
});
return result;
}
private static Map<String,Profile> getProfilePackages() {
Map<String,Profile> map = new HashMap<String,Profile>();
// read the properties as a ResourceBundle as the build compiles
// the properties file into Java class. Another alternative is
// to load it as Properties and fix the build to exclude this file.
ResourceBundle profileBundle =
ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdk");
int i=1;
String key;
while (profileBundle.containsKey((key = "profile." + i + ".name"))) {
Profile profile = new Profile(profileBundle.getString(key));
String n = profileBundle.getString("profile." + i + ".packages");
String[] pkgs = n.split("\\s+");
for (String p : pkgs) {
if (p.isEmpty()) continue;
assert(map.containsKey(p) == false);
profile.packages.add(p);
map.put(p, profile);
}
i++;
}
return map;
}
}

@ -0,0 +1,57 @@
main.usage.summary=\
Usage: {0} <options> <classes...>\n\
use -h, -? or --help for a list of possible options
main.usage=\
Usage: {0} <options> <classes...>\n\
where <classes> can be a pathname to a .class file, a directory, a JAR file,\n\
or a fully-qualified classname or wildcard "*". Possible options include:
error.prefix=Error:
warn.prefix=Warning:
main.opt.h=\
\ -h -? --help Print this usage message
main.opt.version=\
\ --version Version information
main.opt.V=\
\ -V <level> --verbose-level=<level> Print package-level or class-level dependencies\n\
\ Valid levels are: "package" and "class"
main.opt.v=\
\ -v --verbose Print additional information
main.opt.s=\
\ -s --summary Print dependency summary only
main.opt.p=\
\ -p <pkg name> --package=<pkg name> Restrict analysis to classes in this package\n\
\ (may be given multiple times)
main.opt.e=\
\ -e <regex> --regex=<regex> Restrict analysis to packages matching pattern\n\
\ (-p and -e are exclusive)
main.opt.P=\
\ -P --profile Show profile or the file containing a package
main.opt.c=\
\ -c <path> --classpath=<path> Specify where to find class files
main.opt.R=\
\ -R --recursive Recursively traverse all dependencies
main.opt.d=\
\ -d <depth> --depth=<depth> Specify the depth of the transitive dependency analysis
err.unknown.option=unknown option: {0}
err.missing.arg=no value given for {0}
err.internal.error=internal error: {0} {1} {2}
err.invalid.arg.for.option=invalid argument for option: {0}
err.option.after.class=option must be specified before classes: {0}
warn.invalid.arg=Invalid classname or pathname not exist: {0}
warn.split.package=package {0} defined in {1} {2}
artifact.not.found=not found

@ -0,0 +1,262 @@
# This properties file does not need localization.
profile.1.name = compact1
profile.1.packages = \
java.io \
java.lang \
java.lang.annotation \
java.lang.invoke \
java.lang.ref \
java.lang.reflect \
java.math \
java.net \
java.nio \
java.nio.channels \
java.nio.channels.spi \
java.nio.charset \
java.nio.charset.spi \
java.nio.file \
java.nio.file.attribute \
java.nio.file.spi \
java.security \
java.security.cert \
java.security.interfaces \
java.security.spec \
java.text \
java.text.spi \
java.util \
java.util.concurrent \
java.util.concurrent.atomic \
java.util.concurrent.locks \
java.util.jar \
java.util.logging \
java.util.regex \
java.util.spi \
java.util.zip \
javax.crypto \
javax.crypto.interfaces \
javax.crypto.spec \
javax.security.auth \
javax.security.auth.callback \
javax.security.auth.login \
javax.security.auth.spi \
javax.security.auth.x500 \
javax.net \
javax.net.ssl \
javax.security.cert \
\
com.sun.net.ssl \
com.sun.nio.file \
com.sun.nio.sctp \
com.sun.security.auth \
com.sun.security.auth.login
profile.2.name = compact2
profile.2.packages = \
java.sql \
javax.sql \
javax.xml \
javax.xml.datatype \
javax.xml.namespace \
javax.xml.parsers \
javax.xml.stream \
javax.xml.stream.events \
javax.xml.stream.util \
javax.xml.transform \
javax.xml.transform.dom \
javax.xml.transform.sax \
javax.xml.transform.stax \
javax.xml.transform.stream \
javax.xml.validation \
javax.xml.xpath \
org.w3c.dom \
org.w3c.dom.bootstrap \
org.w3c.dom.events \
org.w3c.dom.ls \
org.xml.sax \
org.xml.sax.ext \
org.xml.sax.helpers \
java.rmi \
java.rmi.activation \
java.rmi.dgc \
java.rmi.registry \
java.rmi.server \
javax.rmi.ssl \
javax.transaction \
javax.transaction.xa \
\
com.sun.net.httpserver \
com.sun.net.httpserver.spi
profile.3.name = compact3
profile.3.packages = \
java.lang.instrument \
java.lang.management \
java.security.acl \
java.util.prefs \
javax.management \
javax.management.loading \
javax.management.modelmbean \
javax.management.monitor \
javax.management.openmbean \
javax.management.relation \
javax.management.remote \
javax.management.remote.rmi \
javax.management.timer \
javax.naming \
javax.naming.directory \
javax.naming.event \
javax.naming.ldap \
javax.naming.spi \
javax.sql.rowset \
javax.sql.rowset.serial \
javax.sql.rowset.spi \
javax.security.auth.kerberos \
javax.security.sasl \
javax.script \
javax.smartcardio \
javax.xml.crypto \
javax.xml.crypto.dom \
javax.xml.crypto.dsig \
javax.xml.crypto.dsig.dom \
javax.xml.crypto.dsig.keyinfo \
javax.xml.crypto.dsig.spec \
javax.annotation.processing \
javax.lang.model \
javax.lang.model.element \
javax.lang.model.type \
javax.lang.model.util \
javax.tools \
javax.tools.annotation \
org.ietf.jgss \
\
com.sun.management \
com.sun.security.auth.callback \
com.sun.security.auth.module \
com.sun.security.jgss
profile.4.name = Full JRE
profile.4.packages = \
java.applet \
java.awt \
java.awt.color \
java.awt.datatransfer \
java.awt.dnd \
java.awt.dnd.peer \
java.awt.event \
java.awt.font \
java.awt.geom \
java.awt.im \
java.awt.im.spi \
java.awt.image \
java.awt.image.renderable \
java.awt.peer \
java.awt.print \
java.beans \
java.beans.beancontext \
javax.accessibility \
javax.imageio \
javax.imageio.event \
javax.imageio.metadata \
javax.imageio.plugins.bmp \
javax.imageio.plugins.jpeg \
javax.imageio.spi \
javax.imageio.stream \
javax.print \
javax.print.attribute \
javax.print.attribute.standard \
javax.print.event \
javax.sound.midi \
javax.sound.midi.spi \
javax.sound.sampled \
javax.sound.sampled.spi \
javax.swing \
javax.swing.border \
javax.swing.colorchooser \
javax.swing.event \
javax.swing.filechooser \
javax.swing.plaf \
javax.swing.plaf.basic \
javax.swing.plaf.metal \
javax.swing.plaf.multi \
javax.swing.plaf.nimbus \
javax.swing.plaf.synth \
javax.swing.table \
javax.swing.text \
javax.swing.text.html \
javax.swing.text.html.parser \
javax.swing.text.rtf \
javax.swing.tree \
javax.swing.undo \
javax.activation \
javax.jws \
javax.jws.soap \
javax.rmi \
javax.rmi.CORBA \
javax.xml.bind \
javax.xml.bind.annotation \
javax.xml.bind.annotation.adapters \
javax.xml.bind.attachment \
javax.xml.bind.helpers \
javax.xml.bind.util \
javax.xml.soap \
javax.xml.ws \
javax.xml.ws.handler \
javax.xml.ws.handler.soap \
javax.xml.ws.http \
javax.xml.ws.soap \
javax.xml.ws.spi \
javax.xml.ws.spi.http \
javax.xml.ws.wsaddressing \
javax.annotation \
org.omg.CORBA \
org.omg.CORBA.DynAnyPackage \
org.omg.CORBA.ORBPackage \
org.omg.CORBA.TypeCodePackage \
org.omg.CORBA.portable \
org.omg.CORBA_2_3 \
org.omg.CORBA_2_3.portable \
org.omg.CosNaming \
org.omg.CosNaming.NamingContextExtPackage \
org.omg.CosNaming.NamingContextPackage \
org.omg.Dynamic \
org.omg.DynamicAny \
org.omg.DynamicAny.DynAnyFactoryPackage \
org.omg.DynamicAny.DynAnyPackage \
org.omg.IOP \
org.omg.IOP.CodecFactoryPackage \
org.omg.IOP.CodecPackage \
org.omg.Messaging \
org.omg.PortableInterceptor \
org.omg.PortableInterceptor.ORBInitInfoPackage \
org.omg.PortableServer \
org.omg.PortableServer.CurrentPackage \
org.omg.PortableServer.POAManagerPackage \
org.omg.PortableServer.POAPackage \
org.omg.PortableServer.ServantLocatorPackage \
org.omg.PortableServer.portable \
org.omg.SendingContext \
org.omg.stub.java.rmi \
org.omg.stub.javax.management.remote.rmi
# Remaining JDK supported API
profile.5.name = JDK tools
profile.5.packages = \
com.sun.jdi \
com.sun.jdi.connect \
com.sun.jdi.connect.spi \
com.sun.jdi.event \
com.sun.jdi.request \
com.sun.javadoc \
com.sun.tools.doclets \
com.sun.tools.doctree \
com.sun.source.tree \
com.sun.source.util \
com.sun.tools.attach \
com.sun.tools.attach.spi \
com.sun.tools.jconsole \
com.sun.tools.javac \
com.sun.tools.javah \
com.sun.tools.javap \
com.sun.tools.javadoc \
com.sun.servicetag

@ -0,0 +1,28 @@
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
jdk=$(JDK_VERSION)
full=$(FULL_VERSION)
release=$(RELEASE)

@ -179,6 +179,10 @@ public interface Element {
* instance initializer}, an empty name is returned.
*
* @return the simple name of this element
* @see PackageElement#getSimpleName
* @see ExecutableElement#getSimpleName
* @see TypeElement#getSimpleName
* @see VariableElement#getSimpleName
*/
Name getSimpleName();
@ -202,6 +206,11 @@ public interface Element {
* {@linkplain TypeParameterElement#getGenericElement the
* generic element} of the type parameter is returned.
*
* <li> If this is a {@linkplain
* VariableElement#getEnclosingElement method or constructor
* parameter}, {@linkplain ExecutableElement the executable
* element} which declares the parameter is returned.
*
* </ul>
*
* @return the enclosing element, or {@code null} if there is none

@ -62,4 +62,29 @@ public interface VariableElement extends Element {
* @jls 4.12.4 final Variables
*/
Object getConstantValue();
/**
* Returns the simple name of this variable element.
*
* <p>For method and constructor parameters, the name of each
* parameter must be distinct from the names of all other
* parameters of the same executable. If the original source
* names are not available, an implementation may synthesize names
* subject to the distinctness requirement above.
*
* @return the simple name of this variable element
*/
@Override
Name getSimpleName();
/**
* Returns the enclosing element of this variable.
*
* The enclosing element of a method or constructor parameter is
* the executable declaring the parameter.
*
* @return the enclosing element of this variable
*/
@Override
Element getEnclosingElement();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -48,9 +48,12 @@
* {@linkplain java.lang.annotation.RetentionPolicy#SOURCE source}
* {@linkplain java.lang.annotation.Retention retention} cannot be
* recovered from class files and class files might not be able to
* provide source position information. The {@linkplain
* javax.lang.model.element.Modifier modifiers} on an element may
* differ in some cases including
* provide source position information.
*
* Names of parameters may not be recoverable from class files.
*
* The {@linkplain javax.lang.model.element.Modifier modifiers} on an
* element may differ in some cases including:
*
* <ul>
* <li> {@code strictfp} on a class or interface

@ -229,7 +229,7 @@ JCK_RUNTIME_OUTPUT_DIR = $(ABS_TEST_OUTPUT_DIR)/jck-runtime-Xcompile
all: $(JPRT_CLEAN) jtreg-tests jck-compiler-tests jck-runtime-tests $(JPRT_ARCHIVE_BUNDLE) all-summary
@echo "Testing completed successfully"
jtreg apt javac javadoc javah javap: $(JPRT_CLEAN) jtreg-tests $(JPRT_ARCHIVE_BUNDLE) jtreg-summary
jtreg apt javac javadoc javah javap jdeps: $(JPRT_CLEAN) jtreg-tests $(JPRT_ARCHIVE_BUNDLE) jtreg-summary
@echo "Testing completed successfully"
jck-compiler: $(JPRT_CLEAN) jck-compiler-tests $(JPRT_ARCHIVE_BUNDLE) jck-compiler-summary
@ -246,6 +246,7 @@ javac: JTREG_TESTDIRS = tools/javac
javadoc: JTREG_TESTDIRS = tools/javadoc com/sun/javadoc
javah: JTREG_TESTDIRS = tools/javah
javap: JTREG_TESTDIRS = tools/javap
jdeps: JTREG_TESTDIRS = tools/jdeps
# Run jtreg tests
#
@ -426,7 +427,7 @@ FRC:
# Phony targets (e.g. these are not filenames)
.PHONY: all clean \
jtreg javac javadoc javah javap jtreg-tests jtreg-summary check-jtreg \
jtreg javac javadoc javah javap jdeps jtreg-tests jtreg-summary check-jtreg \
jck-compiler jck-compiler-tests jck-compiler-summary \
jck-runtime jck-runtime-tests jck-runtime-summary check-jck

@ -0,0 +1,121 @@
/*
* Copyright (c) 2012, 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 8004891
* @summary Make sure that the abstract method is identified correctly
* if the abstract modifier is present explicitly or implicitly.
* @author bpatel
* @library ../lib/
* @build JavadocTester TestAbstractMethod
* @run main TestAbstractMethod
*/
public class TestAbstractMethod extends JavadocTester {
//Test information.
private static final String BUG_ID = "8004891";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg"
};
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg" + FS + "A.html",
"<td class=\"colFirst\"><code>default void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "A.html",
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
"All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t2\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span><span id=\"t3\" " +
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">" +
"Abstract Methods</a></span><span class=\"tabEnd\">&nbsp;</span>" +
"</span><span id=\"t5\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
"All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t2\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span><span id=\"t3\" " +
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">Abstract " +
"Methods</a></span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t4\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(8);\">Concrete Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<td class=\"colFirst\"><code>abstract void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
"All Methods</span><span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t2\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span>" +
"<span id=\"t5\" class=\"tableTab\"><span>" +
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span></span></caption>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<td class=\"colFirst\"><code>default void</code></td>"}
};
private static final String[][] NEGATED_TEST = {
{BUG_ID + FS + "pkg" + FS + "A.html",
"<td class=\"colFirst\"><code>abstract void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<span><a href=\"javascript:show(16);\">Default Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span>"},
{BUG_ID + FS + "pkg" + FS + "B.html",
"<td class=\"colFirst\"><code>default void</code></td>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<span><a href=\"javascript:show(4);\">Abstract Methods</a></span>" +
"<span class=\"tabEnd\">&nbsp;</span>"}
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestAbstractMethod tester = new TestAbstractMethod();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
public interface A {
public void method1();
public default void defaultMethod() { }
}

@ -0,0 +1,31 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
public abstract class B {
public abstract void method1();
public void method2() { }
}

@ -0,0 +1,29 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
public interface C {
public default void onlyMethod() { }
}

@ -0,0 +1,187 @@
/*
* Copyright (c) 2012, 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 8005092
* @summary Test repeated annotations output.
* @author bpatel
* @library ../lib/
* @build JavadocTester TestRepeatedAnnotations
* @run main TestRepeatedAnnotations
*/
public class TestRepeatedAnnotations extends JavadocTester {
//Test information.
private static final String BUG_ID = "8005092";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "pkg1"
};
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/ContaineeRegDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeRegDoc</a> " +
"<a href=\"../pkg/ContaineeRegDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeRegDoc</a>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/RegContainerDoc.html\" " +
"title=\"annotation in pkg\">@RegContainerDoc</a>" +
"(<a href=\"../pkg/RegContainerDoc.html#value()\">value</a>={" +
"<a href=\"../pkg/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeNotDoc</a>," +
"<a href=\"../pkg/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeNotDoc</a>})"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/ContainerSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContainerSynthDoc</a>(" +
"<a href=\"../pkg/ContainerSynthDoc.html#value()\">value</a>=" +
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a>)"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a> " +
"<a href=\"../pkg/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg\">@ContaineeSynthDoc</a>"},
{BUG_ID + FS + "pkg" + FS + "D.html",
"<a href=\"../pkg/RegDoc.html\" title=\"annotation in pkg\">@RegDoc</a>" +
"(<a href=\"../pkg/RegDoc.html#x()\">x</a>=1)"},
{BUG_ID + FS + "pkg" + FS + "D.html",
"<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>" +
"(<a href=\"../pkg/RegArryDoc.html#y()\">y</a>=1)"},
{BUG_ID + FS + "pkg" + FS + "D.html",
"<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>" +
"(<a href=\"../pkg/RegArryDoc.html#y()\">y</a>={1,2})"},
{BUG_ID + FS + "pkg" + FS + "D.html",
"<a href=\"../pkg/NonSynthDocContainer.html\" " +
"title=\"annotation in pkg\">@NonSynthDocContainer</a>" +
"(<a href=\"../pkg/NonSynthDocContainer.html#value()\">value</a>=" +
"<a href=\"../pkg/RegArryDoc.html\" title=\"annotation in pkg\">@RegArryDoc</a>)"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/RegContainerValDoc.html\" " +
"title=\"annotation in pkg1\">@RegContainerValDoc</a>" +
"(<a href=\"../pkg1/RegContainerValDoc.html#value()\">value</a>={" +
"<a href=\"../pkg1/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@RegContaineeNotDoc</a>," +
"<a href=\"../pkg1/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@RegContaineeNotDoc</a>}," +
"<a href=\"../pkg1/RegContainerValDoc.html#y()\">y</a>=3)"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/ContainerValDoc.html\" " +
"title=\"annotation in pkg1\">@ContainerValDoc</a>" +
"(<a href=\"../pkg1/ContainerValDoc.html#value()\">value</a>={" +
"<a href=\"../pkg1/ContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeNotDoc</a>," +
"<a href=\"../pkg1/ContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeNotDoc</a>}," +
"<a href=\"../pkg1/ContainerValDoc.html#x()\">x</a>=1)"}
};
private static final String[][] NEGATED_TEST = {
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/RegContaineeDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeDoc</a> " +
"<a href=\"../pkg/RegContaineeDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeDoc</a>"},
{BUG_ID + FS + "pkg" + FS + "C.html",
"<a href=\"../pkg/RegContainerNotDoc.html\" " +
"title=\"annotation in pkg\">@RegContainerNotDoc</a>" +
"(<a href=\"../pkg/RegContainerNotDoc.html#value()\">value</a>={" +
"<a href=\"../pkg/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeNotDoc</a>," +
"<a href=\"../pkg/RegContaineeNotDoc.html\" " +
"title=\"annotation in pkg\">@RegContaineeNotDoc</a>})"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeSynthDoc</a> " +
"<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeSynthDoc</a>"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/RegContainerValNotDoc.html\" " +
"title=\"annotation in pkg1\">@RegContainerValNotDoc</a>" +
"(<a href=\"../pkg1/RegContainerValNotDoc.html#value()\">value</a>={" +
"<a href=\"../pkg1/RegContaineeDoc.html\" " +
"title=\"annotation in pkg1\">@RegContaineeDoc</a>," +
"<a href=\"../pkg1/RegContaineeDoc.html\" " +
"title=\"annotation in pkg1\">@RegContaineeDoc</a>}," +
"<a href=\"../pkg1/RegContainerValNotDoc.html#y()\">y</a>=4)"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/ContainerValNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContainerValNotDoc</a>" +
"(<a href=\"../pkg1/ContainerValNotDoc.html#value()\">value</a>={" +
"<a href=\"../pkg1/ContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeNotDoc</a>," +
"<a href=\"../pkg1/ContaineeNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeNotDoc</a>}," +
"<a href=\"../pkg1/ContainerValNotDoc.html#x()\">x</a>=2)"},
{BUG_ID + FS + "pkg1" + FS + "C.html",
"<a href=\"../pkg1/ContainerSynthNotDoc.html\" " +
"title=\"annotation in pkg1\">@ContainerSynthNotDoc</a>(" +
"<a href=\"../pkg1/ContainerSynthNotDoc.html#value()\">value</a>=" +
"<a href=\"../pkg1/ContaineeSynthDoc.html\" " +
"title=\"annotation in pkg1\">@ContaineeSynthDoc</a>)"}
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestRepeatedAnnotations tester = new TestRepeatedAnnotations();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
@ContainerSynthDoc(value={@ContaineeSynthDoc,@ContaineeSynthDoc})
@ContainerRegDoc(value={@ContaineeRegDoc,@ContaineeRegDoc})
@RegContainerDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc})
@ContainerRegNotDoc(value={@RegContaineeDoc,@RegContaineeDoc})
@RegContainerNotDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc})
@ContaineeSynthDoc @ContaineeSynthDoc @ContaineeSynthDoc
public class C {
@ContainerSynthDoc(value={@ContaineeSynthDoc})
public void test1() {}
@ContaineeSynthDoc @ContaineeSynthDoc
public void test2() {}
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation contained by ContainerRegDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface ContaineeRegDoc {
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented synthesized annotation contained by ContainerSynthDoc.
* It will be used to annotate Class C and a method in the class using a synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
@ContainedBy(ContainerSynthDoc.class)
public @interface ContaineeSynthDoc {
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation container for ContaineeRegDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface ContainerRegDoc {
ContaineeRegDoc[] value();
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation container for RegContaineeDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface ContainerRegNotDoc {
RegContaineeDoc[] value();
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented synthesized annotation container for ContaineeSynthDoc.
* It will be used to annotate Class C and a method in the class using a synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
@ContainerFor(ContaineeSynthDoc.class)
public @interface ContainerSynthDoc {
ContaineeSynthDoc[] value();
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
@RegDoc(x=1)
public class D {
@RegArryDoc(y={1})
public void test1() {}
@RegArryDoc(y={1,2})
public void test2() {}
@NonSynthDocContainer(value={@RegArryDoc})
public void test3() {}
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation.
* It will be used to annotate methods in class D.
*
* @author Bhavesh Patel
*/
@Documented
public @interface NonSynthDocContainer {
RegArryDoc[] value();
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation.
* It will be used to annotate methods in Class D.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegArryDoc {
int[] y();
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation contained by ContainerRegNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegContaineeDoc {
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation contained by RegContainerNotDoc
* and RegContainerDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface RegContaineeNotDoc {
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation container for RegContainerDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegContainerDoc {
RegContaineeNotDoc[] value();
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation container for RegContaineeNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface RegContainerNotDoc {
RegContaineeNotDoc[] value();
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation.
* It will be used to annotate Class D.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegDoc {
int x();
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
@ContainerSynthNotDoc(value={@ContaineeSynthDoc,@ContaineeSynthDoc})
@RegContainerValDoc(value={@RegContaineeNotDoc,@RegContaineeNotDoc},y=3)
@ContainerValDoc(value={@ContaineeNotDoc,@ContaineeNotDoc},x=1)
@RegContainerValNotDoc(value={@RegContaineeDoc,@RegContaineeDoc},y=4)
@ContainerValNotDoc(value={@ContaineeNotDoc,@ContaineeNotDoc},x=2)
public class C {
@ContainerSynthNotDoc(value={@ContaineeSynthDoc})
public void test1() {}
@ContaineeSynthDoc @ContaineeSynthDoc
public void test2() {}
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation contained by ContainerValNotDoc
* and ContainerValDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface ContaineeNotDoc {
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a documented synthesized annotation contained by ContainerSynthNotDoc.
* It will be used to annotate Class C and methods in the class using a synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
@ContainedBy(ContainerSynthNotDoc.class)
public @interface ContaineeSynthDoc {
}

@ -0,0 +1,38 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a non-documented synthesized annotation container for ContaineeSynthDoc.
* It will be used to annotate Class C and methods in the class using a synthesized form.
*
* @author Bhavesh Patel
*/
@ContainerFor(ContaineeSynthDoc.class)
public @interface ContainerSynthNotDoc {
ContaineeSynthDoc[] value();
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation container for ContaineeNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface ContainerValDoc {
ContaineeNotDoc[] value();
int x();
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation container for ContaineeNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface ContainerValNotDoc {
ContaineeNotDoc[] value();
int x();
}

@ -0,0 +1,36 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation contained by RegContainerValNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegContaineeDoc {
}

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation contained by RegContainerValDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface RegContaineeNotDoc {
}

@ -0,0 +1,40 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a documented annotation container for RegContaineeNotDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
@Documented
public @interface RegContainerValDoc {
RegContaineeNotDoc[] value();
int y();
}

@ -0,0 +1,39 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package pkg1;
import java.lang.annotation.*;
/**
* This annotation is a non-documented annotation container for RegContaineeDoc.
* It will be used to annotate Class C using a non-synthesized form.
*
* @author Bhavesh Patel
*/
public @interface RegContainerValNotDoc {
RegContaineeDoc[] value();
int y();
}

@ -107,7 +107,7 @@ public class DocLintTester {
private static final Pattern dirFileLine = Pattern.compile(
"(?m)" // multi-line mode
+ "^([^: ]+?)" // directory part of file name
+ "^(.*?)" // directory part of file name
+ "([A-Za-z0-9.]+:[0-9]+:)"); // file name and line number
String removeFileNames(String s) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2013, 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,14 +26,19 @@
* @bug 6769027
* @summary Source line should be displayed immediately after the first diagnostic line
* @author Maurizio Cimadamore
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main/othervm T6769027
*/
import java.net.URI;
import java.util.regex.Matcher;
import javax.tools.*;
import com.sun.tools.javac.util.*;
public class T6769027 {
public class T6769027
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum OutputKind {
RAW("rawDiagnostics","rawDiagnostics"),
@ -314,7 +319,7 @@ public class T6769027 {
@Override
protected java.io.PrintWriter getWriterForDiagnosticType(JCDiagnostic.DiagnosticType dt) {
return new java.io.PrintWriter(System.out);
return outWriter;
}
@Override
@ -323,13 +328,42 @@ public class T6769027 {
}
}
int nerrors = 0;
OutputKind outputKind;
ErrorKind errorKind;
MultilineKind multiKind;
MultilinePolicy multiPolicy;
PositionKind posKind;
XDiagsSource xdiagsSource;
XDiagsCompact xdiagsCompact;
CaretKind caretKind;
SourceLineKind sourceLineKind;
IndentKind summaryIndent;
IndentKind detailsIndent;
IndentKind sourceIndent;
IndentKind subdiagsIndent;
void exec(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
T6769027(OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
IndentKind subdiagsIndent) {
this.outputKind = outputKind;
this.errorKind = errorKind;
this.multiKind = multiKind;
this.multiPolicy = multiPolicy;
this.posKind = posKind;
this.xdiagsSource = xdiagsSource;
this.xdiagsCompact = xdiagsCompact;
this.caretKind = caretKind;
this.sourceLineKind = sourceLineKind;
this.summaryIndent = summaryIndent;
this.detailsIndent = detailsIndent;
this.sourceIndent = sourceIndent;
this.subdiagsIndent = subdiagsIndent;
}
@Override
public void run() {
Context ctx = new Context();
Options options = Options.instance(ctx);
outputKind.init(options);
@ -362,23 +396,10 @@ public class T6769027 {
d = new JCDiagnostic.MultilineDiagnostic(d, subdiags);
}
String diag = log.getDiagnosticFormatter().format(d, messages.getCurrentLocale());
checkOutput(diag,
outputKind,
errorKind,
multiKind,
multiPolicy,
posKind,
xdiagsSource,
xdiagsCompact,
caretKind,
sourceLineKind,
summaryIndent,
detailsIndent,
sourceIndent,
subdiagsIndent);
checkOutput(diag);
}
void test() {
public static void main(String[] args) throws Exception {
for (OutputKind outputKind : OutputKind.values()) {
for (ErrorKind errKind : ErrorKind.values()) {
for (MultilineKind multiKind : MultilineKind.values()) {
@ -392,7 +413,7 @@ public class T6769027 {
for (IndentKind detailsIndent : IndentKind.values()) {
for (IndentKind sourceIndent : IndentKind.values()) {
for (IndentKind subdiagsIndent : IndentKind.values()) {
exec(outputKind,
pool.execute(new T6769027(outputKind,
errKind,
multiKind,
multiPolicy,
@ -404,7 +425,7 @@ public class T6769027 {
summaryIndent,
detailsIndent,
sourceIndent,
subdiagsIndent);
subdiagsIndent));
}
}
}
@ -418,15 +439,11 @@ public class T6769027 {
}
}
}
if (nerrors != 0)
throw new AssertionError(nerrors + " errors found");
checkAfterExec(false);
}
void printInfo(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
IndentKind subdiagsIndent, String errorLine) {
void printInfo(String msg, String errorLine) {
String sep = "*********************************************************";
String desc = "raw=" + outputKind + " pos=" + posKind + " key=" + errorKind.key() +
" multiline=" + multiKind +" multiPolicy=" + multiPolicy.value +
@ -434,18 +451,14 @@ public class T6769027 {
" caret=" + caretKind + " sourcePosition=" + sourceLineKind +
" summaryIndent=" + summaryIndent + " detailsIndent=" + detailsIndent +
" sourceIndent=" + sourceIndent + " subdiagsIndent=" + subdiagsIndent;
System.out.println(sep);
System.out.println(desc);
System.out.println(sep);
System.out.println(msg);
System.out.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
errWriter.println(sep);
errWriter.println(desc);
errWriter.println(sep);
errWriter.println(msg);
errWriter.println("Diagnostic formatting problem - expected diagnostic...\n" + errorLine);
}
void checkOutput(String msg, OutputKind outputKind, ErrorKind errorKind, MultilineKind multiKind,
MultilinePolicy multiPolicy, PositionKind posKind, XDiagsSource xdiagsSource,
XDiagsCompact xdiagsCompact, CaretKind caretKind, SourceLineKind sourceLineKind,
IndentKind summaryIndent, IndentKind detailsIndent, IndentKind sourceIndent,
IndentKind subdiagsIndent) {
void checkOutput(String msg) {
boolean shouldPrintSource = posKind == PositionKind.POS &&
xdiagsSource != XDiagsSource.NO_SOURCE &&
(xdiagsSource == XDiagsSource.SOURCE ||
@ -453,7 +466,8 @@ public class T6769027 {
String errorLine = posKind.getOutput(outputKind) +
errorKind.getOutput(outputKind, summaryIndent, detailsIndent);
if (xdiagsCompact != XDiagsCompact.COMPACT)
errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy, summaryIndent, detailsIndent, subdiagsIndent);
errorLine += multiKind.getOutput(outputKind, errorKind, multiPolicy,
summaryIndent, detailsIndent, subdiagsIndent);
String[] lines = errorLine.split("\n");
if (xdiagsCompact == XDiagsCompact.COMPACT) {
errorLine = lines[0];
@ -474,26 +488,9 @@ public class T6769027 {
}
if (!msg.equals(errorLine)) {
printInfo(msg,
outputKind,
errorKind,
multiKind,
multiPolicy,
posKind,
xdiagsSource,
xdiagsCompact,
caretKind,
sourceLineKind,
summaryIndent,
detailsIndent,
sourceIndent,
subdiagsIndent,
errorLine);
nerrors++;
printInfo(msg, errorLine);
errCount.incrementAndGet();
}
}
public static void main(String... args) throws Exception {
new T6769027().test();
}
}

@ -0,0 +1,344 @@
/*
* Copyright (c) 2012, 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 8004727
* @summary javac should generate method parameters correctly.
*/
// key: opt.arg.parameters
import com.sun.tools.classfile.*;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Names;
import java.io.*;
import javax.lang.model.element.*;
import java.util.*;
public class MethodParameters {
static final String Foo_name = "Foo";
static final String Foo_contents =
"public class Foo {\n" +
" Foo() {}\n" +
" void foo0() {}\n" +
" void foo2(int j, int k) {}\n" +
"}";
static final String Bar_name = "Bar";
static final String Bar_contents =
"public class Bar {\n" +
" Bar(int i) {}" +
" Foo foo() { return new Foo(); }\n" +
"}";
static final String Baz_name = "Baz";
static final String Baz_contents =
"public class Baz {\n" +
" int baz;" +
" Baz(int i) {}" +
"}";
static final String Qux_name = "Qux";
static final String Qux_contents =
"public class Qux extends Baz {\n" +
" Qux(int i) { super(i); }" +
"}";
static final File classesdir = new File("methodparameters");
public static void main(String... args) throws Exception {
new MethodParameters().run();
}
void run() throws Exception {
classesdir.mkdir();
final File Foo_java =
writeFile(classesdir, Foo_name + ".java", Foo_contents);
final File Bar_java =
writeFile(classesdir, Bar_name + ".java", Bar_contents);
final File Baz_java =
writeFile(classesdir, Baz_name + ".java", Baz_contents);
System.err.println("Test compile with -parameter");
compile("-parameters", "-d", classesdir.getPath(), Foo_java.getPath());
// First test: make sure javac doesn't choke to death on
// MethodParameter attributes
System.err.println("Test compile with classfile containing MethodParameter attributes");
compile("-parameters", "-d", classesdir.getPath(),
"-cp", classesdir.getPath(), Bar_java.getPath());
System.err.println("Examine class foo");
checkFoo();
checkBar();
System.err.println("Test debug information conflict");
compile("-g", "-parameters", "-d", classesdir.getPath(),
"-cp", classesdir.getPath(), Baz_java.getPath());
System.err.println("Introducing debug information conflict");
Baz_java.delete();
modifyBaz(false);
System.err.println("Checking language model");
inspectBaz();
System.err.println("Permuting attributes");
modifyBaz(true);
System.err.println("Checking language model");
inspectBaz();
if(0 != errors)
throw new Exception("MethodParameters test failed with " +
errors + " errors");
}
void inspectBaz() throws Exception {
final File Qux_java =
writeFile(classesdir, Qux_name + ".java", Qux_contents);
final String[] args = { "-XDsave-parameter-names", "-d",
classesdir.getPath(),
"-cp", classesdir.getPath(),
Qux_java.getPath() };
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
// We need to be able to crack open javac and look at its data
// structures. We'll rig up a compiler instance, but keep its
// Context, thus allowing us to get at the ClassReader.
Context context = new Context();
Main comp = new Main("javac", pw);
JavacFileManager.preRegister(context);
// Compile Qux, which uses Baz.
comp.compile(args, context);
pw.close();
final String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
// Now get the class reader, construct a name for Baz, and load it.
com.sun.tools.javac.jvm.ClassReader cr =
com.sun.tools.javac.jvm.ClassReader.instance(context);
Name name = Names.instance(context).fromString(Baz_name);
// Now walk down the language model and check the name of the
// parameter.
final Element baz = cr.loadClass(name);
for (Element e : baz.getEnclosedElements()) {
if (e instanceof ExecutableElement) {
final ExecutableElement ee = (ExecutableElement) e;
final List<? extends VariableElement> params =
ee.getParameters();
if (1 != params.size())
throw new Exception("Classfile Baz badly formed: wrong number of methods");
final VariableElement param = params.get(0);
if (!param.getSimpleName().contentEquals("baz")) {
errors++;
System.err.println("javac did not correctly resolve the metadata conflict, parameter's name reads as " + param.getSimpleName());
} else
System.err.println("javac did correctly resolve the metadata conflict");
}
}
}
void modifyBaz(boolean flip) throws Exception {
final File Baz_class = new File(classesdir, Baz_name + ".class");
final ClassFile baz = ClassFile.read(Baz_class);
final int ind = baz.constant_pool.getUTF8Index("baz");
MethodParameters_attribute mpattr = null;
int mpind = 0;
Code_attribute cattr = null;
int cind = 0;
// Find the indexes of the MethodParameters and the Code attributes
if (baz.methods.length != 1)
throw new Exception("Classfile Baz badly formed: wrong number of methods");
if (!baz.methods[0].getName(baz.constant_pool).equals("<init>"))
throw new Exception("Classfile Baz badly formed: method has name " +
baz.methods[0].getName(baz.constant_pool));
for (int i = 0; i < baz.methods[0].attributes.attrs.length; i++) {
if (baz.methods[0].attributes.attrs[i] instanceof
MethodParameters_attribute) {
mpattr = (MethodParameters_attribute)
baz.methods[0].attributes.attrs[i];
mpind = i;
} else if (baz.methods[0].attributes.attrs[i] instanceof
Code_attribute) {
cattr = (Code_attribute) baz.methods[0].attributes.attrs[i];
cind = i;
}
}
if (null == mpattr)
throw new Exception("Classfile Baz badly formed: no method parameters info");
if (null == cattr)
throw new Exception("Classfile Baz badly formed: no local variable table");
int flags = mpattr.method_parameter_table[0].flags;
// Alter the MethodParameters attribute, changing the name of
// the parameter from i to baz. This requires Black Magic...
//
// The (well-designed) classfile library (correctly) does not
// allow us to mess around with the attribute data structures,
// or arbitrarily generate new ones.
//
// Instead, we install a new subclass of Attribute that
// hijacks the Visitor pattern and outputs the sequence of
// bytes that we want. This only works in this particular
// instance, because we know we'll only every see one kind of
// visitor.
//
// If anyone ever changes the makeup of the Baz class, or
// tries to install some kind of visitor that gets run prior
// to serialization, this will break.
baz.methods[0].attributes.attrs[mpind] =
new Attribute(mpattr.attribute_name_index,
mpattr.attribute_length) {
public <R, D> R accept(Visitor<R, D> visitor, D data) {
if (data instanceof ByteArrayOutputStream) {
ByteArrayOutputStream out =
(ByteArrayOutputStream) data;
out.write(1);
out.write((ind >> 8) & 0xff);
out.write(ind & 0xff);
out.write((flags >> 24) & 0xff);
out.write((flags >> 16) & 0xff);
out.write((flags >> 8) & 0xff);
out.write(flags & 0xff);
} else
throw new RuntimeException("Output stream is of type " + data.getClass() + ", which is not handled by this test. Update the test and it should work.");
return null;
}
};
// Flip the code and method attributes. This is for checking
// that order doesn't matter.
if (flip) {
baz.methods[0].attributes.attrs[mpind] = cattr;
baz.methods[0].attributes.attrs[cind] = mpattr;
}
new ClassWriter().write(baz, Baz_class);
}
// Run a bunch of structural tests on foo to make sure it looks right.
void checkFoo() throws Exception {
final File Foo_class = new File(classesdir, Foo_name + ".class");
final ClassFile foo = ClassFile.read(Foo_class);
for (int i = 0; i < foo.methods.length; i++) {
System.err.println("Examine method Foo." + foo.methods[i].getName(foo.constant_pool));
if (foo.methods[i].getName(foo.constant_pool).equals("foo2")) {
for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
if (foo.methods[i].attributes.attrs[j] instanceof
MethodParameters_attribute) {
MethodParameters_attribute mp =
(MethodParameters_attribute)
foo.methods[i].attributes.attrs[j];
System.err.println("Foo.foo2 should have 2 parameters: j and k");
if (2 != mp.method_parameter_table_length)
error("expected 2 method parameter entries in foo2, got " +
mp.method_parameter_table_length);
else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("j"))
error("expected first parameter to foo2 to be \"j\", got \"" +
foo.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
"\" instead");
else if (!foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index).equals("k"))
error("expected first parameter to foo2 to be \"k\", got \"" +
foo.constant_pool.getUTF8Value(mp.method_parameter_table[1].name_index) +
"\" instead");
}
}
else if (foo.methods[i].getName(foo.constant_pool).equals("<init>")) {
for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++) {
if (foo.methods[i].attributes.attrs[j] instanceof
MethodParameters_attribute)
error("Zero-argument constructor shouldn't have MethodParameters");
}
}
else if (foo.methods[i].getName(foo.constant_pool).equals("foo0")) {
for (int j = 0; j < foo.methods[i].attributes.attrs.length; j++)
if (foo.methods[i].attributes.attrs[j] instanceof
MethodParameters_attribute)
error("Zero-argument method shouldn't have MethodParameters");
}
else
error("Unknown method " + foo.methods[i].getName(foo.constant_pool) + " showed up in class Foo");
}
}
// Run a bunch of structural tests on Bar to make sure it looks right.
void checkBar() throws Exception {
final File Bar_class = new File(classesdir, Bar_name + ".class");
final ClassFile bar = ClassFile.read(Bar_class);
for (int i = 0; i < bar.methods.length; i++) {
System.err.println("Examine method Bar." + bar.methods[i].getName(bar.constant_pool));
if (bar.methods[i].getName(bar.constant_pool).equals("<init>")) {
for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++)
if (bar.methods[i].attributes.attrs[j] instanceof
MethodParameters_attribute) {
MethodParameters_attribute mp =
(MethodParameters_attribute)
bar.methods[i].attributes.attrs[j];
System.err.println("Bar constructor should have 1 parameter: i");
if (1 != mp.method_parameter_table_length)
error("expected 1 method parameter entries in constructor, got " +
mp.method_parameter_table_length);
else if (!bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index).equals("i"))
error("expected first parameter to foo2 to be \"i\", got \"" +
bar.constant_pool.getUTF8Value(mp.method_parameter_table[0].name_index) +
"\" instead");
}
}
else if (bar.methods[i].getName(bar.constant_pool).equals("foo")) {
for (int j = 0; j < bar.methods[i].attributes.attrs.length; j++) {
if (bar.methods[i].attributes.attrs[j] instanceof
MethodParameters_attribute)
error("Zero-argument constructor shouldn't have MethodParameters");
}
}
}
}
String compile(String... args) throws Exception {
System.err.println("compile: " + Arrays.asList(args));
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args, pw);
pw.close();
String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
if (rc != 0)
error("compilation failed, rc=" + rc);
return out;
}
File writeFile(File dir, String path, String body) throws IOException {
File f = new File(dir, path);
f.getParentFile().mkdirs();
FileWriter out = new FileWriter(f);
out.write(body);
out.close();
return f;
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,35 +25,29 @@
* @test
* @bug 7093325
* @summary Redundant entry in bytecode exception table
* @library lib
* @build JavacTestingAbstractThreadedTest
* @run main T7093325
*/
import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool.*;
import com.sun.tools.classfile.Method;
import com.sun.tools.javac.api.JavacTool;
import java.io.File;
import java.net.URI;
import java.util.Arrays;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool.*;
import com.sun.tools.classfile.Method;
public class T7093325 {
/** global decls ***/
// Create a single file manager and reuse it for each compile to save time.
static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
//statistics
static int checkCount = 0;
public class T7093325
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum StatementKind {
THROW("throw new RuntimeException();", false, false),
@ -89,7 +83,8 @@ public class T7093325 {
if (this.ordinal() == 0) {
return catchStr;
} else {
return CatchArity.values()[this.ordinal() - 1].catchers() + catchStr;
return CatchArity.values()[this.ordinal() - 1].catchers() +
catchStr;
}
}
}
@ -98,31 +93,36 @@ public class T7093325 {
for (CatchArity ca : CatchArity.values()) {
for (StatementKind stmt0 : StatementKind.values()) {
if (ca.ordinal() == 0) {
new T7093325(ca, stmt0).compileAndCheck();
pool.execute(new T7093325(ca, stmt0));
continue;
}
for (StatementKind stmt1 : StatementKind.values()) {
if (ca.ordinal() == 1) {
new T7093325(ca, stmt0, stmt1).compileAndCheck();
pool.execute(new T7093325(ca, stmt0, stmt1));
continue;
}
for (StatementKind stmt2 : StatementKind.values()) {
if (ca.ordinal() == 2) {
new T7093325(ca, stmt0, stmt1, stmt2).compileAndCheck();
pool.execute(new T7093325(ca, stmt0, stmt1, stmt2));
continue;
}
for (StatementKind stmt3 : StatementKind.values()) {
if (ca.ordinal() == 3) {
new T7093325(ca, stmt0, stmt1, stmt2, stmt3).compileAndCheck();
pool.execute(
new T7093325(ca, stmt0, stmt1, stmt2, stmt3));
continue;
}
for (StatementKind stmt4 : StatementKind.values()) {
if (ca.ordinal() == 4) {
new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4).compileAndCheck();
pool.execute(
new T7093325(ca, stmt0, stmt1,
stmt2, stmt3, stmt4));
continue;
}
for (StatementKind stmt5 : StatementKind.values()) {
new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4, stmt5).compileAndCheck();
pool.execute(
new T7093325(ca, stmt0, stmt1, stmt2,
stmt3, stmt4, stmt5));
}
}
}
@ -131,7 +131,7 @@ public class T7093325 {
}
}
System.out.println("Total checks made: " + checkCount);
checkAfterExec();
}
/** instance decls **/
@ -144,17 +144,18 @@ public class T7093325 {
this.stmts = stmts;
}
void compileAndCheck() throws Exception {
@Override
public void run() {
int id = checkCount.incrementAndGet();
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavaSource source = new JavaSource();
JavacTask ct = (JavacTask)tool.getTask(null, fm, null,
JavaSource source = new JavaSource(id);
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), null,
null, null, Arrays.asList(source));
ct.call();
verifyBytecode(source);
verifyBytecode(source, id);
}
void verifyBytecode(JavaSource source) {
checkCount++;
void verifyBytecode(JavaSource source, int id) {
boolean lastInlined = false;
boolean hasCode = false;
int gapsCount = 0;
@ -172,11 +173,12 @@ public class T7093325 {
//System.out.printf("gaps %d \n %s \n", gapsCount, source.toString());
File compiledTest = new File("Test.class");
File compiledTest = new File(String.format("Test%s.class", id));
try {
ClassFile cf = ClassFile.read(compiledTest);
if (cf == null) {
throw new Error("Classfile not found: " + compiledTest.getName());
throw new Error("Classfile not found: " +
compiledTest.getName());
}
Method test_method = null;
@ -232,7 +234,7 @@ public class T7093325 {
"class C extends RuntimeException {} \n" +
"class D extends RuntimeException {} \n" +
"class E extends RuntimeException {} \n" +
"class Test {\n" +
"class Test#ID {\n" +
" void test() {\n" +
" try { #S0 } #C finally { System.out.println(); }\n" +
" }\n" +
@ -240,10 +242,12 @@ public class T7093325 {
String source;
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
public JavaSource(int id) {
super(URI.create(String.format("myfo:/Test%s.java", id)),
JavaFileObject.Kind.SOURCE);
source = source_template.replace("#C", ca.catchers());
source = source.replace("#S0", stmts[0].stmt);
source = source.replace("#ID", String.valueOf(id));
for (int i = 1; i < ca.ordinal() + 1; i++) {
source = source.replace("#S" + i, stmts[i].stmt);
}
@ -259,4 +263,5 @@ public class T7093325 {
return source;
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,23 +25,26 @@
* @test
* @bug 8002099
* @summary Add support for intersection types in cast expression
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main/timeout=360 IntersectionTypeCastTest
*/
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class IntersectionTypeCastTest {
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
static int checkCount = 0;
public class IntersectionTypeCastTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
interface Type {
boolean subtypeOf(Type that);
@ -59,7 +62,8 @@ public class IntersectionTypeCastTest {
String typeStr;
InterfaceKind superInterface;
InterfaceKind(String declStr, String typeStr, InterfaceKind superInterface) {
InterfaceKind(String declStr, String typeStr,
InterfaceKind superInterface) {
this.declStr = declStr;
this.typeStr = typeStr;
this.superInterface = superInterface;
@ -67,7 +71,8 @@ public class IntersectionTypeCastTest {
@Override
public boolean subtypeOf(Type that) {
return this == that || superInterface == that || that == ClassKind.OBJECT;
return this == that || superInterface == that ||
that == ClassKind.OBJECT;
}
@Override
@ -88,19 +93,27 @@ public class IntersectionTypeCastTest {
enum ClassKind implements Type {
OBJECT(null, "Object"),
CA("#M class CA implements A { }\n", "CA", InterfaceKind.A),
CB("#M class CB implements B { }\n", "CB", InterfaceKind.B),
CAB("#M class CAB implements A, B { }\n", "CAB", InterfaceKind.A, InterfaceKind.B),
CC("#M class CC implements C { }\n", "CC", InterfaceKind.C, InterfaceKind.A),
CCA("#M class CCA implements C, A { }\n", "CCA", InterfaceKind.C, InterfaceKind.A),
CCB("#M class CCB implements C, B { }\n", "CCB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
CCAB("#M class CCAB implements C, A, B { }\n", "CCAB", InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
CA("#M class CA implements A { }\n", "CA",
InterfaceKind.A),
CB("#M class CB implements B { }\n", "CB",
InterfaceKind.B),
CAB("#M class CAB implements A, B { }\n", "CAB",
InterfaceKind.A, InterfaceKind.B),
CC("#M class CC implements C { }\n", "CC",
InterfaceKind.C, InterfaceKind.A),
CCA("#M class CCA implements C, A { }\n", "CCA",
InterfaceKind.C, InterfaceKind.A),
CCB("#M class CCB implements C, B { }\n", "CCB",
InterfaceKind.C, InterfaceKind.A, InterfaceKind.B),
CCAB("#M class CCAB implements C, A, B { }\n", "CCAB",
InterfaceKind.C, InterfaceKind.A, InterfaceKind.B);
String declTemplate;
String typeStr;
List<InterfaceKind> superInterfaces;
ClassKind(String declTemplate, String typeStr, InterfaceKind... superInterfaces) {
ClassKind(String declTemplate, String typeStr,
InterfaceKind... superInterfaces) {
this.declTemplate = declTemplate;
this.typeStr = typeStr;
this.superInterfaces = List.from(superInterfaces);
@ -114,7 +127,8 @@ public class IntersectionTypeCastTest {
@Override
public boolean subtypeOf(Type that) {
return this == that || superInterfaces.contains(that) || that == OBJECT;
return this == that || superInterfaces.contains(that) ||
that == OBJECT;
}
@Override
@ -170,9 +184,11 @@ public class IntersectionTypeCastTest {
}
String getCast() {
String temp = kind.castTemplate.replaceAll("#C", types[0].asString());
String temp = kind.castTemplate.replaceAll("#C",
types[0].asString());
for (int i = 0; i < kind.interfaceBounds ; i++) {
temp = temp.replace(String.format("#I%d", i), types[i + 1].asString());
temp = temp.replace(String.format("#I%d", i),
types[i + 1].asString());
}
return temp;
}
@ -195,7 +211,8 @@ public class IntersectionTypeCastTest {
t1.subtypeOf(t2) ||
t2.subtypeOf(t1) ||
(t1.isInterface() && t2.isInterface()) || //side-cast (1)
(mod == ModifierKind.NONE && (t1.isInterface() != t2.isInterface())); //side-cast (2)
(mod == ModifierKind.NONE &&
(t1.isInterface() != t2.isInterface())); //side-cast (2)
if (!compat) return false;
}
}
@ -204,18 +221,15 @@ public class IntersectionTypeCastTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (ModifierKind mod : ModifierKind.values()) {
for (CastInfo cast1 : allCastInfo()) {
for (CastInfo cast2 : allCastInfo()) {
new IntersectionTypeCastTest(mod, cast1, cast2).run(comp, fm);
pool.execute(
new IntersectionTypeCastTest(mod, cast1, cast2));
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
static List<CastInfo> allCastInfo() {
@ -235,11 +249,14 @@ public class IntersectionTypeCastTest {
} else {
for (InterfaceKind intf2 : InterfaceKind.values()) {
if (kind.interfaceBounds == 2) {
buf.append(new CastInfo(kind, clazz, intf1, intf2));
buf.append(
new CastInfo(kind, clazz, intf1, intf2));
continue;
} else {
for (InterfaceKind intf3 : InterfaceKind.values()) {
buf.append(new CastInfo(kind, clazz, intf1, intf2, intf3));
buf.append(
new CastInfo(kind, clazz, intf1,
intf2, intf3));
continue;
}
}
@ -265,6 +282,22 @@ public class IntersectionTypeCastTest {
this.diagChecker = new DiagnosticChecker();
}
@Override
public void run() {
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
Arrays.asList("-XDallowIntersectionTypes"),
null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" +
source.getCharContent(true));
}
check();
}
class JavaSource extends SimpleJavaFileObject {
String bodyTemplate = "class Test {\n" +
@ -282,7 +315,8 @@ public class IntersectionTypeCastTest {
for (InterfaceKind ik : InterfaceKind.values()) {
source += ik.declStr;
}
source += bodyTemplate.replaceAll("#C1", cast1.getCast()).replaceAll("#C2", cast2.getCast());
source += bodyTemplate.replaceAll("#C1", cast1.getCast()).
replaceAll("#C2", cast2.getCast());
}
@Override
@ -291,21 +325,11 @@ public class IntersectionTypeCastTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
Arrays.asList("-XDallowIntersectionTypes"), null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
boolean errorExpected = cast1.hasDuplicateTypes() || cast2.hasDuplicateTypes();
boolean errorExpected = cast1.hasDuplicateTypes() ||
cast2.hasDuplicateTypes();
errorExpected |= !cast2.compatibleWith(mod, cast1);
@ -317,7 +341,8 @@ public class IntersectionTypeCastTest {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
@ -327,4 +352,5 @@ public class IntersectionTypeCastTest {
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,25 +24,25 @@
/*
* @test
* @summary Automatic test for checking correctness of default super/this resolution
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main TestDefaultSuperCall
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class TestDefaultSuperCall {
import com.sun.source.util.JavacTask;
static int checkCount = 0;
public class TestDefaultSuperCall
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum InterfaceKind {
DEFAULT("interface A extends B { default void m() { } }"),
@ -212,7 +212,7 @@ public class TestDefaultSuperCall {
List<String> elementsWithMethod;
Shape(ElementKind... elements) {
System.err.println("elements = " + Arrays.toString(elements));
errWriter.println("elements = " + Arrays.toString(elements));
enclosingElements = new ArrayList<>();
enclosingNames = new ArrayList<>();
elementsWithMethod = new ArrayList<>();
@ -231,28 +231,26 @@ public class TestDefaultSuperCall {
elementsWithMethod.add(prevName);
}
String element = ek.templateDecl.replaceAll("#N", name);
shapeStr = shapeStr == null ? element : shapeStr.replaceAll("#B", element);
shapeStr = shapeStr ==
null ? element : shapeStr.replaceAll("#B", element);
prevName = name;
}
}
String getShape(QualifierKind qk, ExprKind ek) {
String methName = ek == ExprKind.THIS ? "test" : "m";
String call = qk.getQualifier(this) + "." + ek.exprStr + "." + methName + "();";
String call = qk.getQualifier(this) + "." +
ek.exprStr + "." + methName + "();";
return shapeStr.replaceAll("#B", call);
}
String enclosingAt(int index) {
return index < enclosingNames.size() ? enclosingNames.get(index) : "BAD";
return index < enclosingNames.size() ?
enclosingNames.get(index) : "BAD";
}
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (InterfaceKind ik : InterfaceKind.values()) {
for (PruneKind pk : PruneKind.values()) {
for (ElementKind ek1 : ElementKind.values()) {
@ -264,10 +262,14 @@ public class TestDefaultSuperCall {
for (ElementKind ek4 : ElementKind.values()) {
if (!ek4.isAllowedEnclosing(ek3, false)) continue;
for (ElementKind ek5 : ElementKind.values()) {
if (!ek5.isAllowedEnclosing(ek4, false) || ek5.isClassDecl()) continue;
if (!ek5.isAllowedEnclosing(ek4, false) ||
ek5.isClassDecl()) continue;
for (QualifierKind qk : QualifierKind.values()) {
for (ExprKind ek : ExprKind.values()) {
new TestDefaultSuperCall(ik, pk, new Shape(ek1, ek2, ek3, ek4, ek5), qk, ek).run(comp, fm);
pool.execute(
new TestDefaultSuperCall(ik, pk,
new Shape(ek1, ek2, ek3,
ek4, ek5), qk, ek));
}
}
}
@ -277,7 +279,8 @@ public class TestDefaultSuperCall {
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
InterfaceKind ik;
@ -288,7 +291,8 @@ public class TestDefaultSuperCall {
JavaSource source;
DiagnosticChecker diagChecker;
TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh, QualifierKind qk, ExprKind ek) {
TestDefaultSuperCall(InterfaceKind ik, PruneKind pk, Shape sh,
QualifierKind qk, ExprKind ek) {
this.ik = ik;
this.pk = pk;
this.sh = sh;
@ -321,13 +325,14 @@ public class TestDefaultSuperCall {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true));
processException(ex);
return;
}
check();
}
@ -370,7 +375,8 @@ public class TestDefaultSuperCall {
int lastIdx = sh.enclosingElements.size() - 1;
boolean found = lastIdx == -1 ? false :
sh.enclosingElements.get(lastIdx).hasSuper() && qk.allowSuperCall(ik, pk);
sh.enclosingElements.get(lastIdx).hasSuper() &&
qk.allowSuperCall(ik, pk);
errorExpected |= !found;
if (!found) {
@ -378,9 +384,10 @@ public class TestDefaultSuperCall {
}
}
checkCount++;
checkCount.incrementAndGet();
if (diagChecker.errorFound != errorExpected) {
throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) +
throw new AssertionError("Problem when compiling source:\n" +
source.getCharContent(true) +
"\nenclosingElems: " + sh.enclosingElements +
"\nenclosingNames: " + sh.enclosingNames +
"\nelementsWithMethod: " + sh.elementsWithMethod +
@ -392,15 +399,17 @@ public class TestDefaultSuperCall {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
System.err.println(diagnostic.getMessage(Locale.getDefault()));
errWriter.println(diagnostic.getMessage(Locale.getDefault()));
errorFound = true;
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -21,7 +21,15 @@
* questions.
*/
import com.sun.source.util.TaskEvent;
/*
* @test
* @bug 6970584
* @summary assorted position errors in compiler syntax trees
* @library ../lib
* @build JavacTestingAbstractThreadedTest
* @run main CheckAttributedTree -q -r -et ERRONEOUS .
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
@ -34,6 +42,20 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
@ -49,23 +71,14 @@ import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.EndPosTable;
@ -76,11 +89,6 @@ import com.sun.tools.javac.tree.TreeInfo;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Pair;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.lang.model.element.Element;
import static com.sun.tools.javac.tree.JCTree.Tag.*;
/**
@ -95,13 +103,7 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*;
* covering any new language features that may be tested in this test suite.
*/
/*
* @test
* @bug 6970584
* @summary assorted position errors in compiler syntax trees
* @run main CheckAttributedTree -q -r -et ERRONEOUS .
*/
public class CheckAttributedTree {
public class CheckAttributedTree extends JavacTestingAbstractThreadedTest {
/**
* Main entry point.
* If test.src is set, program runs in jtreg mode, and will throw an Error
@ -110,9 +112,10 @@ public class CheckAttributedTree {
* args is the value of ${test.src}. In jtreg mode, the -r option can be
* given to change the default base directory to the root test directory.
*/
public static void main(String... args) {
public static void main(String... args) throws Exception {
String testSrc = System.getProperty("test.src");
File baseDir = (testSrc == null) ? null : new File(testSrc);
throwAssertionOnError = false;
boolean ok = new CheckAttributedTree().run(baseDir, args);
if (!ok) {
if (testSrc != null) // jtreg mode
@ -130,7 +133,7 @@ public class CheckAttributedTree {
* @param args command line args
* @return true if successful or in gui mode
*/
boolean run(File baseDir, String... args) {
boolean run(File baseDir, String... args) throws Exception {
if (args.length == 0) {
usage(System.out);
return true;
@ -145,8 +148,10 @@ public class CheckAttributedTree {
gui = true;
else if (arg.equals("-q"))
quiet = true;
else if (arg.equals("-v"))
else if (arg.equals("-v")) {
verbose = true;
printAll = true;
}
else if (arg.equals("-t") && i + 1 < args.length)
tags.add(args[++i]);
else if (arg.equals("-ef") && i + 1 < args.length)
@ -179,12 +184,11 @@ public class CheckAttributedTree {
error("File not found: " + file);
}
if (fileCount != 1)
System.err.println(fileCount + " files read");
if (errors > 0)
System.err.println(errors + " errors");
if (fileCount.get() != 1)
errWriter.println(fileCount + " files read");
checkAfterExec(false);
return (gui || errors == 0);
return (gui || errCount.get() == 0);
}
/**
@ -215,7 +219,7 @@ public class CheckAttributedTree {
* for java files.
* @param file the file or directory to test
*/
void test(File file) {
void test(final File file) {
if (excludeFiles.contains(file)) {
if (!quiet)
error("File " + file + " excluded");
@ -230,20 +234,24 @@ public class CheckAttributedTree {
}
if (file.isFile() && file.getName().endsWith(".java")) {
try {
if (verbose)
System.err.println(file);
fileCount++;
NPETester p = new NPETester();
p.test(read(file));
} catch (AttributionException e) {
if (!quiet) {
error("Error attributing " + file + "\n" + e.getMessage());
pool.execute(new Runnable() {
@Override
public void run() {
try {
if (verbose)
errWriter.println(file);
fileCount.incrementAndGet();
NPETester p = new NPETester();
p.test(read(file));
} catch (AttributionException e) {
if (!quiet) {
error("Error attributing " + file + "\n" + e.getMessage());
}
} catch (IOException e) {
error("Error reading " + file + ": " + e);
}
}
} catch (IOException e) {
error("Error reading " + file + ": " + e);
}
return;
});
}
if (!quiet)
@ -254,8 +262,6 @@ public class CheckAttributedTree {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
Reporter r = new Reporter(pw);
JavacTool tool = JavacTool.create();
StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null);
/**
* Read a file.
@ -265,11 +271,10 @@ public class CheckAttributedTree {
* @throws TreePosTest.ParseException if any errors occur while parsing the file
*/
List<Pair<JCCompilationUnit, JCTree>> read(File file) throws IOException, AttributionException {
JavacTool tool = JavacTool.create();
r.errors = 0;
Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(file);
Iterable<? extends JavaFileObject> files = fm.get().getJavaFileObjects(file);
String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" };
JavacTask task = tool.getTask(pw, fm, r, Arrays.asList(opts), null, files);
JavacTask task = (JavacTask)comp.getTask(pw, fm.get(), r, Arrays.asList(opts), null, files);
final List<Element> analyzedElems = new ArrayList<>();
task.setTaskListener(new TaskListener() {
public void started(TaskEvent e) {
@ -308,13 +313,9 @@ public class CheckAttributedTree {
*/
void error(String msg) {
System.err.println(msg);
errors++;
errCount.incrementAndGet();
}
/** Number of files that have been analyzed. */
int fileCount;
/** Number of errors reported. */
int errors;
/** Flag: don't report irrelevant files. */
boolean quiet;
/** Flag: show errors in GUI viewer. */
@ -385,7 +386,8 @@ public class CheckAttributedTree {
viewer = new Viewer();
viewer.addEntry(sourcefile, label, encl, self);
}
error(label + self.toString() + " encl: " + encl.toString() + " in file: " + sourcefile + " " + self.tree);
error(label + self.toString() + " encl: " + encl.toString() +
" in file: " + sourcefile + " " + self.tree);
}
}
@ -754,4 +756,8 @@ public class CheckAttributedTree {
final Info self;
}
}
/** Number of files that have been analyzed. */
static AtomicInteger fileCount = new AtomicInteger();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,21 +25,21 @@
* @test
* @bug 7046778
* @summary Project Coin: problem with diamond and member inner classes
* @library ../../../lib
* @build JavacTestingAbstractThreadedTest
* @run main DiamondAndInnerClassTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class DiamondAndInnerClassTest {
static int checkCount = 0;
public class DiamondAndInnerClassTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum TypeArgumentKind {
NONE(""),
@ -151,11 +151,6 @@ public class DiamondAndInnerClassTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (InnerClassDeclArity innerClassDeclArity : InnerClassDeclArity.values()) {
for (TypeQualifierArity declType : TypeQualifierArity.values()) {
if (!declType.matches(innerClassDeclArity)) continue;
@ -168,53 +163,79 @@ public class DiamondAndInnerClassTest {
//no diamond on decl site
if (taDecl1 == TypeArgumentKind.DIAMOND) continue;
for (TypeArgumentKind taSite1 : TypeArgumentKind.values()) {
boolean isSiteRaw = taSite1 == TypeArgumentKind.NONE;
boolean isSiteRaw =
taSite1 == TypeArgumentKind.NONE;
//diamond only allowed on the last type qualifier
if (taSite1 == TypeArgumentKind.DIAMOND &&
innerClassDeclArity != InnerClassDeclArity.ONE) continue;
innerClassDeclArity !=
InnerClassDeclArity.ONE)
continue;
for (ArgumentKind arg1 : ArgumentKind.values()) {
if (innerClassDeclArity == innerClassDeclArity.ONE) {
new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
argList, new TypeArgumentKind[] {taDecl1},
new TypeArgumentKind[] {taSite1}, new ArgumentKind[] {arg1}).run(comp, fm);
pool.execute(
new DiamondAndInnerClassTest(
innerClassDeclArity, declType,
newClassType, argList,
new TypeArgumentKind[] {taDecl1},
new TypeArgumentKind[] {taSite1},
new ArgumentKind[] {arg1}));
continue;
}
for (TypeArgumentKind taDecl2 : TypeArgumentKind.values()) {
//no rare types
if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE)) continue;
if (isDeclRaw != (taDecl2 == TypeArgumentKind.NONE))
continue;
//no diamond on decl site
if (taDecl2 == TypeArgumentKind.DIAMOND) continue;
if (taDecl2 == TypeArgumentKind.DIAMOND)
continue;
for (TypeArgumentKind taSite2 : TypeArgumentKind.values()) {
//no rare types
if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE)) continue;
if (isSiteRaw != (taSite2 == TypeArgumentKind.NONE))
continue;
//diamond only allowed on the last type qualifier
if (taSite2 == TypeArgumentKind.DIAMOND &&
innerClassDeclArity != InnerClassDeclArity.TWO) continue;
innerClassDeclArity != InnerClassDeclArity.TWO)
continue;
for (ArgumentKind arg2 : ArgumentKind.values()) {
if (innerClassDeclArity == innerClassDeclArity.TWO) {
new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
argList, new TypeArgumentKind[] {taDecl1, taDecl2},
pool.execute(
new DiamondAndInnerClassTest(
innerClassDeclArity,
declType,
newClassType,
argList,
new TypeArgumentKind[] {taDecl1, taDecl2},
new TypeArgumentKind[] {taSite1, taSite2},
new ArgumentKind[] {arg1, arg2}).run(comp, fm);
new ArgumentKind[] {arg1, arg2}));
continue;
}
for (TypeArgumentKind taDecl3 : TypeArgumentKind.values()) {
//no rare types
if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE)) continue;
if (isDeclRaw != (taDecl3 == TypeArgumentKind.NONE))
continue;
//no diamond on decl site
if (taDecl3 == TypeArgumentKind.DIAMOND) continue;
if (taDecl3 == TypeArgumentKind.DIAMOND)
continue;
for (TypeArgumentKind taSite3 : TypeArgumentKind.values()) {
//no rare types
if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE)) continue;
if (isSiteRaw != (taSite3 == TypeArgumentKind.NONE))
continue;
//diamond only allowed on the last type qualifier
if (taSite3 == TypeArgumentKind.DIAMOND &&
innerClassDeclArity != InnerClassDeclArity.THREE) continue;
innerClassDeclArity != InnerClassDeclArity.THREE)
continue;
for (ArgumentKind arg3 : ArgumentKind.values()) {
if (innerClassDeclArity == innerClassDeclArity.THREE) {
new DiamondAndInnerClassTest(innerClassDeclArity, declType, newClassType,
argList, new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3},
if (innerClassDeclArity ==
innerClassDeclArity.THREE) {
pool.execute(
new DiamondAndInnerClassTest(
innerClassDeclArity,
declType,
newClassType,
argList,
new TypeArgumentKind[] {taDecl1, taDecl2, taDecl3},
new TypeArgumentKind[] {taSite1, taSite2, taSite3},
new ArgumentKind[] {arg1, arg2, arg3}).run(comp, fm);
new ArgumentKind[] {arg1, arg2, arg3}));
continue;
}
}
@ -230,7 +251,8 @@ public class DiamondAndInnerClassTest {
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
InnerClassDeclArity innerClassDeclArity;
@ -244,9 +266,9 @@ public class DiamondAndInnerClassTest {
DiagnosticChecker diagChecker;
DiamondAndInnerClassTest(InnerClassDeclArity innerClassDeclArity,
TypeQualifierArity declType, TypeQualifierArity siteType, ArgumentListArity argList,
TypeArgumentKind[] declTypeArgumentKinds, TypeArgumentKind[] siteTypeArgumentKinds,
ArgumentKind[] argumentKinds) {
TypeQualifierArity declType, TypeQualifierArity siteType,
ArgumentListArity argList, TypeArgumentKind[] declTypeArgumentKinds,
TypeArgumentKind[] siteTypeArgumentKinds, ArgumentKind[] argumentKinds) {
this.innerClassDeclArity = innerClassDeclArity;
this.declType = declType;
this.siteType = siteType;
@ -267,9 +289,9 @@ public class DiamondAndInnerClassTest {
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = innerClassDeclArity.classDeclStr.replace("#B", bodyTemplate)
.replace("#D", declType.getType(declTypeArgumentKinds))
.replace("#S", siteType.getType(siteTypeArgumentKinds))
.replace("#AL", argList.getArgs(argumentKinds));
.replace("#D", declType.getType(declTypeArgumentKinds))
.replace("#S", siteType.getType(siteTypeArgumentKinds))
.replace("#AL", argList.getArgs(argumentKinds));
}
@Override
@ -278,36 +300,39 @@ public class DiamondAndInnerClassTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
@Override
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
throw new AssertionError("Error thrown when compiling the following code:\n" +
source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
boolean errorExpected = false;
TypeArgumentKind[] expectedArgKinds = new TypeArgumentKind[innerClassDeclArity.n];
TypeArgumentKind[] expectedArgKinds =
new TypeArgumentKind[innerClassDeclArity.n];
for (int i = 0 ; i < innerClassDeclArity.n ; i++) {
if (!declTypeArgumentKinds[i].compatible(siteTypeArgumentKinds[i])) {
errorExpected = true;
break;
}
expectedArgKinds[i] = siteTypeArgumentKinds[i] == TypeArgumentKind.DIAMOND ?
expectedArgKinds[i] = siteTypeArgumentKinds[i] ==
TypeArgumentKind.DIAMOND ?
declTypeArgumentKinds[i] : siteTypeArgumentKinds[i];
}
if (!errorExpected) {
for (int i = 0 ; i < innerClassDeclArity.n ; i++) {
//System.out.println("check " + expectedArgKinds[i] + " against " + argumentKinds[i]);
if (!expectedArgKinds[i].compatible(argumentKinds[i])) {
errorExpected = true;
break;
@ -323,7 +348,8 @@ public class DiamondAndInnerClassTest {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
@ -333,4 +359,5 @@ public class DiamondAndInnerClassTest {
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,22 +24,23 @@
/*
* @test
* @bug 7062745
* @summary Regression: difference in overload resolution when two methods are maximally specific
* @summary Regression: difference in overload resolution when two methods
* are maximally specific
* @library ../../../lib
* @build JavacTestingAbstractThreadedTest
* @run main GenericOverrideTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class GenericOverrideTest {
static int checkCount = 0;
public class GenericOverrideTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum SignatureKind {
NON_GENERIC(""),
@ -126,11 +127,6 @@ public class GenericOverrideTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (SignatureKind sig1 : SignatureKind.values()) {
for (ReturnTypeKind rt1 : ReturnTypeKind.values()) {
for (TypeArgumentKind ta1 : TypeArgumentKind.values()) {
@ -141,8 +137,12 @@ public class GenericOverrideTest {
if (!ta2.compatibleWith(sig2)) continue;
for (ReturnTypeKind rt3 : ReturnTypeKind.values()) {
for (TypeArgumentKind ta3 : TypeArgumentKind.values()) {
if (!ta3.compatibleWith(SignatureKind.NON_GENERIC)) continue;
new GenericOverrideTest(sig1, rt1, ta1, sig2, rt2, ta2, rt3, ta3).run(comp, fm);
if (!ta3.compatibleWith(SignatureKind.NON_GENERIC))
continue;
pool.execute(
new GenericOverrideTest(sig1,
rt1, ta1, sig2, rt2,
ta2, rt3, ta3));
}
}
}
@ -151,7 +151,8 @@ public class GenericOverrideTest {
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
SignatureKind sig1, sig2;
@ -161,7 +162,8 @@ public class GenericOverrideTest {
DiagnosticChecker diagChecker;
GenericOverrideTest(SignatureKind sig1, ReturnTypeKind rt1, TypeArgumentKind ta1,
SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2, ReturnTypeKind rt3, TypeArgumentKind ta3) {
SignatureKind sig2, ReturnTypeKind rt2, TypeArgumentKind ta2,
ReturnTypeKind rt3, TypeArgumentKind ta3) {
this.sig1 = sig1;
this.sig2 = sig2;
this.rt1 = rt1;
@ -204,19 +206,21 @@ public class GenericOverrideTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
@Override
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true));
throw new AssertionError("Error thrown when compiling the following code:\n" +
source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
boolean errorExpected = false;
int mostSpecific = 0;
@ -234,14 +238,17 @@ public class GenericOverrideTest {
//check that either TA1 <= TA2 or TA2 <= TA1 (unless most specific return found above is raw)
if (!errorExpected) {
if (ta1 != ta2) {
boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) || ta2.moreSpecificThan(ta1, true);
boolean useStrictCheck = ta1.moreSpecificThan(ta2, true) ||
ta2.moreSpecificThan(ta1, true);
if (!ta1.moreSpecificThan(ta2, useStrictCheck) &&
!ta2.moreSpecificThan(ta1, useStrictCheck)) {
errorExpected = true;
} else {
int mostSpecific2 = ta1.moreSpecificThan(ta2, useStrictCheck) ? 1 : 2;
if (mostSpecific != 0 && mostSpecific2 != mostSpecific) {
errorExpected = mostSpecific == 1 ? ta1 != TypeArgumentKind.NONE : ta2 != TypeArgumentKind.NONE;
errorExpected = mostSpecific == 1 ?
ta1 != TypeArgumentKind.NONE :
ta2 != TypeArgumentKind.NONE;
} else {
mostSpecific = mostSpecific2;
}
@ -273,7 +280,8 @@ public class GenericOverrideTest {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
@ -283,4 +291,5 @@ public class GenericOverrideTest {
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,20 +27,24 @@
* @summary Add lambda tests
* perform several automated checks in lambda conversion, esp. around accessibility
* @author Maurizio Cimadamore
* @library ../lib
* @build JavacTestingAbstractThreadedTest
* @run main FunctionalInterfaceConversionTest
*/
import com.sun.source.util.JavacTask;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class FunctionalInterfaceConversionTest {
public class FunctionalInterfaceConversionTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum PackageKind {
NO_PKG(""),
@ -139,8 +143,6 @@ public class FunctionalInterfaceConversionTest {
}
public static void main(String[] args) throws Exception {
final JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (PackageKind samPkg : PackageKind.values()) {
for (ModifierKind modKind : ModifierKind.values()) {
for (SamKind samKind : SamKind.values()) {
@ -150,8 +152,11 @@ public class FunctionalInterfaceConversionTest {
for (TypeKind argType : TypeKind.values()) {
for (TypeKind thrownType : TypeKind.values()) {
for (ExprKind exprKind : ExprKind.values()) {
new FunctionalInterfaceConversionTest(samPkg, modKind, samKind,
samMeth, clientMeth, retType, argType, thrownType, exprKind).test(comp, fm);
pool.execute(
new FunctionalInterfaceConversionTest(
samPkg, modKind, samKind,
samMeth, clientMeth, retType,
argType, thrownType, exprKind));
}
}
}
@ -161,6 +166,8 @@ public class FunctionalInterfaceConversionTest {
}
}
}
checkAfterExec(false);
}
PackageKind samPkg;
@ -175,24 +182,30 @@ public class FunctionalInterfaceConversionTest {
DiagnosticChecker dc;
SourceFile samSourceFile = new SourceFile("Sam.java", "#P \n #C") {
@Override
public String toString() {
return template.replaceAll("#P", samPkg.getPkgDecl()).
replaceAll("#C", samKind.getSam(samMeth.getMethod(retType, argType, thrownType)));
replaceAll("#C", samKind.getSam(
samMeth.getMethod(retType, argType, thrownType)));
}
};
SourceFile pkgClassSourceFile = new SourceFile("PackageClass.java",
"#P\n #M class PackageClass extends Exception { }") {
SourceFile pkgClassSourceFile =
new SourceFile("PackageClass.java",
"#P\n #M class PackageClass extends Exception { }") {
@Override
public String toString() {
return template.replaceAll("#P", samPkg.getPkgDecl()).
replaceAll("#M", modKind.modifier_str);
}
};
SourceFile clientSourceFile = new SourceFile("Client.java",
"#I\n abstract class Client { \n" +
" Sam s = #E;\n" +
" #M \n }") {
SourceFile clientSourceFile =
new SourceFile("Client.java",
"#I\n abstract class Client { \n" +
" Sam s = #E;\n" +
" #M \n }") {
@Override
public String toString() {
return template.replaceAll("#I", samPkg.getImportStat())
.replaceAll("#E", exprKind.exprStr)
@ -200,9 +213,10 @@ public class FunctionalInterfaceConversionTest {
}
};
FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind, SamKind samKind,
MethodKind samMeth, MethodKind clientMeth, TypeKind retType, TypeKind argType,
TypeKind thrownType, ExprKind exprKind) {
FunctionalInterfaceConversionTest(PackageKind samPkg, ModifierKind modKind,
SamKind samKind, MethodKind samMeth, MethodKind clientMeth,
TypeKind retType, TypeKind argType, TypeKind thrownType,
ExprKind exprKind) {
this.samPkg = samPkg;
this.modKind = modKind;
this.samKind = samKind;
@ -215,12 +229,20 @@ public class FunctionalInterfaceConversionTest {
this.dc = new DiagnosticChecker();
}
void test(JavaCompiler comp, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)comp.getTask(null, fm, dc,
null, null, Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
ct.analyze();
@Override
public void run() {
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), dc, null, null,
Arrays.asList(samSourceFile, pkgClassSourceFile, clientSourceFile));
try {
ct.analyze();
} catch (IOException ex) {
throw new AssertionError("Test failing with cause", ex.getCause());
}
if (dc.errorFound == checkSamConversion()) {
throw new AssertionError(samSourceFile + "\n\n" + pkgClassSourceFile + "\n\n" + clientSourceFile);
throw new AssertionError(samSourceFile + "\n\n" +
pkgClassSourceFile + "\n\n" + clientSourceFile);
}
}
@ -264,13 +286,16 @@ public class FunctionalInterfaceConversionTest {
return toString();
}
@Override
public abstract String toString();
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound = false;
@Override
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errorFound = true;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,21 +27,21 @@
* @bug 8003280
* @summary Add lambda tests
* Add parser support for lambda expressions
* @library ../lib
* @build JavacTestingAbstractThreadedTest
* @run main LambdaParserTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class LambdaParserTest {
static int checkCount = 0;
public class LambdaParserTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum LambdaKind {
NILARY_EXPR("()->x"),
@ -173,25 +173,26 @@ public class LambdaParserTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (LambdaKind lk : LambdaKind.values()) {
for (LambdaParameterKind pk1 : LambdaParameterKind.values()) {
if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) continue;
if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT)
continue;
for (LambdaParameterKind pk2 : LambdaParameterKind.values()) {
if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) continue;
if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT)
continue;
for (ModifierKind mk1 : ModifierKind.values()) {
if (mk1 != ModifierKind.NONE && lk.isShort()) continue;
if (lk.arity() < 1 && mk1 != ModifierKind.NONE) continue;
if (mk1 != ModifierKind.NONE && lk.isShort())
continue;
if (lk.arity() < 1 && mk1 != ModifierKind.NONE)
continue;
for (ModifierKind mk2 : ModifierKind.values()) {
if (lk.arity() < 2 && mk2 != ModifierKind.NONE) continue;
if (lk.arity() < 2 && mk2 != ModifierKind.NONE)
continue;
for (SubExprKind sk : SubExprKind.values()) {
for (ExprKind ek : ExprKind.values()) {
new LambdaParserTest(pk1, pk2, mk1, mk2, lk, sk, ek)
.run(comp, fm);
pool.execute(
new LambdaParserTest(pk1, pk2, mk1,
mk2, lk, sk, ek));
}
}
}
@ -199,7 +200,8 @@ public class LambdaParserTest {
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
LambdaParameterKind pk1;
@ -212,8 +214,9 @@ public class LambdaParserTest {
JavaSource source;
DiagnosticChecker diagChecker;
LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, ModifierKind mk1,
ModifierKind mk2, LambdaKind lk, SubExprKind sk, ExprKind ek) {
LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2,
ModifierKind mk1, ModifierKind mk2, LambdaKind lk,
SubExprKind sk, ExprKind ek) {
this.pk1 = pk1;
this.pk2 = pk2;
this.mk1 = mk1;
@ -235,7 +238,8 @@ public class LambdaParserTest {
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = template.replaceAll("#E", ek.expressionString(pk1, pk2, mk1, mk2, lk, sk));
source = template.replaceAll("#E",
ek.expressionString(pk1, pk2, mk1, mk2, lk, sk));
}
@Override
@ -244,19 +248,20 @@ public class LambdaParserTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
try {
ct.parse();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true));
processException(ex);
return;
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) ||
(lk.arity() > 1 && !mk2.compatibleWith(pk2));
@ -275,7 +280,8 @@ public class LambdaParserTest {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
@ -285,4 +291,5 @@ public class LambdaParserTest {
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,21 +27,21 @@
* @bug 8003280
* @summary Add lambda tests
* Add parser support for method references
* @library ../lib
* @build JavacTestingAbstractThreadedTest
* @run main MethodReferenceParserTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class MethodReferenceParserTest {
static int checkCount = 0;
public class MethodReferenceParserTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum ReferenceKind {
METHOD_REF("#Q::#Gm"),
@ -88,7 +88,8 @@ public class MethodReferenceParserTest {
this.contextTemplate = contextTemplate;
}
String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) {
String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk,
GenericKind gk, SubExprKind sk) {
return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk));
}
}
@ -165,25 +166,21 @@ public class MethodReferenceParserTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (ReferenceKind rk : ReferenceKind.values()) {
for (QualifierKind qk : QualifierKind.values()) {
for (GenericKind gk : GenericKind.values()) {
for (SubExprKind sk : SubExprKind.values()) {
for (ExprKind ek : ExprKind.values()) {
for (ContextKind ck : ContextKind.values()) {
new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck).run(comp, fm);
pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck));
}
}
}
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
ReferenceKind rk;
@ -227,19 +224,21 @@ public class MethodReferenceParserTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
@Override
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
try {
ct.parse();
} catch (Throwable ex) {
throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true));
processException(ex);
return;
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
if (diagChecker.errorFound != rk.erroneous()) {
throw new Error("invalid diagnostics for source:\n" +
@ -259,4 +258,5 @@ public class MethodReferenceParserTest {
}
}
}
}

@ -25,7 +25,7 @@ class TargetType21 {
<R,A> void call(SAM3<R,A> sam) { }
void test() {
call(x -> { throw new Exception(); }); //ok - resolves to call(SAM1)
call(x -> { throw new Exception(); }); //ambiguous
call(x -> { System.out.println(""); }); //ok - resolves to call(SAM2)
call(x -> { return (Object) null; }); //error - call(SAM3) is not applicable because of cyclic inference
call(x -> { return null; }); ////ok - resolves to call(SAM1)

@ -1,3 +1,3 @@
TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM2), TargetType21
TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @755,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
TargetType21.java:30:9: compiler.err.cant.apply.symbols: kindname.method, call, @737,{(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, call(TargetType21.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val)))),(compiler.misc.inapplicable.method: kindname.method, TargetType21, <R,A>call(TargetType21.SAM3<R,A>), (compiler.misc.cyclic.inference: A))}
2 errors

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,7 +28,9 @@
* @bug 8003280
* @summary Add lambda tests
* Add back-end support for invokedynamic
*
* @library ../lib
* @build JavacTestingAbstractThreadedTest
* @run main TestInvokeDynamic
*/
import com.sun.source.tree.MethodInvocationTree;
@ -66,7 +68,6 @@ import java.util.Locale;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
@ -74,69 +75,80 @@ import javax.tools.ToolProvider;
import static com.sun.tools.javac.jvm.ClassFile.*;
public class TestInvokeDynamic {
static int checkCount = 0;
public class TestInvokeDynamic
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum StaticArgumentKind {
STRING("Hello!", "String", "Ljava/lang/String;") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_String_info) &&
((CONSTANT_String_info)cpInfo).getString().equals(value);
((CONSTANT_String_info)cpInfo).getString()
.equals(value);
}
},
CLASS(null, "Class<?>", "Ljava/lang/Class;") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_Class_info) &&
((CONSTANT_Class_info)cpInfo).getName().equals("java/lang/String");
((CONSTANT_Class_info)cpInfo).getName()
.equals("java/lang/String");
}
},
INTEGER(1, "int", "I") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_Integer_info) &&
((CONSTANT_Integer_info)cpInfo).value == ((Integer)value).intValue();
((CONSTANT_Integer_info)cpInfo).value ==
((Integer)value).intValue();
}
},
LONG(1L, "long", "J") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_Long_info) &&
((CONSTANT_Long_info)cpInfo).value == ((Long)value).longValue();
((CONSTANT_Long_info)cpInfo).value ==
((Long)value).longValue();
}
},
FLOAT(1.0f, "float", "F") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_Float_info) &&
((CONSTANT_Float_info)cpInfo).value == ((Float)value).floatValue();
((CONSTANT_Float_info)cpInfo).value ==
((Float)value).floatValue();
}
},
DOUBLE(1.0, "double","D") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_Double_info) &&
((CONSTANT_Double_info)cpInfo).value == ((Double)value).doubleValue();
((CONSTANT_Double_info)cpInfo).value ==
((Double)value).doubleValue();
}
},
METHOD_HANDLE(null, "MethodHandle", "Ljava/lang/invoke/MethodHandle;") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
if (!(cpInfo instanceof CONSTANT_MethodHandle_info)) return false;
CONSTANT_MethodHandle_info handleInfo = (CONSTANT_MethodHandle_info)cpInfo;
if (!(cpInfo instanceof CONSTANT_MethodHandle_info))
return false;
CONSTANT_MethodHandle_info handleInfo =
(CONSTANT_MethodHandle_info)cpInfo;
return handleInfo.getCPRefInfo().getClassName().equals("Array") &&
handleInfo.reference_kind == RefKind.REF_invokeVirtual &&
handleInfo.getCPRefInfo().getNameAndTypeInfo().getName().equals("clone") &&
handleInfo.getCPRefInfo().getNameAndTypeInfo().getType().equals("()Ljava/lang/Object;");
handleInfo.getCPRefInfo()
.getNameAndTypeInfo().getName().equals("clone") &&
handleInfo.getCPRefInfo()
.getNameAndTypeInfo().getType().equals("()Ljava/lang/Object;");
}
},
METHOD_TYPE(null, "MethodType", "Ljava/lang/invoke/MethodType;") {
@Override
boolean check(CPInfo cpInfo) throws Exception {
return (cpInfo instanceof CONSTANT_MethodType_info) &&
((CONSTANT_MethodType_info)cpInfo).getType().equals("()Ljava/lang/Object;");
((CONSTANT_MethodType_info)cpInfo).getType()
.equals("()Ljava/lang/Object;");
}
};
@ -144,7 +156,8 @@ public class TestInvokeDynamic {
String sourceTypeStr;
String bytecodeTypeStr;
StaticArgumentKind(Object value, String sourceTypeStr, String bytecodeTypeStr) {
StaticArgumentKind(Object value, String sourceTypeStr,
String bytecodeTypeStr) {
this.value = value;
this.sourceTypeStr = sourceTypeStr;
this.bytecodeTypeStr = bytecodeTypeStr;
@ -163,7 +176,8 @@ public class TestInvokeDynamic {
case CLASS:
return syms.stringType.tsym;
case METHOD_HANDLE:
return new Pool.MethodHandle(REF_invokeVirtual, syms.arrayCloneMethod, types);
return new Pool.MethodHandle(REF_invokeVirtual,
syms.arrayCloneMethod, types);
case METHOD_TYPE:
return syms.arrayCloneMethod.type;
default:
@ -186,23 +200,21 @@ public class TestInvokeDynamic {
}
public static void main(String... args) throws Exception {
// Create a single file manager and compiler and reuse it for each compile to save time.
StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
for (StaticArgumentsArity arity : StaticArgumentsArity.values()) {
if (arity.arity == 0) {
new TestInvokeDynamic(arity).compileAndCheck(fm, tool);
pool.execute(new TestInvokeDynamic(arity));
} else {
for (StaticArgumentKind sak1 : StaticArgumentKind.values()) {
if (arity.arity == 1) {
new TestInvokeDynamic(arity, sak1).compileAndCheck(fm, tool);
pool.execute(new TestInvokeDynamic(arity, sak1));
} else {
for (StaticArgumentKind sak2 : StaticArgumentKind.values()) {
if (arity.arity == 2) {
new TestInvokeDynamic(arity, sak1, sak2).compileAndCheck(fm, tool);
pool.execute(new TestInvokeDynamic(arity, sak1, sak2));
} else {
for (StaticArgumentKind sak3 : StaticArgumentKind.values()) {
new TestInvokeDynamic(arity, sak1, sak2, sak3).compileAndCheck(fm, tool);
pool.execute(
new TestInvokeDynamic(arity, sak1, sak2, sak3));
}
}
}
@ -211,23 +223,23 @@ public class TestInvokeDynamic {
}
}
System.out.println("Total checks made: " + checkCount);
checkAfterExec();
}
StaticArgumentsArity arity;
StaticArgumentKind[] saks;
JavaSource source;
DiagChecker dc;
TestInvokeDynamic(StaticArgumentsArity arity, StaticArgumentKind... saks) {
this.arity = arity;
this.saks = saks;
source = new JavaSource();
dc = new DiagChecker();
}
void compileAndCheck(JavaFileManager fm, JavaCompiler tool) throws Exception {
JavacTaskImpl ct = (JavacTaskImpl)tool.getTask(null, fm, dc,
public void run() {
int id = checkCount.incrementAndGet();
JavaSource source = new JavaSource(id);
JavacTaskImpl ct = (JavacTaskImpl)comp.getTask(null, fm.get(), dc,
null, null, Arrays.asList(source));
Context context = ct.getContext();
Symtab syms = Symtab.instance(context);
@ -238,16 +250,20 @@ public class TestInvokeDynamic {
ct.generate();
} catch (Throwable t) {
t.printStackTrace();
throw new AssertionError(String.format("Error thrown when compiling following code\n%s", source.source));
throw new AssertionError(
String.format("Error thrown when compiling following code\n%s",
source.source));
}
if (dc.diagFound) {
throw new AssertionError(String.format("Diags found when compiling following code\n%s\n\n%s", source.source, dc.printDiags()));
throw new AssertionError(
String.format("Diags found when compiling following code\n%s\n\n%s",
source.source, dc.printDiags()));
}
verifyBytecode();
verifyBytecode(id);
}
void verifyBytecode() {
File compiledTest = new File("Test.class");
void verifyBytecode(int id) {
File compiledTest = new File(String.format("Test%d.class", id));
try {
ClassFile cf = ClassFile.read(compiledTest);
Method testMethod = null;
@ -260,7 +276,8 @@ public class TestInvokeDynamic {
if (testMethod == null) {
throw new Error("Test method not found");
}
Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
Code_attribute ea =
(Code_attribute)testMethod.attributes.get(Attribute.Code);
if (testMethod == null) {
throw new Error("Code attribute for test() method not found");
}
@ -270,10 +287,12 @@ public class TestInvokeDynamic {
for (Instruction i : ea.getInstructions()) {
if (i.getMnemonic().equals("invokedynamic")) {
CONSTANT_InvokeDynamic_info indyInfo =
(CONSTANT_InvokeDynamic_info)cf.constant_pool.get(i.getShort(1));
(CONSTANT_InvokeDynamic_info)cf
.constant_pool.get(i.getShort(1));
bsmIdx = indyInfo.bootstrap_method_attr_index;
if (!indyInfo.getNameAndTypeInfo().getType().equals("()V")) {
throw new AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
throw new
AssertionError("type mismatch for CONSTANT_InvokeDynamic_info");
}
}
}
@ -281,34 +300,41 @@ public class TestInvokeDynamic {
throw new Error("Missing invokedynamic in generated code");
}
BootstrapMethods_attribute bsm_attr = (BootstrapMethods_attribute)cf.getAttribute(Attribute.BootstrapMethods);
BootstrapMethods_attribute bsm_attr =
(BootstrapMethods_attribute)cf
.getAttribute(Attribute.BootstrapMethods);
if (bsm_attr.bootstrap_method_specifiers.length != 1) {
throw new Error("Bad number of method specifiers in BootstrapMethods attribute");
throw new Error("Bad number of method specifiers " +
"in BootstrapMethods attribute");
}
BootstrapMethods_attribute.BootstrapMethodSpecifier bsm_spec =
bsm_attr.bootstrap_method_specifiers[0];
if (bsm_spec.bootstrap_arguments.length != arity.arity) {
throw new Error("Bad number of static invokedynamic args in BootstrapMethod attribute");
throw new Error("Bad number of static invokedynamic args " +
"in BootstrapMethod attribute");
}
int count = 0;
for (StaticArgumentKind sak : saks) {
if (!sak.check(cf.constant_pool.get(bsm_spec.bootstrap_arguments[count]))) {
if (!sak.check(cf.constant_pool
.get(bsm_spec.bootstrap_arguments[count]))) {
throw new Error("Bad static argument value " + sak);
}
count++;
}
CONSTANT_MethodHandle_info bsm_handle =
(CONSTANT_MethodHandle_info)cf.constant_pool.get(bsm_spec.bootstrap_method_ref);
(CONSTANT_MethodHandle_info)cf.constant_pool
.get(bsm_spec.bootstrap_method_ref);
if (bsm_handle.reference_kind != RefKind.REF_invokeStatic) {
throw new Error("Bad kind on boostrap method handle");
}
CONSTANT_Methodref_info bsm_ref =
(CONSTANT_Methodref_info)cf.constant_pool.get(bsm_handle.reference_index);
(CONSTANT_Methodref_info)cf.constant_pool
.get(bsm_handle.reference_index);
if (!bsm_ref.getClassInfo().getName().equals("Bootstrap")) {
throw new Error("Bad owner of boostrap method");
@ -318,8 +344,11 @@ public class TestInvokeDynamic {
throw new Error("Bad boostrap method name");
}
if (!bsm_ref.getNameAndTypeInfo().getType().equals(asBSMSignatureString())) {
throw new Error("Bad boostrap method type" + bsm_ref.getNameAndTypeInfo().getType() + " " + asBSMSignatureString());
if (!bsm_ref.getNameAndTypeInfo()
.getType().equals(asBSMSignatureString())) {
throw new Error("Bad boostrap method type" +
bsm_ref.getNameAndTypeInfo().getType() + " " +
asBSMSignatureString());
}
} catch (Exception e) {
e.printStackTrace();
@ -341,20 +370,22 @@ public class TestInvokeDynamic {
static final String source_template = "import java.lang.invoke.*;\n" +
"class Bootstrap {\n" +
" public static CallSite bsm(MethodHandles.Lookup lookup, String name, MethodType methodType #SARGS) {\n" +
" public static CallSite bsm(MethodHandles.Lookup lookup, " +
"String name, MethodType methodType #SARGS) {\n" +
" return null;\n" +
" }\n" +
"}\n" +
"class Test {\n" +
"class Test#ID {\n" +
" void m() { }\n" +
" void test() { m(); }\n" +
"}";
String source;
JavaSource() {
JavaSource(int id) {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = source_template.replace("#SARGS", asSignatureString());
source = source_template.replace("#SARGS", asSignatureString())
.replace("#ID", String.valueOf(id));
}
@Override
@ -411,7 +442,8 @@ public class TestInvokeDynamic {
for (int i = 0; i < arity.arity ; i++) {
staticArgs[i] = saks[i].getValue(syms, names, types);
}
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name, oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
ident.sym = new Symbol.DynamicMethodSymbol(oldSym.name,
oldSym.owner, REF_invokeStatic, bsm, oldSym.type, staticArgs);
}
return null;
}
@ -426,7 +458,8 @@ public class TestInvokeDynamic {
}
}
static class DiagChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean diagFound;
ArrayList<String> diags = new ArrayList<>();
@ -445,4 +478,5 @@ public class TestInvokeDynamic {
return buf.toString();
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, 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,24 +26,23 @@
* @bug 8003280
* @summary Add lambda tests
* Automatic test for checking correctness of structural most specific test routine
* @run main/timeout=360 StructuralMostSpecificTest
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main/timeout=600 StructuralMostSpecificTest
*/
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.ClientCodeWrapper;
import com.sun.tools.javac.util.JCDiagnostic;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.ClientCodeWrapper;
import com.sun.tools.javac.util.JCDiagnostic;
public class StructuralMostSpecificTest {
static int checkCount = 0;
public class StructuralMostSpecificTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum RetTypeKind {
SHORT("short"),
@ -105,7 +104,7 @@ public class StructuralMostSpecificTest {
VOID("return;"),
SHORT("return (short)0;"),
INT("return 0;"),
INTEGER("return (Integer)null"),
INTEGER("return (Integer)null;"),
NULL("return null;");
String retStr;
@ -142,11 +141,6 @@ public class StructuralMostSpecificTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (LambdaReturnKind lrk : LambdaReturnKind.values()) {
for (RetTypeKind rk1 : RetTypeKind.values()) {
for (RetTypeKind rk2 : RetTypeKind.values()) {
@ -154,7 +148,9 @@ public class StructuralMostSpecificTest {
for (ExceptionKind ek2 : ExceptionKind.values()) {
for (ArgTypeKind ak11 : ArgTypeKind.values()) {
for (ArgTypeKind ak12 : ArgTypeKind.values()) {
new StructuralMostSpecificTest(lrk, rk1, rk2, ek1, ek2, ak11, ak12).run(comp, fm);
pool.execute(
new StructuralMostSpecificTest(lrk, rk1,
rk2, ek1, ek2, ak11, ak12));
}
}
}
@ -162,7 +158,8 @@ public class StructuralMostSpecificTest {
}
}
}
System.out.println("Total check executed: " + checkCount);
checkAfterExec();
}
LambdaReturnKind lrk;
@ -218,20 +215,22 @@ public class StructuralMostSpecificTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
Arrays.asList("-XDverboseResolution=all,-predef,-internal,-object-init"),
null, Arrays.asList(source));
try {
ct.analyze();
} catch (Throwable ex) {
throw new AssertionError("Error thron when analyzing the following source:\n" + source.getCharContent(true));
throw new
AssertionError("Error thron when analyzing the following source:\n" +
source.getCharContent(true));
}
check();
}
void check() {
checkCount++;
checkCount.incrementAndGet();
if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2))
return;
@ -265,8 +264,8 @@ public class StructuralMostSpecificTest {
}
}
boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, ExceptionKind ek2,
ArgTypeKind ak1, ArgTypeKind ak2) {
boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1,
ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) {
if (!rk1.moreSpecificThan(rk2))
return false;
@ -276,7 +275,8 @@ public class StructuralMostSpecificTest {
return true;
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean ambiguityFound;
String mostSpecificSig;
@ -287,12 +287,16 @@ public class StructuralMostSpecificTest {
diagnostic.getCode().equals("compiler.err.ref.ambiguous")) {
ambiguityFound = true;
} else if (diagnostic.getKind() == Diagnostic.Kind.NOTE &&
diagnostic.getCode().equals("compiler.note.verbose.resolve.multi")) {
diagnostic.getCode()
.equals("compiler.note.verbose.resolve.multi")) {
ClientCodeWrapper.DiagnosticSourceUnwrapper dsu =
(ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
JCDiagnostic.MultilineDiagnostic mdiag = (JCDiagnostic.MultilineDiagnostic)dsu.d;
(ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic;
JCDiagnostic.MultilineDiagnostic mdiag =
(JCDiagnostic.MultilineDiagnostic)dsu.d;
int mostSpecificIndex = (Integer)mdiag.getArgs()[2];
mostSpecificSig = ((JCDiagnostic)mdiag.getSubdiagnostics().get(mostSpecificIndex)).getArgs()[1].toString();
mostSpecificSig =
((JCDiagnostic)mdiag.getSubdiagnostics()
.get(mostSpecificIndex)).getArgs()[1].toString();
}
} catch (RuntimeException t) {
t.printStackTrace();
@ -300,4 +304,5 @@ public class StructuralMostSpecificTest {
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,22 +25,24 @@
* @test
* @bug 8003280
* @summary Add lambda tests
* perform automated checks in type inference in lambda expressions in different contexts
* perform automated checks in type inference in lambda expressions
* in different contexts
* @library ../../../lib
* @build JavacTestingAbstractThreadedTest
* @compile TypeInferenceComboTest.java
* @run main/timeout=360 TypeInferenceComboTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import javax.tools.StandardJavaFileManager;
import com.sun.source.util.JavacTask;
public class TypeInferenceComboTest {
public class TypeInferenceComboTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum Context {
ASSIGNMENT("SAM#Type s = #LBody;"),
METHOD_CALL("#GenericDeclKind void method1(SAM#Type s) { }\n" +
@ -59,27 +61,35 @@ public class TypeInferenceComboTest {
this.context = context;
}
String getContext(SamKind sk, TypeKind samTargetT, Keyword kw, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
String getContext(SamKind sk, TypeKind samTargetT, Keyword kw,
TypeKind parameterT, TypeKind returnT, LambdaKind lk,
ParameterKind pk, GenericDeclKind gdk, LambdaBody lb) {
String result = context;
if (sk == SamKind.GENERIC) {
if(this == Context.METHOD_CALL) {
result = result.replaceAll("#GenericDeclKind", gdk.getGenericDeclKind(samTargetT));
result = result.replaceAll("#GenericDeclKind",
gdk.getGenericDeclKind(samTargetT));
if(gdk == GenericDeclKind.NON_GENERIC)
result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
result = result.replaceAll("#Type", "<" +
samTargetT.typeStr + ">");
else //#GenericDeclKind is <T> or <T extends xxx>
result = result.replaceAll("#Type", "<T>");
}
else {
if(kw == Keyword.VOID)
result = result.replaceAll("#Type", "<" + samTargetT.typeStr + ">");
result = result.replaceAll("#Type", "<" +
samTargetT.typeStr + ">");
else
result = result.replaceAll("#Type", "<? " + kw.keyStr + " " + samTargetT.typeStr + ">");
result = result.replaceAll("#Type", "<? " + kw.keyStr +
" " + samTargetT.typeStr + ">");
}
}
else
result = result.replaceAll("#Type", "").replaceAll("#GenericDeclKind", "");
result = result.replaceAll("#Type", "").
replaceAll("#GenericDeclKind", "");
return result.replaceAll("#LBody", lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
return result.replaceAll("#LBody",
lb.getLambdaBody(samTargetT, parameterT, returnT, lk, pk));
}
}
@ -94,8 +104,10 @@ public class TypeInferenceComboTest {
}
String getSam(TypeKind parameterT, TypeKind returnT) {
return sam_str.replaceAll("#ARG", parameterT == TypeKind.VOID ? "" : parameterT.typeStr + " arg")
.replaceAll("#R", returnT.typeStr);
return sam_str.replaceAll("#ARG",
parameterT == TypeKind.VOID ?
"" : parameterT.typeStr + " arg")
.replaceAll("#R", returnT.typeStr);
}
}
@ -104,7 +116,8 @@ public class TypeInferenceComboTest {
STRING("String", "\"hello\""),
INTEGER("Integer", "1"),
INT("int", "0"),
COMPARATOR("java.util.Comparator<String>", "(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
COMPARATOR("java.util.Comparator<String>",
"(java.util.Comparator<String>)(a, b) -> a.length()-b.length()"),
SAM("SAM2", "null"),
GENERIC("T", null);
@ -152,8 +165,10 @@ public class TypeInferenceComboTest {
}
enum LambdaBody {
RETURN_VOID("() -> #RET"),//no parameters, return type is one of the TypeKind
RETURN_ARG("(#PK arg) -> #RET");//has parameters, return type is one of the TypeKind
//no parameters, return type is one of the TypeKind
RETURN_VOID("() -> #RET"),
//has parameters, return type is one of the TypeKind
RETURN_ARG("(#PK arg) -> #RET");
String bodyStr;
@ -161,12 +176,14 @@ public class TypeInferenceComboTest {
this.bodyStr = bodyStr;
}
String getLambdaBody(TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaKind lk, ParameterKind pk) {
String getLambdaBody(TypeKind samTargetT, TypeKind parameterT,
TypeKind returnT, LambdaKind lk, ParameterKind pk) {
String result = bodyStr.replaceAll("#PK", pk.paramTemplate);
if(result.contains("#TYPE")) {
if (parameterT == TypeKind.GENERIC && this != RETURN_VOID)
result = result.replaceAll("#TYPE", samTargetT == null? "": samTargetT.typeStr);
result = result.replaceAll("#TYPE",
samTargetT == null? "": samTargetT.typeStr);
else
result = result.replaceAll("#TYPE", parameterT.typeStr);
}
@ -174,9 +191,12 @@ public class TypeInferenceComboTest {
return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", "arg"));
else {
if(returnT != TypeKind.GENERIC)
return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", (returnT==TypeKind.VOID && lk==LambdaKind.EXPRESSION)? "{}" : returnT.valStr));
return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL",
(returnT==TypeKind.VOID &&
lk==LambdaKind.EXPRESSION) ? "{}" : returnT.valStr));
else
return result.replaceAll("#RET", lk.stmt.replaceAll("#VAL", samTargetT.valStr));
return result.replaceAll("#RET",
lk.stmt.replaceAll("#VAL", samTargetT.valStr));
}
}
}
@ -203,8 +223,10 @@ public class TypeInferenceComboTest {
}
else if (lambdaBodyType != LambdaBody.RETURN_ARG)
return false;
if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
if ( parameterType == TypeKind.GENERIC && parameterKind == ParameterKind.IMPLICIT) //cyclic inference
if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND ||
genericDeclKind == GenericDeclKind.GENERIC_BOUND ) {
if ( parameterType == TypeKind.GENERIC &&
parameterKind == ParameterKind.IMPLICIT) //cyclic inference
return false;
}
return true;
@ -216,7 +238,8 @@ public class TypeInferenceComboTest {
"}\n";
SourceFile samSourceFile = new SourceFile("Sam.java", templateStr) {
public String toString() {
return template.replaceAll("#C", samKind.getSam(parameterType, returnType));
return template.replaceAll("#C",
samKind.getSam(parameterType, returnType));
}
};
@ -225,22 +248,35 @@ public class TypeInferenceComboTest {
" #Context\n" +
"}") {
public String toString() {
return template.replaceAll("#Context", context.getContext(samKind, samTargetType, keyword, parameterType, returnType, lambdaKind, parameterKind, genericDeclKind, lambdaBodyType));
return template.replaceAll("#Context",
context.getContext(samKind, samTargetType, keyword,
parameterType, returnType, lambdaKind, parameterKind,
genericDeclKind, lambdaBodyType));
}
};
void test() throws Exception {
System.out.println("kk:");
public void run() {
outWriter.println("kk:");
StringBuilder sb = new StringBuilder("SamKind:");
sb.append(samKind).append(" SamTargetType:").append(samTargetType).append(" ParameterType:").append(parameterType)
.append(" ReturnType:").append(returnType).append(" Context:").append(context).append(" LambdaKind:").append(lambdaKind)
.append(" LambdaBodyType:").append(lambdaBodyType).append(" ParameterKind:").append(parameterKind).append(" Keyword:").append(keyword);
System.out.println(sb);
sb.append(samKind).append(" SamTargetType:")
.append(samTargetType).append(" ParameterType:").append(parameterType)
.append(" ReturnType:").append(returnType).append(" Context:")
.append(context).append(" LambdaKind:").append(lambdaKind)
.append(" LambdaBodyType:").append(lambdaBodyType)
.append(" ParameterKind:").append(parameterKind).append(" Keyword:")
.append(keyword);
outWriter.println(sb);
DiagnosticChecker dc = new DiagnosticChecker();
JavacTask ct = (JavacTask)comp.getTask(null, fm, dc, null, null, Arrays.asList(samSourceFile, clientSourceFile));
ct.analyze();
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), dc,
null, null, Arrays.asList(samSourceFile, clientSourceFile));
try {
ct.analyze();
} catch (Throwable t) {
processException(t);
}
if (dc.errorFound == checkTypeInference()) {
throw new AssertionError(samSourceFile + "\n\n" + clientSourceFile + "\n" + parameterType + " " + returnType);
throw new AssertionError(samSourceFile + "\n\n" +
clientSourceFile + "\n" + parameterType + " " + returnType);
}
}
@ -261,7 +297,8 @@ public class TypeInferenceComboTest {
public abstract String toString();
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound = false;
@ -283,10 +320,9 @@ public class TypeInferenceComboTest {
Keyword keyword;
GenericDeclKind genericDeclKind;
static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
static StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT, TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk, ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
TypeInferenceComboTest(SamKind sk, TypeKind samTargetT, TypeKind parameterT,
TypeKind returnT, LambdaBody lb, Context c, LambdaKind lk,
ParameterKind pk, Keyword kw, GenericDeclKind gdk) {
samKind = sk;
samTargetType = samTargetT;
parameterType = parameterT;
@ -308,24 +344,14 @@ public class TypeInferenceComboTest {
for(LambdaKind lambdaK : LambdaKind.values()) {
for (SamKind sk : SamKind.values()) {
if (sk == SamKind.NON_GENERIC) {
if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC )
new TypeInferenceComboTest(sk, null, parameterT, returnT, lb, ct, lambdaK, parameterK, null, null).test();
generateNonGenericSAM(ct, returnT,
parameterT, lb, parameterK,
lambdaK, sk);
}
else if (sk == SamKind.GENERIC) {
for (Keyword kw : Keyword.values()) {
for (TypeKind samTargetT : TypeKind.values()) {
if(samTargetT != TypeKind.VOID && samTargetT != TypeKind.INT && samTargetT != TypeKind.GENERIC
&& (parameterT == TypeKind.GENERIC || returnT == TypeKind.GENERIC)) {
if(ct != Context.METHOD_CALL) {
new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, null).test();
}
else {//Context.METHOD_CALL
for (GenericDeclKind gdk : GenericDeclKind.values())
new TypeInferenceComboTest(sk, samTargetT, parameterT, returnT, lb, ct, lambdaK, parameterK, kw, gdk).test();
}
}
}
}
generateGenericSAM(ct, returnT,
parameterT, lb, parameterK,
lambdaK, sk);
}
}
}
@ -334,5 +360,44 @@ public class TypeInferenceComboTest {
}
}
}
checkAfterExec(false);
}
static void generateNonGenericSAM(Context ct, TypeKind returnT,
TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
LambdaKind lambdaK, SamKind sk) {
if(parameterT != TypeKind.GENERIC && returnT != TypeKind.GENERIC ) {
pool.execute(new TypeInferenceComboTest(sk, null, parameterT,
returnT, lb, ct, lambdaK, parameterK, null, null));
}
}
static void generateGenericSAM(Context ct, TypeKind returnT,
TypeKind parameterT, LambdaBody lb, ParameterKind parameterK,
LambdaKind lambdaK, SamKind sk) {
for (Keyword kw : Keyword.values()) {
for (TypeKind samTargetT : TypeKind.values()) {
if(samTargetT != TypeKind.VOID &&
samTargetT != TypeKind.INT &&
samTargetT != TypeKind.GENERIC &&
(parameterT == TypeKind.GENERIC ||
returnT == TypeKind.GENERIC)) {
if(ct != Context.METHOD_CALL) {
pool.execute(
new TypeInferenceComboTest(sk, samTargetT, parameterT,
returnT, lb, ct, lambdaK, parameterK, kw, null));
} else {//Context.METHOD_CALL
for (GenericDeclKind gdk :
GenericDeclKind.values())
pool.execute(
new TypeInferenceComboTest(sk, samTargetT,
parameterT, returnT, lb, ct, lambdaK,
parameterK, kw, gdk));
}
}
}
}
}
}

@ -0,0 +1,142 @@
/*
* Copyright (c) 2010, 2013, 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.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
/**
* An abstract superclass for threaded tests.
*
* This class will try to read a property named test.concurrency.
* The property can be provided by passing this option to jtreg:
* -javaoption:-Dtest.concurrency=#
*
* If the property is not set the class will use a heuristic to determine the
* maximum number of threads that can be fired to execute a given test.
*/
public abstract class JavacTestingAbstractThreadedTest {
protected static int getThreadPoolSize() {
Integer testConc = Integer.getInteger("test.concurrency");
if (testConc != null) return testConc;
int cores = Runtime.getRuntime().availableProcessors();
return Math.max(2, Math.min(8, cores / 2));
}
protected static void checkAfterExec() throws InterruptedException {
checkAfterExec(true);
};
protected static boolean throwAssertionOnError = true;
protected static boolean printAll = false;
protected static StringWriter errSWriter = new StringWriter();
protected static PrintWriter errWriter = new PrintWriter(errSWriter);
protected static StringWriter outSWriter = new StringWriter();
protected static PrintWriter outWriter = new PrintWriter(outSWriter);
protected static void checkAfterExec(boolean printCheckCount)
throws InterruptedException {
pool.shutdown();
while (!pool.isTerminated()) {
Thread.sleep(10);
}
if (errCount.get() > 0) {
if (throwAssertionOnError) {
closePrinters();
System.err.println(errSWriter.toString());
throw new AssertionError(
String.format("%d errors found", errCount.get()));
} else {
System.err.println(
String.format("%d errors found", errCount.get()));
}
} else if (printCheckCount) {
outWriter.println("Total check executed: " + checkCount.get());
}
closePrinters();
if (printAll) {
System.out.println(errSWriter.toString());
System.out.println(outSWriter.toString());
}
}
protected static void closePrinters() {
errWriter.close();
outWriter.close();
}
protected static void processException(Throwable t) {
errCount.incrementAndGet();
t.printStackTrace(errWriter);
pool.shutdown();
}
//number of checks executed
protected static AtomicInteger checkCount = new AtomicInteger();
//number of errors found while running combo tests
protected static AtomicInteger errCount = new AtomicInteger();
//create default shared JavaCompiler - reused across multiple compilations
protected static JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
protected static ExecutorService pool = Executors.newFixedThreadPool(
getThreadPoolSize(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
pool.shutdown();
errCount.incrementAndGet();
e.printStackTrace(System.err);
}
});
return t;
}
});
/*
* File manager is not thread-safe so it cannot be re-used across multiple
* threads. However we cache per-thread FileManager to avoid excessive
* object creation
*/
protected static final ThreadLocal<StandardJavaFileManager> fm =
new ThreadLocal<StandardJavaFileManager>() {
@Override protected StandardJavaFileManager initialValue() {
return comp.getStandardFileManager(null, null, null);
}
};
}

@ -0,0 +1,70 @@
import java.io.PrintWriter;
import java.io.StringWriter;
/*
* Copyright (c) 2013, 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 8006037
* @summary extra space in javac -help for -J and @ options
*/
public class Option_J_At_Test {
public static void main(String... args) throws Exception {
new Option_J_At_Test().run();
}
void run() throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
String[] help = { "-help" };
int rc = com.sun.tools.javac.Main.compile(help, pw);
pw.flush();
String out = sw.toString();
System.out.println(out);
check(out, "-J<flag>", true);
check(out, "-J <flag>", false);
check(out, "@<filename>", true);
check(out, "@ <filename>", false);
if (errors > 0)
throw new Exception(errors + " errors found");
}
void check(String out, String text, boolean expect) {
if (out.contains(text) != expect) {
if (expect)
error("expected string not found: " + text);
else
error("unexpected string found: " + text);
}
}
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
int errors;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,19 +25,21 @@
* @test
* @bug 7030606
* @summary Project-coin: multi-catch types should be pairwise disjoint
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main DisjunctiveTypeWellFormednessTest
*/
import com.sun.source.util.JavacTask;
import java.net.URI;
import java.util.Arrays;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class DisjunctiveTypeWellFormednessTest {
public class DisjunctiveTypeWellFormednessTest
extends JavacTestingAbstractThreadedTest
implements Runnable {
enum Alternative {
EXCEPTION("Exception"),
@ -92,40 +94,37 @@ public class DisjunctiveTypeWellFormednessTest {
}
public static void main(String... args) throws Exception {
//create default shared JavaCompiler - reused across multiple compilations
JavaCompiler comp = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null);
for (Arity arity : Arity.values()) {
for (Alternative a1 : Alternative.values()) {
if (arity == Arity.ONE) {
new DisjunctiveTypeWellFormednessTest(a1).run(comp, fm);
pool.execute(new DisjunctiveTypeWellFormednessTest(a1));
continue;
}
for (Alternative a2 : Alternative.values()) {
if (arity == Arity.TWO) {
new DisjunctiveTypeWellFormednessTest(a1, a2).run(comp, fm);
pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2));
continue;
}
for (Alternative a3 : Alternative.values()) {
if (arity == Arity.THREE) {
new DisjunctiveTypeWellFormednessTest(a1, a2, a3).run(comp, fm);
pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3));
continue;
}
for (Alternative a4 : Alternative.values()) {
if (arity == Arity.FOUR) {
new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4).run(comp, fm);
pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4));
continue;
}
for (Alternative a5 : Alternative.values()) {
new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5).run(comp, fm);
pool.execute(new DisjunctiveTypeWellFormednessTest(a1, a2, a3, a4, a5));
}
}
}
}
}
}
checkAfterExec(false);
}
Alternative[] alternatives;
@ -159,10 +158,16 @@ public class DisjunctiveTypeWellFormednessTest {
}
}
void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception {
JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker,
@Override
public void run() {
JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker,
null, null, Arrays.asList(source));
ct.analyze();
try {
ct.analyze();
} catch (Throwable t) {
processException(t);
return;
}
check();
}
@ -202,4 +207,5 @@ public class DisjunctiveTypeWellFormednessTest {
}
}
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2013, 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 8006033
* @summary bug in Pretty.toSimpleString
*/
import java.io.File;
import javax.tools.StandardJavaFileManager;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.Pretty;
public class PrettySimpleStringTest {
public static void main(String... args) throws Exception {
new PrettySimpleStringTest().run();
}
void run() throws Exception {
File testSrc = new File(System.getProperty("test.src"));
File thisFile = new File(testSrc, getClass().getName() + ".java");
JavacTool tool = JavacTool.create();
StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
JavacTask task = tool.getTask(null, fm, null, null, null,
fm.getJavaFileObjects(thisFile));
Iterable<? extends CompilationUnitTree> trees = task.parse();
CompilationUnitTree thisTree = trees.iterator().next();
{ // test default
String thisSrc = Pretty.toSimpleString((JCTree) thisTree);
System.err.println(thisSrc);
String expect = "import jav[...]} } }";
if (!thisSrc.equals(expect)) {
throw new Exception("unexpected result");
}
}
{ // test explicit length
String thisSrc = Pretty.toSimpleString((JCTree) thisTree, 32);
System.err.println(thisSrc);
String expect = "import java.io.Fil[...]; } } } }";
if (!thisSrc.equals(expect)) {
throw new Exception("unexpected result");
}
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,8 +25,22 @@
* @test
* @bug 7042566
* @summary Unambiguous varargs method calls flagged as ambiguous
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main T7042566
*/
import java.io.File;
import java.net.URI;
import java.util.Arrays;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Attribute;
@ -34,44 +48,36 @@ import com.sun.tools.classfile.ClassFile;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ConstantPool.*;
import com.sun.tools.classfile.Method;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.util.List;
import java.io.File;
import java.net.URI;
import java.util.Arrays;
import java.util.Locale;
import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class T7042566 {
public class T7042566
extends JavacTestingAbstractThreadedTest
implements Runnable {
VarargsMethod m1;
VarargsMethod m2;
TypeConfiguration actuals;
T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf, TypeConfiguration actuals) {
T7042566(TypeConfiguration m1_conf, TypeConfiguration m2_conf,
TypeConfiguration actuals) {
this.m1 = new VarargsMethod(m1_conf);
this.m2 = new VarargsMethod(m2_conf);
this.actuals = actuals;
}
void compileAndCheck() throws Exception {
@Override
public void run() {
int id = checkCount.incrementAndGet();
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavaSource source = new JavaSource();
JavaSource source = new JavaSource(id);
ErrorChecker ec = new ErrorChecker();
JavacTask ct = (JavacTask)tool.getTask(null, fm, ec,
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), ec,
null, null, Arrays.asList(source));
ct.call();
check(source, ec);
check(source, ec, id);
}
void check(JavaSource source, ErrorChecker ec) {
checkCount++;
void check(JavaSource source, ErrorChecker ec, int id) {
boolean resolutionError = false;
VarargsMethod selectedMethod = null;
@ -99,13 +105,13 @@ public class T7042566 {
"\nFound error: " + ec.errorFound +
"\nCompiler diagnostics:\n" + ec.printDiags());
} else if (!resolutionError) {
verifyBytecode(selectedMethod, source);
verifyBytecode(selectedMethod, source, id);
}
}
void verifyBytecode(VarargsMethod selected, JavaSource source) {
bytecodeCheckCount++;
File compiledTest = new File("Test.class");
void verifyBytecode(VarargsMethod selected, JavaSource source, int id) {
bytecodeCheckCount.incrementAndGet();
File compiledTest = new File(String.format("Test%d.class", id));
try {
ClassFile cf = ClassFile.read(compiledTest);
Method testMethod = null;
@ -118,7 +124,8 @@ public class T7042566 {
if (testMethod == null) {
throw new Error("Test method not found");
}
Code_attribute ea = (Code_attribute)testMethod.attributes.get(Attribute.Code);
Code_attribute ea =
(Code_attribute)testMethod.attributes.get(Attribute.Code);
if (testMethod == null) {
throw new Error("Code attribute for test() method not found");
}
@ -127,11 +134,12 @@ public class T7042566 {
if (i.getMnemonic().equals("invokevirtual")) {
int cp_entry = i.getUnsignedShort(1);
CONSTANT_Methodref_info methRef =
(CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
(CONSTANT_Methodref_info)cf.constant_pool.get(cp_entry);
String type = methRef.getNameAndTypeInfo().getType();
String sig = selected.parameterTypes.bytecodeSigStr;
if (!type.contains(sig)) {
throw new Error("Unexpected type method call: " + type + "" +
throw new Error("Unexpected type method call: " +
type + "" +
"\nfound: " + sig +
"\n" + source.getCharContent(true));
}
@ -146,7 +154,7 @@ public class T7042566 {
class JavaSource extends SimpleJavaFileObject {
static final String source_template = "class Test {\n" +
static final String source_template = "class Test#ID {\n" +
" #V1\n" +
" #V2\n" +
" void test() { m(#E); }\n" +
@ -154,11 +162,13 @@ public class T7042566 {
String source;
public JavaSource() {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
source = source_template.replaceAll("#V1", m1.toString()).
replaceAll("#V2", m2.toString()).
replaceAll("#E", actuals.expressionListStr);
public JavaSource(int id) {
super(URI.create(String.format("myfo:/Test%d.java", id)),
JavaFileObject.Kind.SOURCE);
source = source_template.replaceAll("#V1", m1.toString())
.replaceAll("#V2", m2.toString())
.replaceAll("#E", actuals.expressionListStr)
.replaceAll("#ID", String.valueOf(id));
}
@Override
@ -167,26 +177,17 @@ public class T7042566 {
}
}
/** global decls ***/
// Create a single file manager and reuse it for each compile to save time.
static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
//statistics
static int checkCount = 0;
static int bytecodeCheckCount = 0;
public static void main(String... args) throws Exception {
for (TypeConfiguration tconf1 : TypeConfiguration.values()) {
for (TypeConfiguration tconf2 : TypeConfiguration.values()) {
for (TypeConfiguration tconf3 : TypeConfiguration.values()) {
new T7042566(tconf1, tconf2, tconf3).compileAndCheck();
pool.execute(new T7042566(tconf1, tconf2, tconf3));
}
}
}
System.out.println("Total checks made: " + checkCount);
System.out.println("Bytecode checks made: " + bytecodeCheckCount);
outWriter.println("Bytecode checks made: " + bytecodeCheckCount.get());
checkAfterExec();
}
enum TypeKind {
@ -326,14 +327,16 @@ public class T7042566 {
}
}
static class ErrorChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class ErrorChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
boolean errorFound;
List<String> errDiags = List.nil();
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
errDiags = errDiags.append(diagnostic.getMessage(Locale.getDefault()));
errDiags = errDiags
.append(diagnostic.getMessage(Locale.getDefault()));
errorFound = true;
}
}
@ -347,4 +350,8 @@ public class T7042566 {
return buf.toString();
}
}
//number of bytecode checks made while running combo tests
static AtomicInteger bytecodeCheckCount = new AtomicInteger();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2013, 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,10 +26,11 @@
* @bug 6945418 6993978
* @summary Project Coin: Simplified Varargs Method Invocation
* @author mcimadamore
* @library ../../lib
* @build JavacTestingAbstractThreadedTest
* @run main Warn4
*/
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
import java.net.URI;
import java.util.Arrays;
import java.util.Set;
@ -38,16 +39,19 @@ import javax.tools.Diagnostic;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import com.sun.source.util.JavacTask;
public class Warn4 {
public class Warn4
extends JavacTestingAbstractThreadedTest
implements Runnable {
final static Warning[] error = null;
final static Warning[] none = new Warning[] {};
final static Warning[] vararg = new Warning[] { Warning.VARARGS };
final static Warning[] unchecked = new Warning[] { Warning.UNCHECKED };
final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
final static Warning[] both =
new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
enum Warning {
UNCHECKED("generic.array.creation"),
@ -59,8 +63,10 @@ public class Warn4 {
this.key = key;
}
boolean isSuppressed(TrustMe trustMe, SourceLevel source, SuppressLevel suppressLevelClient,
SuppressLevel suppressLevelDecl, ModifierKind modKind) {
boolean isSuppressed(TrustMe trustMe, SourceLevel source,
SuppressLevel suppressLevelClient,
SuppressLevel suppressLevelDecl,
ModifierKind modKind) {
switch(this) {
case VARARGS:
return source == SourceLevel.JDK_6 ||
@ -68,7 +74,8 @@ public class Warn4 {
trustMe == TrustMe.TRUST;
case UNCHECKED:
return suppressLevelClient == SuppressLevel.UNCHECKED ||
(trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE && source == SourceLevel.JDK_7);
(trustMe == TrustMe.TRUST && modKind !=
ModifierKind.NONE && source == SourceLevel.JDK_7);
}
SuppressLevel supLev = this == VARARGS ?
@ -172,13 +179,13 @@ public class Warn4 {
for (Signature vararg_meth : Signature.values()) {
for (Signature client_meth : Signature.values()) {
if (vararg_meth.isApplicableTo(client_meth)) {
test(sourceLevel,
pool.execute(new Warn4(sourceLevel,
trustMe,
suppressLevelClient,
suppressLevelDecl,
modKind,
vararg_meth,
client_meth);
client_meth));
}
}
}
@ -187,63 +194,82 @@ public class Warn4 {
}
}
}
checkAfterExec();
}
// Create a single file manager and reuse it for each compile to save time.
static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
SourceLevel sourceLevel;
TrustMe trustMe;
SuppressLevel suppressLevelClient;
SuppressLevel suppressLevelDecl;
ModifierKind modKind;
Signature vararg_meth;
Signature client_meth;
DiagnosticChecker diagChecker;
static void test(SourceLevel sourceLevel, TrustMe trustMe, SuppressLevel suppressLevelClient,
SuppressLevel suppressLevelDecl, ModifierKind modKind, Signature vararg_meth, Signature client_meth) throws Exception {
public Warn4(SourceLevel sourceLevel, TrustMe trustMe,
SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
this.sourceLevel = sourceLevel;
this.trustMe = trustMe;
this.suppressLevelClient = suppressLevelClient;
this.suppressLevelDecl = suppressLevelDecl;
this.modKind = modKind;
this.vararg_meth = vararg_meth;
this.client_meth = client_meth;
this.diagChecker = new DiagnosticChecker();
}
@Override
public void run() {
int id = checkCount.incrementAndGet();
final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavaSource source = new JavaSource(trustMe, suppressLevelClient, suppressLevelDecl, modKind, vararg_meth, client_meth);
DiagnosticChecker dc = new DiagnosticChecker();
JavacTask ct = (JavacTask)tool.getTask(null, fm, dc,
JavaSource source = new JavaSource(id);
JavacTask ct = (JavacTask)tool.getTask(null, fm.get(), diagChecker,
Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey),
null, Arrays.asList(source));
ct.generate(); //to get mandatory notes
check(dc.warnings, sourceLevel,
new boolean[] {vararg_meth.giveUnchecked(client_meth),
vararg_meth.giveVarargs(client_meth)},
source, trustMe, suppressLevelClient, suppressLevelDecl, modKind);
ct.call(); //to get mandatory notes
check(source, new boolean[] {vararg_meth.giveUnchecked(client_meth),
vararg_meth.giveVarargs(client_meth)});
}
static void check(Set<Warning> warnings, SourceLevel sourceLevel, boolean[] warnArr, JavaSource source,
TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl, ModifierKind modKind) {
void check(JavaSource source, boolean[] warnArr) {
boolean badOutput = false;
for (Warning wkind : Warning.values()) {
boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
suppressLevelClient, suppressLevelDecl, modKind);
System.out.println("SUPPRESSED = " + isSuppressed);
badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != warnings.contains(wkind);
badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) !=
diagChecker.warnings.contains(wkind);
}
if (badOutput) {
throw new Error("invalid diagnostics for source:\n" +
source.getCharContent(true) +
"\nExpected unchecked warning: " + warnArr[0] +
"\nExpected unsafe vararg warning: " + warnArr[1] +
"\nWarnings: " + warnings +
"\nWarnings: " + diagChecker.warnings +
"\nSource level: " + sourceLevel);
}
}
static class JavaSource extends SimpleJavaFileObject {
class JavaSource extends SimpleJavaFileObject {
String source;
public JavaSource(TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
public JavaSource(int id) {
super(URI.create(String.format("myfo:/Test%d.java", id)),
JavaFileObject.Kind.SOURCE);
String meth1 = vararg_meth.template.replace("#arity", "...");
meth1 = meth1.replace("#name", "m");
meth1 = meth1.replace("#body", "");
meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() + modKind.mod + meth1;
meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() +
modKind.mod + meth1;
String meth2 = client_meth.template.replace("#arity", "");
meth2 = meth2.replace("#name", "test");
meth2 = meth2.replace("#body", "m(arg);");
meth2 = suppressLevelClient.getSuppressAnno() + meth2;
source = "import java.util.List;\n" +
"class Test {\n" + meth1 +
"\n" + meth2 + "\n}\n";
source = String.format("import java.util.List;\n" +
"class Test%s {\n %s \n %s \n } \n", id, meth1, meth2);
}
@Override
@ -252,7 +278,8 @@ public class Warn4 {
}
}
static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
static class DiagnosticChecker
implements javax.tools.DiagnosticListener<JavaFileObject> {
Set<Warning> warnings = new HashSet<>();
@ -267,4 +294,5 @@ public class Warn4 {
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More