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 * @run main Patterns 32 */ 33 34 import java.lang.annotation.*; 35 import java.util.regex.Matcher; 36 import java.util.regex.Pattern; 37 import java.util.stream.Collectors; 38 39 import toolbox.JavapTask; 40 import toolbox.Task; 41 import toolbox.ToolBox; 42 43 public class Patterns { 44 45 private ToolBox tb = new ToolBox(); 46 main(String[] args)47 public static void main(String[] args) throws Exception { 48 new Patterns().run(); 49 } 50 run()51 public void run() throws Exception { 52 String out = new JavapTask(tb) 53 .options("-private", 54 "-verbose") 55 .classpath(System.getProperty("test.classes")) 56 .classes("Patterns$SimpleBindingPattern") 57 .run() 58 .getOutputLines(Task.OutputKind.DIRECT) 59 .stream() 60 .collect(Collectors.joining("\n")); 61 62 String constantPool = out.substring(0, out.indexOf('{')); 63 64 out = out.replaceAll("(?ms) *Code:.*?\n( *RuntimeInvisibleTypeAnnotations:)", "$1"); 65 out = out.substring(out.indexOf('{')); 66 out = out.substring(0, out.lastIndexOf('}') + 1); 67 68 String A = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$A;"); 69 String CA = snipCPNumber(constantPool, "LPatterns$SimpleBindingPattern$CA;"); 70 String value = snipCPNumber(constantPool, "value"); 71 72 String expected = """ 73 { 74 private static final java.lang.Object o; 75 descriptor: Ljava/lang/Object; 76 flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL 77 78 private static final boolean B1s; 79 descriptor: Z 80 flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL 81 82 private static final boolean B1m; 83 descriptor: Z 84 flags: (0x001a) ACC_PRIVATE, ACC_STATIC, ACC_FINAL 85 86 private final boolean B2s; 87 descriptor: Z 88 flags: (0x0012) ACC_PRIVATE, ACC_FINAL 89 90 private final boolean B2m; 91 descriptor: Z 92 flags: (0x0012) ACC_PRIVATE, ACC_FINAL 93 94 public Patterns$SimpleBindingPattern(); 95 descriptor: ()V 96 flags: (0x0001) ACC_PUBLIC 97 RuntimeInvisibleTypeAnnotations: 98 0: #_A_(): LOCAL_VARIABLE, {start_pc=206, length=11, index=2} 99 Patterns$SimpleBindingPattern$A 100 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=238, length=11, index=3} 101 Patterns$SimpleBindingPattern$CA( 102 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 103 ) 104 2: #_A_(): LOCAL_VARIABLE, {start_pc=21, length=11, index=1} 105 Patterns$SimpleBindingPattern$A 106 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=53, length=11, index=1} 107 Patterns$SimpleBindingPattern$CA( 108 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 109 ) 110 4: #_A_(): LOCAL_VARIABLE, {start_pc=84, length=11, index=2} 111 Patterns$SimpleBindingPattern$A 112 5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=116, length=11, index=3} 113 Patterns$SimpleBindingPattern$CA( 114 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 115 ) 116 6: #_A_(): LOCAL_VARIABLE, {start_pc=145, length=11, index=2} 117 Patterns$SimpleBindingPattern$A 118 7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=177, length=11, index=3} 119 Patterns$SimpleBindingPattern$CA( 120 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 121 ) 122 123 void testPatterns(); 124 descriptor: ()V 125 flags: (0x0000) 126 RuntimeInvisibleTypeAnnotations: 127 0: #_A_(): LOCAL_VARIABLE, {start_pc=16, length=11, index=2} 128 Patterns$SimpleBindingPattern$A 129 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=48, length=11, index=3} 130 Patterns$SimpleBindingPattern$CA( 131 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 132 ) 133 134 void testPatternsDesugared(); 135 descriptor: ()V 136 flags: (0x0000) 137 RuntimeInvisibleTypeAnnotations: 138 0: #_A_(): LOCAL_VARIABLE, {start_pc=17, length=15, index=1; start_pc=51, length=15, index=1} 139 Patterns$SimpleBindingPattern$A 140 141 static {}; 142 descriptor: ()V 143 flags: (0x0008) ACC_STATIC 144 RuntimeInvisibleTypeAnnotations: 145 0: #_A_(): LOCAL_VARIABLE, {start_pc=21, length=11, index=0} 146 Patterns$SimpleBindingPattern$A 147 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=52, length=11, index=0} 148 Patterns$SimpleBindingPattern$CA( 149 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 150 ) 151 2: #_A_(): LOCAL_VARIABLE, {start_pc=83, length=11, index=1} 152 Patterns$SimpleBindingPattern$A 153 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=112, length=11, index=2} 154 Patterns$SimpleBindingPattern$CA( 155 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] 156 ) 157 }""".replace("_A_", A).replace("_CA_", CA).replace("_value_", value); 158 159 if (!expected.equals(out)) { 160 throw new AssertionError("Unexpected output:\n" + out + "\nexpected:\n" + expected); 161 } 162 } 163 snipCPNumber(String constantPool, String expectedConstant)164 private String snipCPNumber(String constantPool, String expectedConstant) { 165 Matcher m = Pattern.compile("#([0-9]+).*" + Pattern.quote(expectedConstant)) 166 .matcher(constantPool); 167 if (!m.find()) { 168 throw new AssertionError("Cannot find constant pool item"); 169 } 170 171 return m.group(1); 172 } 173 174 /*********************** Test class *************************/ 175 static class SimpleBindingPattern { 176 @Target(ElementType.TYPE_USE) 177 @Repeatable(CA.class) 178 @interface A {} 179 @Target(ElementType.TYPE_USE) 180 @interface CA { value()181 public A[] value(); 182 } 183 184 private static final Object o = ""; 185 private static final boolean B1s = o instanceof @A String s && s.isEmpty(); 186 private static final boolean B1m = o instanceof @A @A String s && s.isEmpty(); 187 private final boolean B2s = o instanceof @A String s && s.isEmpty(); 188 private final boolean B2m = o instanceof @A @A String s && s.isEmpty(); 189 190 static { 191 boolean B3s = o instanceof @A String s && s.isEmpty(); 192 boolean B3m = o instanceof @A @A String s && s.isEmpty(); 193 } 194 195 { 196 boolean B4s = o instanceof @A String s && s.isEmpty(); 197 boolean B4m = o instanceof @A @A String s && s.isEmpty(); 198 } 199 200 { 201 boolean B5s = o instanceof @A String s && s.isEmpty(); 202 boolean B5m = o instanceof @A @A String s && s.isEmpty(); 203 } 204 SimpleBindingPattern()205 public SimpleBindingPattern() { 206 boolean B6s = o instanceof @A String s && s.isEmpty(); 207 boolean B6m = o instanceof @A @A String s && s.isEmpty(); 208 } 209 testPatterns()210 void testPatterns() { 211 boolean B7s = o instanceof @A String s && s.isEmpty(); 212 boolean B7m = o instanceof @A @A String s && s.isEmpty(); 213 } 214 testPatternsDesugared()215 void testPatternsDesugared() { 216 @A String s; 217 boolean B8s = o instanceof String && (s = (String) o) == s && s.isEmpty(); 218 boolean B8sx = o instanceof String && (s = (String) o) == s && s.isEmpty(); 219 } 220 } 221 } 222