|
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=257, length=18, index=2} |
|
100 Patterns$SimpleBindingPattern$A |
|
101 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=297, length=19, index=3} |
|
102 Patterns$SimpleBindingPattern$CA( |
|
103 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] |
|
104 ) |
|
105 2: #_A_(): LOCAL_VARIABLE, {start_pc=22, length=18, index=1} |
|
106 Patterns$SimpleBindingPattern$A |
|
107 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=18, index=1} |
|
108 Patterns$SimpleBindingPattern$CA( |
|
109 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] |
|
110 ) |
|
111 4: #_A_(): LOCAL_VARIABLE, {start_pc=101, length=18, index=2} |
|
112 Patterns$SimpleBindingPattern$A |
|
113 5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=141, length=19, index=3} |
|
114 Patterns$SimpleBindingPattern$CA( |
|
115 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] |
|
116 ) |
|
117 6: #_A_(): LOCAL_VARIABLE, {start_pc=179, length=18, index=2} |
|
118 Patterns$SimpleBindingPattern$A |
|
119 7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=219, length=19, 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=17, length=18, index=2} |
|
129 Patterns$SimpleBindingPattern$A |
|
130 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=57, length=19, 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=22, length=18, index=0} |
|
147 Patterns$SimpleBindingPattern$A |
|
148 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=61, length=18, index=0} |
|
149 Patterns$SimpleBindingPattern$CA( |
|
150 value=[@Patterns$SimpleBindingPattern$A,@Patterns$SimpleBindingPattern$A] |
|
151 ) |
|
152 2: #_A_(): LOCAL_VARIABLE, {start_pc=100, length=18, index=1} |
|
153 Patterns$SimpleBindingPattern$A |
|
154 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=137, length=18, 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 } |