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 
main(String[] args)48     public static void main(String[] args) throws Exception {
49         new Patterns().run();
50     }
51 
run()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 
snipCPNumber(String constantPool, String expectedConstant)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 {
value()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 
SimpleBindingPattern()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 
testPatterns()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 
testPatternsDesugared()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 }
223