1 /*
   2  * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @summary Verify type annotation on binding patterns
  27  * @library /tools/lib
  28  * @modules java.compiler
  29  *          jdk.jdeps/com.sun.tools.javap
  30  * @build toolbox.JavapTask
  31  * @compile --enable-preview -source ${jdk.version} Patterns.java
  32  * @run main/othervm --enable-preview Patterns
  33  */
  34 
  35 import java.lang.annotation.*;
  36 import java.util.regex.Matcher;
  37 import java.util.regex.Pattern;
  38 import java.util.stream.Collectors;
  39 
  40 import toolbox.JavapTask;
  41 import toolbox.Task;
  42 import toolbox.ToolBox;
  43 
  44 public class Patterns {
  45 
  46     private ToolBox tb = new ToolBox();
  47 
  48     public static void main(String[] args) throws Exception {
  49         new Patterns().run();
  50     }
  51 
  52     public void run() throws Exception {
  53         String out = new JavapTask(tb)
  54                 .options("-private",
  55                          "-verbose")
  56                 .classpath(System.getProperty("test.classes"))
  57                 .classes("Patterns$SimpleBindingPattern")
  58                 .run()
  59                 .getOutputLines(Task.OutputKind.DIRECT)
  60                 .stream()
  61                 .collect(Collectors.joining("\n"));
  62 
  63         String constantPool = out.substring(0, out.indexOf('{'));
  64 
  65         out = out.replaceAll("(?ms) *Code:.*?\n( *RuntimeInvisibleTypeAnnotations:)", "$1");
  66         out = out.substring(out.indexOf('{'));
  67         out = out.substring(0, out.lastIndexOf('}') + 1);
  68 
  69         String A = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$A;");
  70         String CA = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$CA;");
  71         String value = snipCPNumber(constantPool, "value");
  72 
  73         String expected = """
  74                           {
  75                             private static final java.lang.Object o;
  76                               descriptor: Ljava/lang/Object;
  77                               flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
  78 
  79                             private static final boolean B1s;
  80                               descriptor: Z
  81                               flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
  82 
  83                             private static final boolean B1m;
  84                               descriptor: Z
  85                               flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL
  86 
  87                             private final boolean B2s;
  88                               descriptor: Z
  89                               flags: (0x0012) ACC_PRIVATE, ACC_FINAL
  90 
  91                             private final boolean B2m;
  92                               descriptor: Z
  93                               flags: (0x0012) ACC_PRIVATE, ACC_FINAL
  94 
  95                             public Patterns$SimpleBindingPattern();
  96                               descriptor: ()V
  97                               flags: (0x0001) ACC_PUBLIC
  98                                 RuntimeInvisibleTypeAnnotations:
  99                                   0: #_A_(): LOCAL_VARIABLE, {start_pc=206, length=11, index=2}
 100                                     Patterns$SimpleBindingPattern$A
 101                                   1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=238, length=11, index=3}
 102                                     Patterns$SimpleBindingPattern$CA(
 103                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 104                                     )
 105                                   2: #_A_(): LOCAL_VARIABLE, {start_pc=21, length=11, index=1}
 106                                     Patterns$SimpleBindingPattern$A
 107                                   3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=53, length=11, index=1}
 108                                     Patterns$SimpleBindingPattern$CA(
 109                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 110                                     )
 111                                   4: #_A_(): LOCAL_VARIABLE, {start_pc=84, length=11, index=2}
 112                                     Patterns$SimpleBindingPattern$A
 113                                   5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=116, length=11, index=3}
 114                                     Patterns$SimpleBindingPattern$CA(
 115                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 116                                     )
 117                                   6: #_A_(): LOCAL_VARIABLE, {start_pc=145, length=11, index=2}
 118                                     Patterns$SimpleBindingPattern$A
 119                                   7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=177, length=11, index=3}
 120                                     Patterns$SimpleBindingPattern$CA(
 121                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 122                                     )
 123 
 124                             void testPatterns();
 125                               descriptor: ()V
 126                               flags: (0x0000)
 127                                 RuntimeInvisibleTypeAnnotations:
 128                                   0: #_A_(): LOCAL_VARIABLE, {start_pc=16, length=11, index=2}
 129                                     Patterns$SimpleBindingPattern$A
 130                                   1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=48, length=11, index=3}
 131                                     Patterns$SimpleBindingPattern$CA(
 132                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 133                                     )
 134 
 135                             void testPatternsDesugared();
 136                               descriptor: ()V
 137                               flags: (0x0000)
 138                                 RuntimeInvisibleTypeAnnotations:
 139                                   0: #_A_(): LOCAL_VARIABLE, {start_pc=17, length=15, index=1; start_pc=51, length=15, index=1}
 140                                     Patterns$SimpleBindingPattern$A
 141 
 142                             static {};
 143                               descriptor: ()V
 144                               flags: (0x0008) ACC_STATIC
 145                                 RuntimeInvisibleTypeAnnotations:
 146                                   0: #_A_(): LOCAL_VARIABLE, {start_pc=21, length=11, index=0}
 147                                     Patterns$SimpleBindingPattern$A
 148                                   1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=52, length=11, index=0}
 149                                     Patterns$SimpleBindingPattern$CA(
 150                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 151                                     )
 152                                   2: #_A_(): LOCAL_VARIABLE, {start_pc=83, length=11, index=1}
 153                                     Patterns$SimpleBindingPattern$A
 154                                   3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=112, length=11, index=2}
 155                                     Patterns$SimpleBindingPattern$CA(
 156                                       value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A]
 157                                     )
 158                           }""".replace("_A_", A).replace("_CA_", CA).replace("_value_", value);
 159 
 160         if (!expected.equals(out)) {
 161             throw new AssertionError("Unexpected output:\n" + out + "\nexpected:\n" + expected);
 162         }
 163     }
 164 
 165     private String snipCPNumber(String constantPool, String expectedConstant) {
 166         Matcher m = Pattern.compile("#([0-9]+).*" + Pattern.quote(expectedConstant))
 167                            .matcher(constantPool);
 168         if (!m.find()) {
 169             throw new AssertionError("Cannot find constant pool item");
 170         }
 171 
 172         return m.group(1);
 173     }
 174 
 175     /*********************** Test class *************************/
 176     static class SimpleBindingPattern {
 177         @Target(ElementType.TYPE_USE)
 178         @Repeatable(CA.class)
 179         @interface A {}
 180         @Target(ElementType.TYPE_USE)
 181         @interface CA {
 182             public A[] value();
 183         }
 184 
 185         private static final Object o = "";
 186         private static final boolean B1s = o instanceof @A String s && s.isEmpty();
 187         private static final boolean B1m = o instanceof @A @A String s && s.isEmpty();
 188         private final boolean B2s = o instanceof @A String s && s.isEmpty();
 189         private final boolean B2m = o instanceof @A @A String s && s.isEmpty();
 190 
 191         static {
 192             boolean B3s = o instanceof @A String s && s.isEmpty();
 193             boolean B3m = o instanceof @A @A String s && s.isEmpty();
 194         }
 195 
 196         {
 197             boolean B4s = o instanceof @A String s && s.isEmpty();
 198             boolean B4m = o instanceof @A @A String s && s.isEmpty();
 199         }
 200 
 201         {
 202             boolean B5s = o instanceof @A String s && s.isEmpty();
 203             boolean B5m = o instanceof @A @A String s && s.isEmpty();
 204         }
 205 
 206         public SimpleBindingPattern() {
 207             boolean B6s = o instanceof @A String s && s.isEmpty();
 208             boolean B6m = o instanceof @A @A String s && s.isEmpty();
 209         }
 210 
 211         void testPatterns() {
 212             boolean B7s = o instanceof @A String s && s.isEmpty();
 213             boolean B7m = o instanceof @A @A String s && s.isEmpty();
 214         }
 215 
 216         void testPatternsDesugared() {
 217             @A String s;
 218             boolean B8s = o instanceof String && (s = (String) o) == s && s.isEmpty();
 219             boolean B8sx = o instanceof String && (s = (String) o) == s && s.isEmpty();
 220         }
 221     }
 222 }