OpenJDK / amber / amber
changeset 56928:7559b9413ba7 amber-demo-II
Automatic merge with records-and-sealed
author | mcimadamore |
---|---|
date | Fri, 12 Jul 2019 18:50:44 +0000 |
parents | 6d2b8e46b010 e458917a1c54 |
children | f02972e89dec |
files | src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java |
diffstat | 10 files changed, 194 insertions(+), 33 deletions(-) [+] |
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Fri Jul 12 18:50:44 2019 +0000 @@ -1646,8 +1646,6 @@ return ElementKind.PARAMETER; } else if ((flags & ENUM) != 0) { return ElementKind.ENUM_CONSTANT; - } else if ((flags & RECORD) != 0) { - return ElementKind.STATE_COMPONENT; } else if (owner.kind == TYP || owner.kind == ERR) { return ElementKind.FIELD; } else if (isResourceVariable()) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/SymbolMetadata.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/SymbolMetadata.java Fri Jul 12 18:50:44 2019 +0000 @@ -255,4 +255,36 @@ private boolean isStarted() { return attributes != DECL_NOT_STARTED; } + + private List<Attribute.Compound> removeFromCompoundList(List<Attribute.Compound> l, Attribute.Compound compound) { + ListBuffer<Attribute.Compound> lb = new ListBuffer<>(); + for (Attribute.Compound c : l) { + if (c != compound) { + lb.add(c); + } + } + return lb.toList(); + } + + private List<Attribute.TypeCompound> removeFromTypeCompoundList(List<Attribute.TypeCompound> l, Attribute.TypeCompound compound) { + ListBuffer<Attribute.TypeCompound> lb = new ListBuffer<>(); + for (Attribute.TypeCompound c : l) { + if (c != compound) { + lb.add(c); + } + } + return lb.toList(); + } + + public void remove(Attribute.Compound compound) { + if (attributes.contains(compound)) { + attributes = removeFromCompoundList(attributes, compound); + } else if (type_attributes.contains(compound)) { + type_attributes = removeFromTypeCompoundList(type_attributes, (TypeCompound)compound); + } else if (init_type_attributes.contains(compound)) { + init_type_attributes = removeFromTypeCompoundList(init_type_attributes, (TypeCompound)compound); + } else if (clinit_type_attributes.contains(compound)) { + clinit_type_attributes = removeFromTypeCompoundList(clinit_type_attributes, (TypeCompound)compound); + } + } }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Fri Jul 12 18:50:44 2019 +0000 @@ -1266,7 +1266,7 @@ // No type annotations can occur here. } else { // There is nothing else in a variable declaration that needs separation. - Assert.error("Unhandled variable kind"); + Assert.error("Unhandled variable kind: " + tree.sym.getKind()); } scan(tree.mods);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Fri Jul 12 18:50:44 2019 +0000 @@ -276,7 +276,7 @@ validate(() -> { //validate annotations JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); try { - chk.validateAnnotations(annotations, s); + chk.validateAnnotations(annotations, TreeInfo.declarationFor(s, localEnv.tree), s); } finally { log.useSource(prev); }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Fri Jul 12 18:50:44 2019 +0000 @@ -2839,9 +2839,9 @@ /** Check the annotations of a symbol. */ - public void validateAnnotations(List<JCAnnotation> annotations, Symbol s) { + public void validateAnnotations(List<JCAnnotation> annotations, JCTree declarationTree, Symbol s) { for (JCAnnotation a : annotations) - validateAnnotation(a, s); + validateAnnotation(a, declarationTree, s); } /** Check the type annotations. @@ -2853,11 +2853,48 @@ /** Check an annotation of a symbol. */ - private void validateAnnotation(JCAnnotation a, Symbol s) { + private void validateAnnotation(JCAnnotation a, JCTree declarationTree, Symbol s) { validateAnnotationTree(a); - if (a.type.tsym.isAnnotationType() && !annotationApplicable(a, s)) - log.error(a.pos(), Errors.AnnotationTypeNotApplicable); + if (s.isRecord() && s.flags_field == (Flags.PRIVATE | Flags.FINAL | Flags.MANDATED | Flags.RECORD) && declarationTree.hasTag(VARDEF)) { + // we are seeing a record field, which had the original annotations, now is the moment, + // before stripping some of them just below, to check if the original annotations + // applied to records at all, first version only cares about declaration annotations + // we will add type annotations later on + Name[] targets = getTargetNames(a, s); + boolean appliesToRecords = false; + for (Name target : targets) { + appliesToRecords = target == names.FIELD || target == names.PARAMETER || target == names.METHOD; + if (appliesToRecords) { + break; + } + } + if (!appliesToRecords) { + log.error(a.pos(), Errors.AnnotationTypeNotApplicable); + } + } + + if (a.type.tsym.isAnnotationType() && !annotationApplicable(a, s)) { + // debug + //System.out.println("at Check.validateAnnotation: flags: " + Flags.toString(s.flags_field) + ", declaration tree " + declarationTree); + if (s.isRecord() || s.owner.isRecord() && (s.flags_field & Flags.MANDATED) != 0) { + JCModifiers modifiers = TreeInfo.getModifiers(declarationTree); + // lets first remove the annotation from the modifier + if (modifiers != null) { + ListBuffer<JCAnnotation> newAnnotations = new ListBuffer<>(); + for (JCAnnotation anno : modifiers.annotations) { + if (anno != a) { + newAnnotations.add(anno); + } + } + modifiers.annotations = newAnnotations.toList(); + } + // now lets remove it from the symbol + s.getMetadata().remove(a.attribute); + } else { + log.error(a.pos(), Errors.AnnotationTypeNotApplicable); + } + } if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) { if (s.kind != TYP) { @@ -3107,10 +3144,9 @@ } /** Is the annotation applicable to the symbol? */ - boolean annotationApplicable(JCAnnotation a, Symbol s) { + Name[] getTargetNames(JCAnnotation a, Symbol s) { Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym); Name[] targets; - if (arr == null) { targets = defaultTargetMetaInfo(a, s); } else { @@ -3119,12 +3155,21 @@ for (int i=0; i<arr.values.length; ++i) { Attribute app = arr.values[i]; if (!(app instanceof Attribute.Enum)) { - return true; // recovery + return new Name[0]; } Attribute.Enum e = (Attribute.Enum) app; targets[i] = e.value.name; } } + return targets; + } + + boolean annotationApplicable(JCAnnotation a, Symbol s) { + Name[] targets = getTargetNames(a, s); + if (targets.length == 0) { + // recovery + return true; + } for (Name target : targets) { if (target == names.TYPE) { if (s.kind == TYP)
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Fri Jul 12 18:50:44 2019 +0000 @@ -28,7 +28,9 @@ import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; +import java.util.stream.Collectors; +import javax.lang.model.element.ElementKind; import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; @@ -949,7 +951,7 @@ } } } else if ((sym.flags() & RECORD) != 0) { - helper = new RecordConstructorHelper(sym, TreeInfo.recordFields(tree).map(vd -> vd.sym)); + helper = new RecordConstructorHelper(sym, TreeInfo.recordFields(tree)); } if (helper != null) { JCTree constrDef = defaultConstructor(make.at(tree.pos), helper); @@ -965,9 +967,7 @@ TreeInfo.getConstructorInvocationName(((JCMethodDecl)def).body.stats, names, true); if (constructorInvocationName == names.empty || constructorInvocationName == names._super) { - RecordConstructorHelper helper = new RecordConstructorHelper( - sym, - TreeInfo.recordFields(tree).map(vd -> vd.sym)); + RecordConstructorHelper helper = new RecordConstructorHelper(sym, TreeInfo.recordFields(tree)); JCMethodDecl methDecl = (JCMethodDecl)def; if (constructorInvocationName == names.empty) { JCStatement supCall = make.at(methDecl.body.pos).Exec(make.Apply(List.nil(), @@ -1052,14 +1052,14 @@ (types.supertype(tree.sym.type).tsym.flags() & Flags.ENUM) == 0) { addEnumMembers(tree, env); } - List<JCTree> defsToEnter = (tree.sym.flags_field & RECORD) != 0 ? + boolean isRecord = (tree.sym.flags_field & RECORD) != 0; + List<JCTree> defsToEnter = isRecord ? tree.defs.diff(List.convert(JCTree.class, TreeInfo.recordFields(tree))) : tree.defs; memberEnter.memberEnter(defsToEnter, env); - if ((tree.mods.flags & RECORD) != 0) { - if ((tree.mods.flags & (RECORD | ABSTRACT)) == RECORD) { - addRecordMembersIfNeeded(tree, env, defaultConstructorGenerated); - } + if (isRecord) { + addRecordMembersIfNeeded(tree, env, defaultConstructorGenerated); addAccessorsIfNeeded(tree, env); + //List<JCVariableDecl> recordFields = TreeInfo.recordFields(tree); } if (tree.sym.isAnnotationType()) { @@ -1130,7 +1130,7 @@ Type accessorType = accessor.fst.accessorType(syms, tree.sym.type); MethodSymbol implSym = lookupMethod(env.enclClass.sym, accessor.snd, accessorType.getParameterTypes()); if (implSym == null || (implSym.flags_field & MANDATED) != 0) { - JCMethodDecl getter = make.at(tree.pos).MethodDef(make.Modifiers(Flags.PUBLIC | Flags.MANDATED), + JCMethodDecl getter = make.at(tree.pos).MethodDef(make.Modifiers(Flags.PUBLIC | Flags.MANDATED, tree.mods.annotations), accessor.snd, make.Type(accessorType.getReturnType()), List.nil(), @@ -1213,7 +1213,7 @@ null : canonicalDecl.sym; if (canonicalInit == null) { - RecordConstructorHelper helper = new RecordConstructorHelper(tree.sym, TreeInfo.recordFields(tree).map(vd -> vd.sym)); + RecordConstructorHelper helper = new RecordConstructorHelper(tree.sym, TreeInfo.recordFields(tree)); JCTree constrDef = defaultConstructor(make.at(tree.pos), helper); tree.defs = tree.defs.prepend(constrDef); defaultConstructorGenerated = true; @@ -1314,6 +1314,7 @@ TypeSymbol owner(); List<Name> superArgs(); List<Name> inits(); + default JCMethodDecl finalAdjustment(JCMethodDecl md) { return md; } } class BasicConstructorHelper implements DefaultConstructorHelper { @@ -1435,17 +1436,19 @@ class RecordConstructorHelper extends BasicConstructorHelper { - List<VarSymbol> recordFields; + List<VarSymbol> recordFieldSymbols; + List<JCVariableDecl> recordFieldDecls; - RecordConstructorHelper(TypeSymbol owner, List<VarSymbol> recordFields) { + RecordConstructorHelper(TypeSymbol owner, List<JCVariableDecl> recordFieldDecls) { super(owner); - this.recordFields = recordFields; + this.recordFieldDecls = recordFieldDecls; + this.recordFieldSymbols = recordFieldDecls.map(vd -> vd.sym); } @Override public Type constructorType() { if (constructorType == null) { - List<Type> argtypes = recordFields.map(v -> v.type); + List<Type> argtypes = recordFieldSymbols.map(v -> v.type); constructorType = new MethodType(argtypes, syms.voidType, List.nil(), syms.methodClass); } return constructorType; @@ -1455,8 +1458,8 @@ public MethodSymbol constructorSymbol() { MethodSymbol csym = super.constructorSymbol(); ListBuffer<VarSymbol> params = new ListBuffer<>(); - for (VarSymbol p : recordFields) { - params.add(new VarSymbol(MANDATED | PARAMETER, p.name, p.type, csym)); + for (VarSymbol p : recordFieldSymbols) { + params.add(new VarSymbol(MANDATED | PARAMETER | RECORD, p.name, p.type, csym)); } csym.params = params.toList(); csym.flags_field |= RECORD | PUBLIC; @@ -1465,7 +1468,17 @@ @Override public List<Name> inits() { - return recordFields.map(v -> v.name); + return recordFieldSymbols.map(v -> v.name); + } + + @Override + public JCMethodDecl finalAdjustment(JCMethodDecl md) { + List<JCVariableDecl> tmpRecordFieldDecls = recordFieldDecls; + for (JCVariableDecl arg : md.params) { + arg.mods.annotations = tmpRecordFieldDecls.head.mods.annotations; + tmpRecordFieldDecls = tmpRecordFieldDecls.tail; + } + return md; } } @@ -1488,8 +1501,8 @@ helper.inits().forEach((initName) -> { stats.add(make.Exec(make.Assign(make.Select(make.Ident(names._this), initName), make.Ident(initName)))); }); - JCTree result = make.MethodDef(initSym, make.Block(0, stats.toList())); - return result; + JCMethodDecl result = make.MethodDef(initSym, make.Block(0, stats.toList())); + return helper.finalAdjustment(result); } /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Jul 12 18:50:44 2019 +0000 @@ -3823,7 +3823,7 @@ if (mods.flags != 0) { log.error(mods.pos, Errors.RecordCantDeclareFieldModifiers); } - mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE; + mods.flags |= Flags.RECORD | Flags.FINAL | Flags.PRIVATE | Flags.MANDATED; JCExpression type = parseType(); int pos = token.pos; Name id = ident();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Jul 10 06:10:38 2019 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Jul 12 18:50:44 2019 +0000 @@ -924,6 +924,24 @@ } } + /** If this tree has a modifiers field, return it otherwise return null + */ + public static JCModifiers getModifiers(JCTree tree) { + tree = skipParens(tree); + switch (tree.getTag()) { + case VARDEF: + return ((JCVariableDecl) tree).mods; + case METHODDEF: + return ((JCMethodDecl) tree).mods; + case CLASSDEF: + return ((JCClassDecl) tree).mods; + case MODULEDEF: + return ((JCModuleDecl) tree).mods; + default: + return null; + } + } + /** Return true if this is a nonstatic selection. */ public static boolean nonstaticSelect(JCTree tree) { tree = skipParens(tree);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/records/annotations/BadAnnotations.java Fri Jul 12 18:50:44 2019 +0000 @@ -0,0 +1,49 @@ +/* + * @test /nodynamiccopyright/ + * @summary bad declaration annotations on records + * @compile/fail/ref=BadAnnotations.out -XDrawDiagnostics BadAnnotations.java + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +class BadAnnotations { + @Target({ ElementType.CONSTRUCTOR }) + @interface Foo1 {} + record R1(@Foo1 int i) {} + + @Target({ ElementType.TYPE }) + @interface Foo2 {} + record R2(@Foo2 int i) {} + + @Target({ ElementType.LOCAL_VARIABLE }) + @interface Foo3 {} + record R3(@Foo3 int i) {} + + @Target({ ElementType.PACKAGE }) + @interface Foo4 {} + record R4(@Foo4 int i) {} + + @Target({ ElementType.MODULE }) + @interface Foo5 {} + record R5(@Foo5 int i) {} + + // positive cases + @Target({ ElementType.FIELD }) + @interface Foo6 {} + record R6(@Foo6 int i) {} + + @Target({ ElementType.METHOD }) + @interface Foo7 {} + record R7(@Foo7 int i) {} + + @Target({ ElementType.PARAMETER }) + @interface Foo8 {} + record R8(@Foo8 int i) {} + + // no target applies to all + @interface Foo9 {} + record R9(@Foo9 int i) {} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/langtools/tools/javac/records/annotations/BadAnnotations.out Fri Jul 12 18:50:44 2019 +0000 @@ -0,0 +1,6 @@ +BadAnnotations.java:15:15: compiler.err.annotation.type.not.applicable +BadAnnotations.java:19:15: compiler.err.annotation.type.not.applicable +BadAnnotations.java:23:15: compiler.err.annotation.type.not.applicable +BadAnnotations.java:27:15: compiler.err.annotation.type.not.applicable +BadAnnotations.java:31:15: compiler.err.annotation.type.not.applicable +5 errors