changeset 58509:ef9c7edce2ec records

additional refactorings, changing timing of checkings
author vromero
date Thu, 24 Oct 2019 15:55:56 -0400
parents 6f36468c551a
children 48d4397ef025
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java test/langtools/tools/javac/AnonymousClass/AnonymousClassFlags.java test/langtools/tools/javac/processing/model/element/PersonalBest.java test/langtools/tools/javac/processing/model/element/TestRecord.java test/langtools/tools/javac/records/BadRecord.java test/langtools/tools/javac/records/RecordMemberTests.java test/langtools/tools/javac/records/VarargsRecordsTest.java test/langtools/tools/javac/records/writeread/WriteReadTest.java
diffstat 10 files changed, 62 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Oct 24 15:55:56 2019 -0400
@@ -1039,6 +1039,20 @@
 
             if (env.enclClass.sym.isRecord() && tree.sym.owner.kind == TYP) {
                 chk.checkForSerializationMethods(env, tree);
+                Optional<? extends RecordComponent> recordComponent = env.enclClass.sym.getRecordComponents().stream()
+                        .filter(rc -> rc.accessor == tree.sym && (rc.accessor.flags_field & MANDATED) == 0).findFirst();
+                if (recordComponent.isPresent()) {
+                    // the method is a user defined accessor lets check that everything is fine
+                    if ((tree.sym.flags() & Flags.PUBLIC) == 0) {
+                        log.error(tree, Errors.MethodMustBePublic(tree.sym.name));
+                    }
+                    if (!types.isSameType(tree.sym.type.getReturnType(), recordComponent.get().type)) {
+                        log.error(tree, Errors.AccessorReturnTypeDoesntMatch(recordComponent.get().type, tree.sym.type));
+                    }
+                    if (tree.sym.type.asMethodType().thrown.stream().anyMatch(exc -> !isUnchecked(exc))) {
+                        log.error(tree, Errors.MethodCantThrowCheckedException);
+                    }
+                }
             }
 
             // annotation method checks
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Thu Oct 24 15:55:56 2019 -0400
@@ -31,7 +31,6 @@
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Kinds.KindSelector;
 import com.sun.tools.javac.code.Scope.WriteableScope;
-import com.sun.tools.javac.comp.Resolve.MethodResolutionContext;
 import com.sun.tools.javac.jvm.*;
 import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant;
 import com.sun.tools.javac.main.Option.PkgInfo;
@@ -800,21 +799,6 @@
         return rs.resolveInternalMethod(pos, attrEnv, qual, name, args, List.nil());
     }
 
-    private Symbol findMethodOrFailSilently(
-            DiagnosticPosition pos,
-            Env<AttrContext> env,
-            Type site,
-            Name name,
-            List<Type> argtypes,
-            List<Type> typeargtypes) {
-        MethodResolutionContext resolveContext = rs.new MethodResolutionContext();
-        resolveContext.internalResolution = true;
-        resolveContext.silentFail = true;
-        Symbol sym = rs.resolveQualifiedMethod(resolveContext, pos, env, site.tsym,
-                site, name, argtypes, typeargtypes);
-        return sym;
-    }
-
     /** Anon inner classes are used as access constructor tags.
      * accessConstructorTag will use an existing anon class if one is available,
      * and synthethise a class (with makeEmptyClass) if one is not available.
@@ -2274,7 +2258,7 @@
         result = make_at(tree.pos()).Block(SYNTHETIC, List.nil());
     }
 
-    List<JCTree> accessors(JCClassDecl tree) {
+    List<JCTree> generateMandatedAccessors(JCClassDecl tree) {
         ListBuffer<JCTree> buffer = new ListBuffer<>();
         tree.sym.getRecordComponents().stream()
                 .forEach(rc -> {
@@ -2469,7 +2453,7 @@
             index++;
         }
 
-        tree.defs = tree.defs.appendList(accessors(tree));
+        tree.defs = tree.defs.appendList(generateMandatedAccessors(tree));
         tree.defs = tree.defs.appendList(List.of(
                 generateRecordMethod(tree, names.toString, vars, getterMethHandles),
                 generateRecordMethod(tree, names.hashCode, vars, getterMethHandles),
@@ -2484,7 +2468,13 @@
                 name,
                 tree.sym.type,
                 isEquals ? List.of(syms.objectType) : List.nil());
+        // compiler generated methods have the record flag set, user defined ones dont
         if ((msym.flags() & RECORD) != 0) {
+            /* class java.lang.runtime.ObjectMethods provides a common bootstrap that provides a customized implementation
+             * for methods: toString, hashCode and equals. Here we just need to generate and indy call to:
+             * java.lang.runtime.ObjectMethods::bootstrap and provide: the record class, the record component names and
+             * the accessors.
+             */
             Name bootstrapName = names.bootstrap;
             LoadableConstant[] staticArgsValues = new LoadableConstant[2 + getterMethHandles.length];
             staticArgsValues[0] = (ClassType)tree.sym.type;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Oct 24 15:55:56 2019 -0400
@@ -1016,15 +1016,6 @@
                 memberEnter.memberEnter(getter, env);
                 rec.accessor = getter.sym;
             } else if (implSym != null) {
-                if ((implSym.flags() & Flags.PUBLIC) == 0) {
-                    log.error(TreeInfo.declarationFor(implSym, env.enclClass), Errors.MethodMustBePublic(implSym.name));
-                }
-                if (!types.isSameType(implSym.type.getReturnType(), tree.sym.type)) {
-                    log.error(TreeInfo.declarationFor(implSym, env.enclClass), Errors.AccessorReturnTypeDoesntMatch(tree.sym.type, implSym.type.getReturnType()));
-                }
-                if (implSym.type.asMethodType().thrown.stream().anyMatch(exc -> !isUnchecked(exc))) {
-                    log.error(TreeInfo.declarationFor(implSym, env.enclClass), Errors.MethodCantThrowCheckedException);
-                }
                 rec.accessor = implSym;
             }
         }
--- a/test/langtools/tools/javac/AnonymousClass/AnonymousClassFlags.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/AnonymousClass/AnonymousClassFlags.java	Thu Oct 24 15:55:56 2019 -0400
@@ -26,7 +26,7 @@
  * @bug 8161013
  * @summary Verify that anonymous class binaries have the correct flags set
  * @modules jdk.jdeps/com.sun.tools.classfile
- * @compile AnonymousClassFlags.java
+ * @run main AnonymousClassFlags
  */
 
 import java.util.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/element/PersonalBest.java	Thu Oct 24 15:55:56 2019 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2019, 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.Serializable;
+import java.time.*;
+
+record PersonalBest(Duration marathonTime) implements Serializable {
+    private static final Duration MIN_QUAL_TIME = Duration.ofHours(3);
+    public boolean bostonQualified() {
+        return marathonTime.compareTo(MIN_QUAL_TIME) <= 0;
+    }
+}
--- a/test/langtools/tools/javac/processing/model/element/TestRecord.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/processing/model/element/TestRecord.java	Thu Oct 24 15:55:56 2019 -0400
@@ -23,17 +23,14 @@
 
 /*
  * @test
- * @bug  8888888
  * @summary Test basic modeling of a record type
  * @library /tools/javac/lib
  * @modules jdk.compiler
  * @build JavacTestingAbstractProcessor
- * @compile -source 14 --enable-preview TestRecord.java
- * @compile -J--enable-preview -source 14 --enable-preview -source 14 -processor TestRecord -proc:only --enable-preview -source 14 TestRecord.java
+ * @compile TestRecord.java
+ * @compile -processor TestRecord -proc:only --enable-preview -source ${jdk.version} PersonalBest.java
  */
 
-//@compile -processor TestRecord -proc:only -source 14 --enable-preview TestRecord.java
-
 import java.io.*;
 import javax.annotation.processing.*;
 import javax.lang.model.*;
@@ -64,13 +61,6 @@
        return true;
     }
 
-    static record PersonalBest(Duration marathonTime) implements Serializable {
-        private static final Duration MIN_QUAL_TIME = Duration.ofHours(3);
-        public boolean bostonQualified() {
-            return marathonTime.compareTo(MIN_QUAL_TIME) <= 0;
-        }
-    }
-
     /**
      * Verify that a record modeled as an element behaves as expected
      * under 6 and latest specific visitors.
--- a/test/langtools/tools/javac/records/BadRecord.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/records/BadRecord.java	Thu Oct 24 15:55:56 2019 -0400
@@ -1,7 +1,7 @@
 /*
  * @test /nodynamiccopyright/
  * @summary Verifying error recovery for broken record classes
- * @compile/fail/ref=BadRecord.out --enable-preview -source 14 -XDrawDiagnostics BadRecord.java
+ * @compile/fail/ref=BadRecord.out --enable-preview -source ${jdk.version} -XDrawDiagnostics BadRecord.java
  */
 record BadRecord001 {}
 
--- a/test/langtools/tools/javac/records/RecordMemberTests.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/records/RecordMemberTests.java	Thu Oct 24 15:55:56 2019 -0400
@@ -27,7 +27,7 @@
  * RecordMemberTests
  *
  * @test
- * @compile --enable-preview -source 14 RecordMemberTests.java
+ * @compile --enable-preview -source ${jdk.version} RecordMemberTests.java
  * @run testng/othervm --enable-preview RecordMemberTests
  */
 
--- a/test/langtools/tools/javac/records/VarargsRecordsTest.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/records/VarargsRecordsTest.java	Thu Oct 24 15:55:56 2019 -0400
@@ -36,7 +36,7 @@
  * VarargsRecordsTest
  *
  * @test
- * @compile --enable-preview -source 14 VarargsRecordsTest.java
+ * @compile --enable-preview -source ${jdk.version} VarargsRecordsTest.java
  * @run testng/othervm --enable-preview VarargsRecordsTest
  */
 @Test
--- a/test/langtools/tools/javac/records/writeread/WriteReadTest.java	Thu Oct 24 13:30:00 2019 -0400
+++ b/test/langtools/tools/javac/records/writeread/WriteReadTest.java	Thu Oct 24 15:55:56 2019 -0400
@@ -24,8 +24,8 @@
 /*
  * @test
  * @summary Verify javac can read record classfiles it writes
- * @compile --enable-preview -source 14 Record.java
- * @compile --enable-preview -source 14 WriteReadTest.java
+ * @compile --enable-preview -source ${jdk.version} Record.java
+ * @compile --enable-preview -source ${jdk.version} WriteReadTest.java
  */
 public class WriteReadTest {
     Record1 r1;