mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-07 17:08:53 +00:00
8008762: Type annotation on inner class in anonymous class show up as regular type annotations
8015257: type annotation with TYPE_USE and FIELD attributed differently if repeated 8013409: test failures for type annotations Fixes to address some problems in type annotations Reviewed-by: jfranck, jjg
This commit is contained in:
parent
ad8c918fb1
commit
a78344ba67
@ -64,6 +64,8 @@ public abstract class Attribute implements AnnotationValue {
|
||||
return false;
|
||||
}
|
||||
|
||||
public TypeAnnotationPosition getPosition() { return null; };
|
||||
|
||||
/** The value for an annotation element of primitive type or String. */
|
||||
public static class Constant extends Attribute {
|
||||
public final Object value;
|
||||
@ -191,8 +193,13 @@ public abstract class Attribute implements AnnotationValue {
|
||||
}
|
||||
|
||||
public Attribute member(Name member) {
|
||||
Pair<MethodSymbol,Attribute> res = getElemPair(member);
|
||||
return res == null ? null : res.snd;
|
||||
}
|
||||
|
||||
private Pair<MethodSymbol, Attribute> getElemPair(Name member) {
|
||||
for (Pair<MethodSymbol,Attribute> pair : values)
|
||||
if (pair.fst.name == member) return pair.snd;
|
||||
if (pair.fst.name == member) return pair;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -208,6 +215,16 @@ public abstract class Attribute implements AnnotationValue {
|
||||
return (DeclaredType) type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeAnnotationPosition getPosition() {
|
||||
if (values.size() != 0) {
|
||||
Name valueName = values.head.fst.name.table.names.value;
|
||||
Pair<MethodSymbol, Attribute> res = getElemPair(valueName);
|
||||
return res == null ? null : res.snd.getPosition();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<MethodSymbol, Attribute> getElementValues() {
|
||||
Map<MethodSymbol, Attribute> valmap =
|
||||
new LinkedHashMap<MethodSymbol, Attribute>();
|
||||
@ -230,6 +247,14 @@ public abstract class Attribute implements AnnotationValue {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeAnnotationPosition getPosition() {
|
||||
if (hasUnknownPosition()) {
|
||||
position = super.getPosition();
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
public boolean hasUnknownPosition() {
|
||||
return position == null || position.type == TargetType.UNKNOWN;
|
||||
}
|
||||
@ -302,6 +327,14 @@ public abstract class Attribute implements AnnotationValue {
|
||||
public <R, P> R accept(AnnotationValueVisitor<R, P> v, P p) {
|
||||
return v.visitArray(getValue(), p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeAnnotationPosition getPosition() {
|
||||
if (values.length != 0)
|
||||
return values[0].getPosition();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The value for an annotation element of an enum type.
|
||||
|
||||
@ -71,6 +71,7 @@ import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.ListBuffer;
|
||||
import com.sun.tools.javac.util.Log;
|
||||
import com.sun.tools.javac.util.Names;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
|
||||
/**
|
||||
* Contains operations specific to processing type annotations.
|
||||
@ -94,6 +95,7 @@ public class TypeAnnotations {
|
||||
final Names names;
|
||||
final Symtab syms;
|
||||
final Annotate annotate;
|
||||
private final boolean typeAnnoAsserts;
|
||||
|
||||
protected TypeAnnotations(Context context) {
|
||||
context.put(typeAnnosKey, this);
|
||||
@ -101,6 +103,8 @@ public class TypeAnnotations {
|
||||
log = Log.instance(context);
|
||||
syms = Symtab.instance(context);
|
||||
annotate = Annotate.instance(context);
|
||||
Options options = Options.instance(context);
|
||||
typeAnnoAsserts = options.isSet("TypeAnnotationAsserts");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,10 +269,6 @@ public class TypeAnnotations {
|
||||
*/
|
||||
private void separateAnnotationsKinds(JCTree typetree, Type type, Symbol sym,
|
||||
TypeAnnotationPosition pos) {
|
||||
/*
|
||||
System.out.printf("separateAnnotationsKinds(typetree: %s, type: %s, symbol: %s, pos: %s%n",
|
||||
typetree, type, sym, pos);
|
||||
*/
|
||||
List<Attribute.Compound> annotations = sym.getRawAttributes();
|
||||
ListBuffer<Attribute.Compound> declAnnos = new ListBuffer<Attribute.Compound>();
|
||||
ListBuffer<Attribute.TypeCompound> typeAnnos = new ListBuffer<Attribute.TypeCompound>();
|
||||
@ -1023,10 +1023,12 @@ public class TypeAnnotations {
|
||||
@Override
|
||||
public void visitMethodDef(final JCMethodDecl tree) {
|
||||
if (tree.sym == null) {
|
||||
// Something most be wrong, e.g. a class not found.
|
||||
// Quietly ignore. (See test FailOver15.java)
|
||||
if (typeAnnoAsserts) {
|
||||
Assert.error("Visiting tree node before memberEnter");
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (sigOnly) {
|
||||
if (!tree.mods.annotations.isEmpty()) {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
@ -1129,6 +1131,9 @@ public class TypeAnnotations {
|
||||
// Nothing to do for separateAnnotationsKinds if
|
||||
// there are no annotations of either kind.
|
||||
} else if (tree.sym == null) {
|
||||
if (typeAnnoAsserts) {
|
||||
Assert.error("Visiting tree node before memberEnter");
|
||||
}
|
||||
// Something is wrong already. Quietly ignore.
|
||||
} else if (tree.sym.getKind() == ElementKind.PARAMETER) {
|
||||
// Parameters are handled in visitMethodDef or visitLambda.
|
||||
@ -1282,9 +1287,9 @@ public class TypeAnnotations {
|
||||
private void findPosition(JCTree tree, JCTree frame, List<JCAnnotation> annotations) {
|
||||
if (!annotations.isEmpty()) {
|
||||
/*
|
||||
System.out.println("Finding pos for: " + annotations);
|
||||
System.out.println(" tree: " + tree + " kind: " + tree.getKind());
|
||||
System.out.println(" frame: " + frame + " kind: " + frame.getKind());
|
||||
System.err.println("Finding pos for: " + annotations);
|
||||
System.err.println(" tree: " + tree + " kind: " + tree.getKind());
|
||||
System.err.println(" frame: " + frame + " kind: " + frame.getKind());
|
||||
*/
|
||||
TypeAnnotationPosition p = new TypeAnnotationPosition();
|
||||
p.onLambda = currentLambda;
|
||||
|
||||
@ -643,9 +643,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
if (TreeInfo.isEnumInit(tree)) {
|
||||
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
||||
} else {
|
||||
// Make sure type annotations are processed.
|
||||
// But we don't have a symbol to attach them to yet - use null.
|
||||
typeAnnotate(tree.vartype, env, null, tree.pos());
|
||||
attr.attribType(tree.vartype, localEnv);
|
||||
if (tree.nameexpr != null) {
|
||||
attr.attribExpr(tree.nameexpr, localEnv);
|
||||
@ -696,7 +693,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
}
|
||||
annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
|
||||
typeAnnotate(tree.vartype, env, v, tree.pos());
|
||||
annotate.flush();
|
||||
v.pos = tree.pos;
|
||||
}
|
||||
// where
|
||||
@ -1084,7 +1080,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
// Do this here, where we have the symbol.
|
||||
for (JCTypeParameter tp : tree.typarams)
|
||||
typeAnnotate(tp, baseEnv, sym, tree.pos());
|
||||
annotate.flush();
|
||||
|
||||
// Add default constructor if needed.
|
||||
if ((c.flags() & INTERFACE) == 0 &&
|
||||
|
||||
@ -104,6 +104,8 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
private LVTRanges lvtRanges;
|
||||
|
||||
private final boolean typeAnnoAsserts;
|
||||
|
||||
protected Gen(Context context) {
|
||||
context.put(genKey, this);
|
||||
|
||||
@ -140,6 +142,7 @@ public class Gen extends JCTree.Visitor {
|
||||
debugCode = options.isSet("debugcode");
|
||||
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
|
||||
pool = new Pool(types);
|
||||
typeAnnoAsserts = options.isSet("TypeAnnotationAsserts");
|
||||
|
||||
generateIproxies =
|
||||
target.requiresIproxy() ||
|
||||
@ -562,9 +565,13 @@ public class Gen extends JCTree.Visitor {
|
||||
ListBuffer<Attribute.TypeCompound> fieldTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
ListBuffer<Attribute.TypeCompound> nonfieldTAs = new ListBuffer<Attribute.TypeCompound>();
|
||||
for (TypeCompound ta : tas) {
|
||||
if (ta.position.type == TargetType.FIELD) {
|
||||
if (ta.getPosition().type == TargetType.FIELD) {
|
||||
fieldTAs.add(ta);
|
||||
} else {
|
||||
if (typeAnnoAsserts) {
|
||||
Assert.error("Type annotation does not have a valid positior");
|
||||
}
|
||||
|
||||
nonfieldTAs.add(ta);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,439 @@
|
||||
/*
|
||||
* 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 8005085 8008762 8008751 8013065 8015323 8015257
|
||||
* @summary Type annotations on anonymous and inner class.
|
||||
* Six TYPE_USE annotations are repeated(or not); Four combinations create
|
||||
* four test files, and each results in the test class and 2 anonymous classes.
|
||||
* Each element of these three classes is checked for expected number of the
|
||||
* four annotation Attributes. Expected annotation counts depend on type of
|
||||
* annotation place on type of element (a FIELD&TYPE_USE element on a field
|
||||
* results in 2). Elements with no annotations expect 0.
|
||||
* Source template is read in from testanoninner.template
|
||||
*
|
||||
*/
|
||||
import java.lang.annotation.*;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
import java.util.LinkedList;
|
||||
import com.sun.tools.classfile.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.charset.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
|
||||
/*
|
||||
* A source template is read in and testname and annotations are inserted
|
||||
* via replace().
|
||||
*/
|
||||
public class TestAnonInnerClasses extends ClassfileTestHelper {
|
||||
// tally errors and test cases
|
||||
int errors = 0;
|
||||
int checks = 0;
|
||||
//Note expected test count in case of skips due to bugs.
|
||||
int tc = 0, xtc = 180; // 45 x 4 variations of repeated annotations.
|
||||
File testSrc = new File(System.getProperty("test.src"));
|
||||
|
||||
String[] AnnoAttributes = {
|
||||
Attribute.RuntimeVisibleTypeAnnotations,
|
||||
Attribute.RuntimeInvisibleTypeAnnotations,
|
||||
Attribute.RuntimeVisibleAnnotations,
|
||||
Attribute.RuntimeInvisibleAnnotations
|
||||
};
|
||||
|
||||
// template for source files
|
||||
String srcTemplate = "testanoninner.template";
|
||||
|
||||
// Four test files generated based on combinations of repeating annotations.
|
||||
Boolean As= false, Bs=true, Cs=false, Ds=false, TAs=false,TBs=false;
|
||||
Boolean[][] bRepeat = new Boolean[][]{
|
||||
/* no repeats */ {false, false, false, false, false, false},
|
||||
/* repeat A,C,TA */ {true, false, true, false, true, false},
|
||||
/* repeat B,D,TB */ {false, true, false, true, false, true},
|
||||
/* repeat all */ {true, true, true, true, true, true}
|
||||
};
|
||||
// Save descriptions of failed test case; does not terminate upon a failure.
|
||||
List<String> failed = new LinkedList<>();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new TestAnonInnerClasses().run();
|
||||
}
|
||||
|
||||
// Check annotation counts and make reports sufficiently descriptive to
|
||||
// easily diagnose.
|
||||
void check(String testcase, int vtaX, int itaX, int vaX, int iaX,
|
||||
int vtaA, int itaA, int vaA, int iaA) {
|
||||
|
||||
String descr = " checking " + testcase+" _TYPE_, expected: " +
|
||||
vtaX + ", " + itaX + ", " + vaX + ", " + iaX + "; actual: " +
|
||||
vtaA + ", " + itaA + ", " + vaA + ", " + iaA;
|
||||
String description;
|
||||
description=descr.replace("_TYPE_","RuntimeVisibleTypeAnnotations");
|
||||
if (vtaX != vtaA) {
|
||||
errors++;
|
||||
failed.add(++checks + " " + testcase + ": (vtaX) " + vtaX +
|
||||
" != " + vtaA + " (vtaA)");
|
||||
println(checks + " FAIL: " + description);
|
||||
} else {
|
||||
println(++checks + " PASS: " + description);
|
||||
}
|
||||
description=descr.replace("_TYPE_","RuntimeInvisibleTypeAnnotations");
|
||||
if (itaX != itaA) {
|
||||
errors++;
|
||||
failed.add(++checks + " " + testcase + ": (itaX) " + itaX + " != " +
|
||||
itaA + " (itaA)");
|
||||
println(checks + " FAIL: " + description);
|
||||
} else {
|
||||
println(++checks + " PASS: " + description);
|
||||
}
|
||||
description=descr.replace("_TYPE_","RuntimeVisibleAnnotations");
|
||||
if (vaX != vaA) {
|
||||
errors++;
|
||||
failed.add(++checks + " " + testcase + ": (vaX) " + vaX + " != " +
|
||||
vaA + " (vaA)");
|
||||
println(checks + " FAIL: " + description);
|
||||
} else {
|
||||
println(++checks + " PASS: " + description);
|
||||
}
|
||||
description=descr.replace("_TYPE_","RuntimeInvisibleAnnotations");
|
||||
if (iaX != iaA) {
|
||||
errors++;
|
||||
failed.add(++checks + " " + testcase + ": (iaX) " + iaX + " != " +
|
||||
iaA + " (iaA)");
|
||||
println(checks + " FAIL: " + description);
|
||||
} else {
|
||||
println(++checks + " PASS: " + description);
|
||||
}
|
||||
println("");
|
||||
}
|
||||
|
||||
// Print failed cases (if any) and throw exception for fail.
|
||||
void report() {
|
||||
if (errors!=0) {
|
||||
System.err.println("Failed tests: " + errors +
|
||||
"\nfailed test cases:\n");
|
||||
for (String t: failed) System.err.println(" " + t);
|
||||
throw new RuntimeException("FAIL: There were test failures.");
|
||||
} else
|
||||
System.out.println("PASSED all tests.");
|
||||
}
|
||||
|
||||
void test(String ttype, ClassFile cf, Method m, Field f, boolean visible) {
|
||||
int vtaActual = 0,
|
||||
itaActual = 0,
|
||||
vaActual = 0,
|
||||
iaActual = 0,
|
||||
vtaExp = 0,
|
||||
itaExp = 0,
|
||||
vaExp = 0,
|
||||
iaExp = 0,
|
||||
index = 0,
|
||||
index2 = 0;
|
||||
String memberName = null,
|
||||
testcase = "undefined",
|
||||
testClassName = null;
|
||||
Attribute attr = null,
|
||||
cattr = null;
|
||||
Code_attribute CAttr = null;
|
||||
// Get counts of 4 annotation Attributes on element being checked.
|
||||
for (String AnnoType : AnnoAttributes) {
|
||||
try {
|
||||
switch (ttype) {
|
||||
case "METHOD":
|
||||
index = m.attributes.getIndex(cf.constant_pool,
|
||||
AnnoType);
|
||||
memberName = m.getName(cf.constant_pool);
|
||||
if (index != -1)
|
||||
attr = m.attributes.get(index);
|
||||
//fetch index annotations from code attribute.
|
||||
index2 = m.attributes.getIndex(cf.constant_pool,
|
||||
Attribute.Code);
|
||||
if (index2 != -1) {
|
||||
cattr = m.attributes.get(index2);
|
||||
assert cattr instanceof Code_attribute;
|
||||
CAttr = (Code_attribute)cattr;
|
||||
index2 = CAttr.attributes.getIndex(cf.constant_pool,
|
||||
AnnoType);
|
||||
if (index2 != -1)
|
||||
cattr = CAttr.attributes.get(index2);
|
||||
}
|
||||
break;
|
||||
case "FIELD":
|
||||
index = f.attributes.getIndex(cf.constant_pool,
|
||||
AnnoType);
|
||||
memberName = f.getName(cf.constant_pool);
|
||||
if (index != -1)
|
||||
attr = f.attributes.get(index);
|
||||
//fetch index annotations from code attribute.
|
||||
index2 = cf.attributes.getIndex(cf.constant_pool,
|
||||
Attribute.Code);
|
||||
if (index2!= -1) {
|
||||
cattr = cf.attributes.get(index2);
|
||||
assert cattr instanceof Code_attribute;
|
||||
CAttr = (Code_attribute)cattr;
|
||||
index2 = CAttr.attributes.getIndex(cf.constant_pool,
|
||||
AnnoType);
|
||||
if (index2!= -1)
|
||||
cattr = CAttr.attributes.get(index2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
memberName = cf.getName();
|
||||
index = cf.attributes.getIndex(cf.constant_pool,
|
||||
AnnoType);
|
||||
if (index!= -1) attr = cf.attributes.get(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (ConstantPoolException cpe) { cpe.printStackTrace(); }
|
||||
try {
|
||||
testClassName=cf.getName();
|
||||
testcase = ttype + ": " + testClassName + ": " +
|
||||
memberName + ", ";
|
||||
}
|
||||
catch (ConstantPoolException cpe) { cpe.printStackTrace(); }
|
||||
if (index != -1) {
|
||||
switch (AnnoType) {
|
||||
case Attribute.RuntimeVisibleTypeAnnotations:
|
||||
//count RuntimeVisibleTypeAnnotations
|
||||
RuntimeVisibleTypeAnnotations_attribute RVTAa =
|
||||
(RuntimeVisibleTypeAnnotations_attribute)attr;
|
||||
vtaActual += RVTAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeVisibleAnnotations:
|
||||
//count RuntimeVisibleAnnotations
|
||||
RuntimeVisibleAnnotations_attribute RVAa =
|
||||
(RuntimeVisibleAnnotations_attribute)attr;
|
||||
vaActual += RVAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeInvisibleTypeAnnotations:
|
||||
//count RuntimeInvisibleTypeAnnotations
|
||||
RuntimeInvisibleTypeAnnotations_attribute RITAa =
|
||||
(RuntimeInvisibleTypeAnnotations_attribute)attr;
|
||||
itaActual += RITAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeInvisibleAnnotations:
|
||||
//count RuntimeInvisibleAnnotations
|
||||
RuntimeInvisibleAnnotations_attribute RIAa =
|
||||
(RuntimeInvisibleAnnotations_attribute)attr;
|
||||
iaActual += RIAa.annotations.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// annotations from code attribute.
|
||||
if (index2 != -1) {
|
||||
switch (AnnoType) {
|
||||
case Attribute.RuntimeVisibleTypeAnnotations:
|
||||
//count RuntimeVisibleTypeAnnotations
|
||||
RuntimeVisibleTypeAnnotations_attribute RVTAa =
|
||||
(RuntimeVisibleTypeAnnotations_attribute)cattr;
|
||||
vtaActual += RVTAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeVisibleAnnotations:
|
||||
//count RuntimeVisibleAnnotations
|
||||
RuntimeVisibleAnnotations_attribute RVAa =
|
||||
(RuntimeVisibleAnnotations_attribute)cattr;
|
||||
vaActual += RVAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeInvisibleTypeAnnotations:
|
||||
//count RuntimeInvisibleTypeAnnotations
|
||||
RuntimeInvisibleTypeAnnotations_attribute RITAa =
|
||||
(RuntimeInvisibleTypeAnnotations_attribute)cattr;
|
||||
itaActual += RITAa.annotations.length;
|
||||
break;
|
||||
case Attribute.RuntimeInvisibleAnnotations:
|
||||
//count RuntimeInvisibleAnnotations
|
||||
RuntimeInvisibleAnnotations_attribute RIAa =
|
||||
(RuntimeInvisibleAnnotations_attribute)cattr;
|
||||
iaActual += RIAa.annotations.length;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (memberName) {
|
||||
//METHODs
|
||||
case "test" : vtaExp=4; itaExp=4; vaExp=0; iaExp=0; tc++; break;
|
||||
case "mtest": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "m1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "m2": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "m3": vtaExp=10; itaExp=10; vaExp=1; iaExp=1; tc++; break;
|
||||
case "tm": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//inner class
|
||||
case "i_m1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_m2": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_um": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//local class
|
||||
case "l_m1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_m2": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_um": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//anon class
|
||||
case "mm_m1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_m2": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_m3": vtaExp=10; itaExp=10;vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_tm": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//InnerAnon class
|
||||
case "ia_m1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_m2": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_um": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//FIELDs
|
||||
case "data": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "odata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "pdata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "tdata": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "sa1": vtaExp = 6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
//inner class
|
||||
case "i_odata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_pdata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_udata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_sa1": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
case "i_tdata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
//local class
|
||||
case "l_odata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_pdata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_udata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_sa1": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
case "l_tdata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
//anon class
|
||||
case "mm_odata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_pdata1": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_sa1": vtaExp = 6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
case "mm_tdata": vtaExp = 2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
// InnerAnon class
|
||||
case "ia_odata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_pdata1": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_udata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_sa1": vtaExp=6; itaExp=6; vaExp=1; iaExp=1; tc++; break;
|
||||
case "ia_tdata": vtaExp=2; itaExp=2; vaExp=1; iaExp=1; tc++; break;
|
||||
case "IA": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
case "IN": vtaExp=4; itaExp=4; vaExp=1; iaExp=1; tc++; break;
|
||||
// default cases are <init>, this$0, this$1, mmtest, atest
|
||||
default: vtaExp = 0; itaExp=0; vaExp=0; iaExp=0; break;
|
||||
}
|
||||
check(testcase,vtaExp, itaExp, vaExp, iaExp,
|
||||
vtaActual,itaActual,vaActual,iaActual);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
ClassFile cf = null;
|
||||
InputStream in = null;
|
||||
int testcount = 1;
|
||||
File testFile = null;
|
||||
// Generate source, check methods and fields for each combination.
|
||||
for (Boolean[] bCombo : bRepeat) {
|
||||
As=bCombo[0]; Bs=bCombo[1]; Cs=bCombo[2];
|
||||
Ds=bCombo[3]; TAs=bCombo[4]; TBs=bCombo[5];
|
||||
String testname = "Test" + testcount++;
|
||||
println("Combinations: " + As + ", " + Bs + ", " + Cs + ", " + Ds +
|
||||
", " + TAs + ", " + TBs +
|
||||
"; see " + testname + ".java");
|
||||
String[] classes = {testname + ".class",
|
||||
testname + "$Inner.class",
|
||||
testname + "$1Local1.class",
|
||||
testname + "$1.class",
|
||||
testname + "$1$1.class",
|
||||
testname + "$1$InnerAnon.class"
|
||||
};
|
||||
// Create test source, create and compile File.
|
||||
String sourceString = getSource(srcTemplate, testname,
|
||||
As, Bs, Cs, Ds, TAs, TBs);
|
||||
System.out.println(sourceString);
|
||||
try {
|
||||
testFile = writeTestFile(testname+".java", sourceString);
|
||||
}
|
||||
catch (IOException ioe) { ioe.printStackTrace(); }
|
||||
// Compile test source and read classfile.
|
||||
File classFile = null;
|
||||
try {
|
||||
classFile = compile(testFile);
|
||||
}
|
||||
catch (Error err) {
|
||||
System.err.println("FAILED compile. Source:\n" + sourceString);
|
||||
throw err;
|
||||
}
|
||||
String testloc = classFile.getAbsolutePath().substring(
|
||||
0,classFile.getAbsolutePath().indexOf(classFile.getPath()));
|
||||
for (String clazz : classes) {
|
||||
try {
|
||||
cf = ClassFile.read(new File(testloc+clazz));
|
||||
}
|
||||
catch (Exception e) { e.printStackTrace(); }
|
||||
// Test for all methods and fields
|
||||
for (Method m: cf.methods) {
|
||||
test("METHOD", cf, m, null, true);
|
||||
}
|
||||
for (Field f: cf.fields) {
|
||||
test("FIELD", cf, null, f, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
report();
|
||||
if (tc!=xtc) System.out.println("Test Count: " + tc + " != " +
|
||||
"expected: " + xtc);
|
||||
}
|
||||
|
||||
|
||||
String getSrcTemplate(String sTemplate) {
|
||||
List<String> tmpl = null;
|
||||
String sTmpl = "";
|
||||
try {
|
||||
tmpl = Files.readAllLines(new File(testSrc,sTemplate).toPath(),
|
||||
Charset.defaultCharset());
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
String error = "FAILED: Test failed to read template" + sTemplate;
|
||||
ioe.printStackTrace();
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
for (String l : tmpl)
|
||||
sTmpl=sTmpl.concat(l).concat("\n");
|
||||
return sTmpl;
|
||||
}
|
||||
|
||||
// test class template
|
||||
String getSource(String templateName, String testname,
|
||||
Boolean Arepeats, Boolean Brepeats,
|
||||
Boolean Crepeats, Boolean Drepeats,
|
||||
Boolean TArepeats, Boolean TBrepeats) {
|
||||
String As = Arepeats ? "@A @A":"@A",
|
||||
Bs = Brepeats ? "@B @B":"@B",
|
||||
Cs = Crepeats ? "@C @C":"@C",
|
||||
Ds = Drepeats ? "@D @D":"@D",
|
||||
TAs = TArepeats ? "@TA @TA":"@TA",
|
||||
TBs = TBrepeats ? "@TB @TB":"@TB";
|
||||
|
||||
// split up replace() lines for readability
|
||||
String testsource = getSrcTemplate(templateName).replace("testname",testname);
|
||||
testsource = testsource.replace("_As",As).replace("_Bs",Bs).replace("_Cs",Cs);
|
||||
testsource = testsource.replace("_Ds",Ds).replace("_TAs",TAs).replace("_TBs",TBs);
|
||||
return testsource;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
import java.lang.annotation.*;
|
||||
import static java.lang.annotation.RetentionPolicy.*;
|
||||
import static java.lang.annotation.ElementType.*;
|
||||
import java.util.List;
|
||||
|
||||
class testname <T> { // TestN.class
|
||||
_As _Bs _Cs _Ds String data = "test";
|
||||
_As _Bs _Cs _Ds Object mtest( _As _Bs _Cs _Ds testname <T> t){ return null; }
|
||||
Object mmtest( testname<T> t){ return null; }
|
||||
|
||||
class Inner<U> { // TestN$1$Inner.class
|
||||
_As _Bs _Cs _Ds String i_odata1 = "test";
|
||||
_As _Bs _Cs _Ds int i_pdata1 = 0;
|
||||
_As _Bs _Cs _Ds U i_udata = null;
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds [] _As _Bs _Cs _Ds [] i_sa1 = null;
|
||||
_As _Bs _Cs _Ds T i_tdata = null;
|
||||
_As _Bs _Cs _Ds String i_m1(){ return null; };
|
||||
_As _Bs _Cs _Ds int i_m2( _As _Bs _Cs _Ds Object o){return 0;}
|
||||
_As _Bs _Cs _Ds
|
||||
<_TAs _TBs _Cs _Ds U> Object i_um( _As _Bs _Cs _Ds U u) { return null; }
|
||||
}
|
||||
//8015323
|
||||
_As _Bs _Cs _Ds Inner< _As _Bs _Cs _Ds String> IN = new Inner< String>();
|
||||
|
||||
public void test() {
|
||||
|
||||
class Local1<U> { // TestN$Local1.class
|
||||
_As _Bs _Cs _Ds String l_odata1 = "test";
|
||||
_As _Bs _Cs _Ds int l_pdata1 = 0;
|
||||
_As _Bs _Cs _Ds U l_udata = null;
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] l_sa1 = null;
|
||||
_TAs _TBs _Cs _Ds T l_tdata = null;
|
||||
_As _Bs _Cs _Ds String l_m1(){ return null; };
|
||||
_As _Bs _Cs _Ds int l_m2(_As _Bs _Cs _Ds Object o){return 0;}
|
||||
_As _Bs _Cs _Ds
|
||||
<_TAs _TBs _Cs _Ds U> Object l_um(_As _Bs _Cs _Ds U u) { return null; }
|
||||
}
|
||||
// The below, as a local variable, will show up on test()
|
||||
_As _Bs _Cs _Ds Local1<_As _Bs _Cs _Ds String> LC = new Local1<String>();
|
||||
|
||||
mtest( new testname<T>() { // TestN$1
|
||||
class InnerAnon<U> { // TestN$1$InnerAnon.class
|
||||
_As _Bs _Cs _Ds String ia_odata1 = "test";
|
||||
_As _Bs _Cs _Ds int ia_pdata1 = 0;
|
||||
_As _Bs _Cs _Ds U ia_udata = null;
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] ia_sa1 = null;
|
||||
_TAs _TBs _Cs _Ds T ia_tdata = null;
|
||||
_As _Bs _Cs _Ds String ia_m1(){ return null; };
|
||||
_As _Bs _Cs _Ds int ia_m2(_As _Bs _Cs _Ds Object o){return 0;}
|
||||
_As _Bs _Cs _Ds
|
||||
<_TAs _TBs _Cs _Ds U> Object ia_um(_As _Bs _Cs _Ds U u) { return null; }
|
||||
}
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds InnerAnon<_As _Bs _Cs _Ds String> IA = new InnerAnon< String>();
|
||||
|
||||
_As _Bs _Cs _Ds String odata1 = "test";
|
||||
_As _Bs _Cs _Ds int pdata1 = 0;
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] sa1 = null;
|
||||
_As _Bs _Cs _Ds T tdata = null;
|
||||
|
||||
_As _Bs _Cs _Ds String m1(){ return null; };
|
||||
_As _Bs _Cs _Ds int m2(_As _Bs _Cs _Ds Object o){return 0;}
|
||||
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds [] _As _Bs _Cs _Ds []
|
||||
m3(String _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] sa){ return null; }
|
||||
|
||||
_As _Bs _Cs _Ds
|
||||
<_TAs _TBs _Cs _Ds T> Object tm(_As _Bs _Cs _Ds T t) { return null; }
|
||||
|
||||
public void atest( testname<T> t){
|
||||
t.mmtest( new testname<T>() { // TestN$1$1.class
|
||||
_As _Bs _Cs _Ds String mm_odata1 = "test";
|
||||
_As _Bs _Cs _Ds int mm_pdata1 = 0;
|
||||
//8015257
|
||||
_As _Bs _Cs _Ds Object _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] mm_sa1 = null;
|
||||
_TAs _TBs _Cs _Ds T mm_tdata = null;
|
||||
|
||||
_As _Bs _Cs _Ds String mm_m1(){ return null; };
|
||||
_As _Bs _Cs _Ds int mm_m2(_As _Bs _Cs _Ds Object o){return 0;}
|
||||
|
||||
_As _Bs _Cs _Ds String _As _Bs _Cs _Ds [] _As _Bs _Cs _Ds []
|
||||
mm_m3(String _As _Bs _Cs _Ds []_As _Bs _Cs _Ds [] sa){ return null; }
|
||||
|
||||
_As _Bs _Cs _Ds
|
||||
<_TAs _TBs _Cs _Ds T> Object mm_tm(_As _Bs _Cs _Ds T t) { return null; }
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,FIELD}) @Repeatable( AC.class ) @interface A { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @Repeatable( BC.class ) @interface B { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,FIELD}) @interface AC { A[] value(); }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface BC { B[] value(); }
|
||||
|
||||
@Retention(CLASS) @Target({TYPE_USE,FIELD}) @Repeatable( CC.class ) @interface C { }
|
||||
@Retention(CLASS) @Target({TYPE_USE,METHOD}) @Repeatable( DC.class ) @interface D { }
|
||||
@Retention(CLASS) @Target({TYPE_USE,FIELD}) @interface CC { C[] value(); }
|
||||
@Retention(CLASS) @Target({TYPE_USE,METHOD}) @interface DC { D[] value(); }
|
||||
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,TYPE_PARAMETER,FIELD}) @Repeatable( TAC.class ) @interface TA { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,TYPE_PARAMETER,METHOD}) @Repeatable( TBC.class ) @interface TB { }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,TYPE_PARAMETER,FIELD}) @interface TAC { TA[] value(); }
|
||||
@Retention(RUNTIME) @Target({TYPE_USE,TYPE_PARAMETER,METHOD}) @interface TBC { TB[] value(); }
|
||||
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8006733 8006775
|
||||
* @ignore 8013409: test failures for type annotations
|
||||
|
||||
* @summary A static outer class cannot be annotated.
|
||||
* @author Werner Dietl
|
||||
* @compile/fail/ref=CantAnnotateStaticClass.out -XDrawDiagnostics CantAnnotateStaticClass.java
|
||||
|
||||
@ -1 +1,10 @@
|
||||
dummy
|
||||
CantAnnotateStaticClass.java:22:20: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:23:13: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:24:29: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:26:29: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:29:26: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:30:9: compiler.err.cant.annotate.static.class
|
||||
CantAnnotateStaticClass.java:31:35: compiler.err.cant.annotate.static.class
|
||||
- compiler.note.unchecked.filename: CantAnnotateStaticClass.java
|
||||
- compiler.note.unchecked.recompile
|
||||
7 errors
|
||||
|
||||
@ -25,6 +25,7 @@ import java.lang.annotation.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @ignore 8008762 Type annotations failures
|
||||
* @bug 8006775
|
||||
* @summary new type annotation location: multicatch
|
||||
* @author Werner Dietl
|
||||
|
||||
@ -25,6 +25,7 @@ import static com.sun.tools.classfile.TypeAnnotation.TargetType.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @ignore 8008762 Type annotation failures
|
||||
* @bug 8006732 8006775
|
||||
* @summary Test population of reference info for multicatch exception parameters
|
||||
* @author Werner Dietl
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user