mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-12 06:29:37 +00:00
8136419: Type annotations in initializers and lambda bodies not written to class file
Reviewed-by: jlahoda
This commit is contained in:
parent
f7bc90496a
commit
431aa657a6
@ -180,6 +180,14 @@ public abstract class Symbol extends AnnoConstruct implements Element {
|
||||
: metadata.getInitTypeAttributes();
|
||||
}
|
||||
|
||||
public void setInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
initedMetadata().setInitTypeAttributes(l);
|
||||
}
|
||||
|
||||
public void setClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
initedMetadata().setClassInitTypeAttributes(l);
|
||||
}
|
||||
|
||||
public List<Attribute.Compound> getDeclarationAttributes() {
|
||||
return (metadata == null)
|
||||
? List.<Attribute.Compound>nil()
|
||||
|
||||
@ -32,6 +32,7 @@ import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.code.Attribute.Array;
|
||||
import com.sun.tools.javac.code.Attribute.TypeCompound;
|
||||
import com.sun.tools.javac.code.Symbol.ClassSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.TypeSymbol;
|
||||
import com.sun.tools.javac.code.Type.ArrayType;
|
||||
import com.sun.tools.javac.code.Type.CapturedType;
|
||||
@ -388,8 +389,21 @@ public class TypeAnnotations {
|
||||
sym.getKind() == ElementKind.RESOURCE_VARIABLE ||
|
||||
sym.getKind() == ElementKind.EXCEPTION_PARAMETER) {
|
||||
// Make sure all type annotations from the symbol are also
|
||||
// on the owner.
|
||||
sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes());
|
||||
// on the owner. If the owner is an initializer block, propagate
|
||||
// to the type.
|
||||
final long ownerFlags = sym.owner.flags();
|
||||
if ((ownerFlags & Flags.BLOCK) != 0) {
|
||||
// Store init and clinit type annotations with the ClassSymbol
|
||||
// to allow output in Gen.normalizeDefs.
|
||||
ClassSymbol cs = (ClassSymbol) sym.owner.owner;
|
||||
if ((ownerFlags & Flags.STATIC) != 0) {
|
||||
cs.appendClassInitTypeAttributes(typeAnnotations);
|
||||
} else {
|
||||
cs.appendInitTypeAttributes(typeAnnotations);
|
||||
}
|
||||
} else {
|
||||
sym.owner.appendUniqueTypeAttributes(sym.getRawTypeAttributes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -55,12 +55,16 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.sun.tools.javac.comp.LambdaToMethod.LambdaSymbolKind.*;
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
import static com.sun.tools.javac.code.Kinds.Kind.*;
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
/**
|
||||
@ -268,21 +272,34 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
MethodSymbol sym = localContext.translatedSym;
|
||||
MethodType lambdaType = (MethodType) sym.type;
|
||||
|
||||
{
|
||||
Symbol owner = localContext.owner;
|
||||
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
|
||||
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
|
||||
{ /* Type annotation management: Based on where the lambda features, type annotations that
|
||||
are interior to it, may at this point be attached to the enclosing method, or the first
|
||||
constructor in the class, or in the enclosing class symbol or in the field whose
|
||||
initializer is the lambda. In any event, gather up the annotations that belong to the
|
||||
lambda and attach it to the implementation method.
|
||||
*/
|
||||
|
||||
for (Attribute.TypeCompound tc : owner.getRawTypeAttributes()) {
|
||||
if (tc.position.onLambda == tree) {
|
||||
lambdaTypeAnnos.append(tc);
|
||||
} else {
|
||||
ownerTypeAnnos.append(tc);
|
||||
}
|
||||
Symbol owner = localContext.owner;
|
||||
apportionTypeAnnotations(tree,
|
||||
owner::getRawTypeAttributes,
|
||||
owner::setTypeAttributes,
|
||||
sym::setTypeAttributes);
|
||||
|
||||
|
||||
boolean init;
|
||||
if ((init = (owner.name == names.init)) || owner.name == names.clinit) {
|
||||
owner = owner.owner;
|
||||
apportionTypeAnnotations(tree,
|
||||
init ? owner::getInitTypeAttributes : owner::getClassInitTypeAttributes,
|
||||
init ? owner::setInitTypeAttributes : owner::setClassInitTypeAttributes,
|
||||
sym::appendUniqueTypeAttributes);
|
||||
}
|
||||
if (lambdaTypeAnnos.nonEmpty()) {
|
||||
owner.setTypeAttributes(ownerTypeAnnos.toList());
|
||||
sym.setTypeAttributes(lambdaTypeAnnos.toList());
|
||||
if (localContext.self != null && localContext.self.getKind() == ElementKind.FIELD) {
|
||||
owner = localContext.self;
|
||||
apportionTypeAnnotations(tree,
|
||||
owner::getRawTypeAttributes,
|
||||
owner::setTypeAttributes,
|
||||
sym::appendUniqueTypeAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,6 +371,29 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
result = makeMetafactoryIndyCall(context, refKind, sym, indy_args);
|
||||
}
|
||||
|
||||
// where
|
||||
// Reassign type annotations from the source that should really belong to the lambda
|
||||
private void apportionTypeAnnotations(JCLambda tree,
|
||||
Supplier<List<Attribute.TypeCompound>> source,
|
||||
Consumer<List<Attribute.TypeCompound>> owner,
|
||||
Consumer<List<Attribute.TypeCompound>> lambda) {
|
||||
|
||||
ListBuffer<Attribute.TypeCompound> ownerTypeAnnos = new ListBuffer<>();
|
||||
ListBuffer<Attribute.TypeCompound> lambdaTypeAnnos = new ListBuffer<>();
|
||||
|
||||
for (Attribute.TypeCompound tc : source.get()) {
|
||||
if (tc.position.onLambda == tree) {
|
||||
lambdaTypeAnnos.append(tc);
|
||||
} else {
|
||||
ownerTypeAnnos.append(tc);
|
||||
}
|
||||
}
|
||||
if (lambdaTypeAnnos.nonEmpty()) {
|
||||
owner.accept(ownerTypeAnnos.toList());
|
||||
lambda.accept(lambdaTypeAnnos.toList());
|
||||
}
|
||||
}
|
||||
|
||||
private JCIdent makeThis(Type type, Symbol owner) {
|
||||
VarSymbol _this = new VarSymbol(PARAMETER | FINAL | SYNTHETIC,
|
||||
names._this,
|
||||
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8136419
|
||||
* @summary test that type annotations on entities in initializers are emitted to classfile
|
||||
* @modules jdk.jdeps/com.sun.tools.classfile
|
||||
*/
|
||||
|
||||
public class InstanceInitializer extends ClassfileTestHelper {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new InstanceInitializer().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
expected_tinvisibles = 4;
|
||||
expected_tvisibles = 0;
|
||||
|
||||
ClassFile cf = getClassFile("InstanceInitializer$Test.class");
|
||||
test(cf);
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors found");
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
|
||||
/*********************** Test class *************************/
|
||||
static class Test {
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface T {}
|
||||
|
||||
{
|
||||
@T String s = null;
|
||||
Runnable r = () -> new ArrayList<@T String>();
|
||||
}
|
||||
@T String s = null;
|
||||
Runnable r = () -> new ArrayList<@T String>();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.tools.classfile.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8136419
|
||||
* @summary test that type annotations on entities in static initializers are emitted to classfile
|
||||
* @modules jdk.jdeps/com.sun.tools.classfile
|
||||
*/
|
||||
|
||||
public class StaticInitializer extends ClassfileTestHelper {
|
||||
public static void main(String[] args) throws Exception {
|
||||
new StaticInitializer().run();
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
expected_tinvisibles = 4;
|
||||
expected_tvisibles = 0;
|
||||
|
||||
ClassFile cf = getClassFile("StaticInitializer$Test.class");
|
||||
test(cf);
|
||||
for (Field f : cf.fields) {
|
||||
test(cf, f);
|
||||
}
|
||||
for (Method m: cf.methods) {
|
||||
test(cf, m, true);
|
||||
}
|
||||
|
||||
countAnnotations();
|
||||
|
||||
if (errors > 0)
|
||||
throw new Exception(errors + " errors found");
|
||||
System.out.println("PASSED");
|
||||
}
|
||||
|
||||
/*********************** Test class *************************/
|
||||
static class Test {
|
||||
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
|
||||
@interface T {}
|
||||
|
||||
static {
|
||||
@T String s = null;
|
||||
Runnable r = () -> new ArrayList<@T String>();
|
||||
}
|
||||
@T static String s = null;
|
||||
static Runnable r = () -> new ArrayList<@T String>();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user