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