Merge
This commit is contained in:
commit
7026f02404
.hgtags.hgtags-top-repo
common/bin
corba
hotspot
jaxp
jaxws
jdk
langtools
.hgtags
make
makefiles
src/share/classes
com/sun
javadoc
tools
classfile
doclets/formats/html
javac
code
comp
jvm
main
resources
tree
util
javadoc
javap
jdeps
javax/lang/model/element
test
Makefile
com/sun/javadoc
testAbstractMethod
testRepeatedAnnotations
tools
doclint
javac
Diagnostics/6769027
MethodParameters.javaT7093325.javacast/intersection
defaultMethods/super
failover
generics
lambda
FunctionalInterfaceConversionTest.javaLambdaParserTest.javaMethodReferenceParserTest.javaTargetType21.javaTargetType21.outTestInvokeDynamic.java
mostSpecific
typeInference/combo
lib
main
multicatch/7030606
tree
varargs
2
.hgtags
2
.hgtags
@ -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:
|
||||
|
103
jdk/test/javax/swing/JTable/8005019/bug8005019.java
Normal file
103
jdk/test/javax/swing/JTable/8005019/bug8005019.java
Normal file
@ -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");
|
||||
}
|
||||
|
173
langtools/src/share/classes/com/sun/tools/jdeps/Archive.java
Normal file
173
langtools/src/share/classes/com/sun/tools/jdeps/Archive.java
Normal file
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
650
langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java
Normal file
650
langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
66
langtools/src/share/classes/com/sun/tools/jdeps/Main.java
Normal file
66
langtools/src/share/classes/com/sun/tools/jdeps/Main.java
Normal file
@ -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
|
28
langtools/src/share/classes/com/sun/tools/jdeps/resources/version.properties-template
Normal file
28
langtools/src/share/classes/com/sun/tools/jdeps/resources/version.properties-template
Normal file
@ -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\"> </span></span>" +
|
||||
"<span id=\"t2\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span><span id=\"t3\" " +
|
||||
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">" +
|
||||
"Abstract Methods</a></span><span class=\"tabEnd\"> </span>" +
|
||||
"</span><span id=\"t5\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span></caption>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "B.html",
|
||||
"<caption><span id=\"t0\" class=\"activeTableTab\"><span>" +
|
||||
"All Methods</span><span class=\"tabEnd\"> </span></span>" +
|
||||
"<span id=\"t2\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span><span id=\"t3\" " +
|
||||
"class=\"tableTab\"><span><a href=\"javascript:show(4);\">Abstract " +
|
||||
"Methods</a></span><span class=\"tabEnd\"> </span></span>" +
|
||||
"<span id=\"t4\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(8);\">Concrete Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </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\"> </span></span>" +
|
||||
"<span id=\"t2\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(2);\">Instance Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span>" +
|
||||
"<span id=\"t5\" class=\"tableTab\"><span>" +
|
||||
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </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\"> </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\"> </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();
|
||||
}
|
||||
}
|
31
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/A.java
Normal file
31
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/A.java
Normal file
@ -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() { }
|
||||
}
|
31
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/B.java
Normal file
31
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/B.java
Normal file
@ -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() { }
|
||||
}
|
29
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/C.java
Normal file
29
langtools/test/com/sun/javadoc/testAbstractMethod/pkg/C.java
Normal file
@ -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 {
|
||||
}
|
38
langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java
Normal file
38
langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/ContainerSynthNotDoc.java
Normal file
@ -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();
|
||||
}
|
39
langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContainerValNotDoc.java
Normal file
39
langtools/test/com/sun/javadoc/testRepeatedAnnotations/pkg1/RegContainerValNotDoc.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
|
344
langtools/test/tools/javac/MethodParameters.java
Normal file
344
langtools/test/tools/javac/MethodParameters.java
Normal file
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
70
langtools/test/tools/javac/main/Option_J_At_Test.java
Normal file
70
langtools/test/tools/javac/main/Option_J_At_Test.java
Normal file
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
73
langtools/test/tools/javac/tree/PrettySimpleStringTest.java
Normal file
73
langtools/test/tools/javac/tree/PrettySimpleStringTest.java
Normal file
@ -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
Loading…
x
Reference in New Issue
Block a user