21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 7115052 8003280 8006694 |
26 * @bug 7115052 8003280 8006694 8129962 |
27 * @summary Add lambda tests |
27 * @summary Add lambda tests |
28 * Add parser support for method references |
28 * Add parser support for method references |
29 * temporarily workaround combo tests are causing time out in several platforms |
29 * temporarily workaround combo tests are causing time out in several platforms |
30 * @library ../lib |
30 * @library /tools/javac/lib |
31 * @modules jdk.compiler |
31 * @modules jdk.compiler/com.sun.tools.javac.api |
32 * @build JavacTestingAbstractThreadedTest |
32 * jdk.compiler/com.sun.tools.javac.code |
33 * @run main/othervm MethodReferenceParserTest |
33 * jdk.compiler/com.sun.tools.javac.comp |
|
34 * jdk.compiler/com.sun.tools.javac.main |
|
35 * jdk.compiler/com.sun.tools.javac.tree |
|
36 * jdk.compiler/com.sun.tools.javac.util |
|
37 * @build combo.ComboTestHelper |
|
38 * @run main MethodReferenceParserTest |
34 */ |
39 */ |
35 |
40 |
36 // use /othervm to avoid jtreg timeout issues (CODETOOLS-7900047) |
41 import java.io.IOException; |
37 // see JDK-8006746 |
42 |
38 |
43 import combo.ComboInstance; |
39 import java.net.URI; |
44 import combo.ComboParameter; |
40 import java.util.Arrays; |
45 import combo.ComboTask.Result; |
41 import javax.tools.Diagnostic; |
46 import combo.ComboTestHelper; |
42 import javax.tools.JavaFileObject; |
47 |
43 import javax.tools.SimpleJavaFileObject; |
48 public class MethodReferenceParserTest extends ComboInstance<MethodReferenceParserTest> { |
44 import com.sun.source.util.JavacTask; |
49 |
45 |
50 enum ReferenceKind implements ComboParameter { |
46 public class MethodReferenceParserTest |
51 METHOD_REF("#{QUAL}::#{TARGS}m"), |
47 extends JavacTestingAbstractThreadedTest |
52 CONSTRUCTOR_REF("#{QUAL}::#{TARGS}new"), |
48 implements Runnable { |
|
49 |
|
50 enum ReferenceKind { |
|
51 METHOD_REF("#Q::#Gm"), |
|
52 CONSTRUCTOR_REF("#Q::#Gnew"), |
|
53 FALSE_REF("min < max"), |
53 FALSE_REF("min < max"), |
54 ERR_SUPER("#Q::#Gsuper"), |
54 ERR_SUPER("#{QUAL}::#{TARGS}super"), |
55 ERR_METH0("#Q::#Gm()"), |
55 ERR_METH0("#{QUAL}::#{TARGS}m()"), |
56 ERR_METH1("#Q::#Gm(X)"), |
56 ERR_METH1("#{QUAL}::#{TARGS}m(X)"), |
57 ERR_CONSTR0("#Q::#Gnew()"), |
57 ERR_CONSTR0("#{QUAL}::#{TARGS}new()"), |
58 ERR_CONSTR1("#Q::#Gnew(X)"); |
58 ERR_CONSTR1("#{QUAL}::#{TARGS}new(X)"); |
59 |
59 |
60 String referenceTemplate; |
60 String referenceTemplate; |
61 |
61 |
62 ReferenceKind(String referenceTemplate) { |
62 ReferenceKind(String referenceTemplate) { |
63 this.referenceTemplate = referenceTemplate; |
63 this.referenceTemplate = referenceTemplate; |
64 } |
|
65 |
|
66 String getReferenceString(QualifierKind qk, GenericKind gk) { |
|
67 return referenceTemplate |
|
68 .replaceAll("#Q", qk.qualifier) |
|
69 .replaceAll("#G", gk.typeParameters); |
|
70 } |
64 } |
71 |
65 |
72 boolean erroneous() { |
66 boolean erroneous() { |
73 switch (this) { |
67 switch (this) { |
74 case ERR_SUPER: |
68 case ERR_SUPER: |
78 case ERR_CONSTR1: |
72 case ERR_CONSTR1: |
79 return true; |
73 return true; |
80 default: return false; |
74 default: return false; |
81 } |
75 } |
82 } |
76 } |
83 } |
77 |
84 |
78 @Override |
85 enum ContextKind { |
79 public String expand(String optParameter) { |
86 ASSIGN("SAM s = #E;"), |
80 return referenceTemplate; |
87 METHOD("m(#E, i);"); |
81 } |
|
82 } |
|
83 |
|
84 enum ContextKind implements ComboParameter { |
|
85 ASSIGN("SAM s = #{EXPR};"), |
|
86 METHOD("m(#{EXPR}, i);"); |
88 |
87 |
89 String contextTemplate; |
88 String contextTemplate; |
90 |
89 |
91 ContextKind(String contextTemplate) { |
90 ContextKind(String contextTemplate) { |
92 this.contextTemplate = contextTemplate; |
91 this.contextTemplate = contextTemplate; |
93 } |
92 } |
94 |
93 |
95 String contextString(ExprKind ek, ReferenceKind rk, QualifierKind qk, |
94 @Override |
96 GenericKind gk, SubExprKind sk) { |
95 public String expand(String optParameter) { |
97 return contextTemplate.replaceAll("#E", ek.expressionString(rk, qk, gk, sk)); |
96 return contextTemplate; |
98 } |
97 } |
99 } |
98 } |
100 |
99 |
101 enum GenericKind { |
100 enum GenericKind implements ComboParameter { |
102 NONE(""), |
101 NONE(""), |
103 ONE("<X>"), |
102 ONE("<X>"), |
104 TWO("<X,Y>"); |
103 TWO("<X,Y>"); |
105 |
104 |
106 String typeParameters; |
105 String typeParameters; |
107 |
106 |
108 GenericKind(String typeParameters) { |
107 GenericKind(String typeParameters) { |
109 this.typeParameters = typeParameters; |
108 this.typeParameters = typeParameters; |
110 } |
109 } |
111 } |
110 |
112 |
111 @Override |
113 enum QualifierKind { |
112 public String expand(String optParameter) { |
|
113 return typeParameters; |
|
114 } |
|
115 } |
|
116 |
|
117 enum QualifierKind implements ComboParameter { |
114 THIS("this"), |
118 THIS("this"), |
115 SUPER("super"), |
119 SUPER("super"), |
116 NEW("new Foo()"), |
120 NEW("new Foo()"), |
117 METHOD("m()"), |
121 METHOD("m()"), |
118 FIELD("a.f"), |
122 FIELD("a.f"), |
129 String qualifier; |
133 String qualifier; |
130 |
134 |
131 QualifierKind(String qualifier) { |
135 QualifierKind(String qualifier) { |
132 this.qualifier = qualifier; |
136 this.qualifier = qualifier; |
133 } |
137 } |
134 } |
138 |
135 |
139 @Override |
136 enum ExprKind { |
140 public String expand(String optParameter) { |
137 NONE("#R::S"), |
141 return qualifier; |
138 SINGLE_PAREN1("(#R#S)"), |
142 } |
139 SINGLE_PAREN2("(#R)#S"), |
143 } |
140 DOUBLE_PAREN1("((#R#S))"), |
144 |
141 DOUBLE_PAREN2("((#R)#S)"), |
145 enum ExprKind implements ComboParameter { |
142 DOUBLE_PAREN3("((#R))#S"); |
146 NONE("#{MREF}"), |
|
147 SINGLE_PAREN1("(#{MREF}#{SUBEXPR})"), |
|
148 SINGLE_PAREN2("(#{MREF})#{SUBEXPR}"), |
|
149 DOUBLE_PAREN1("((#{MREF}#{SUBEXPR}))"), |
|
150 DOUBLE_PAREN2("((#{MREF})#{SUBEXPR})"), |
|
151 DOUBLE_PAREN3("((#{MREF}))#{SUBEXPR}"); |
143 |
152 |
144 String expressionTemplate; |
153 String expressionTemplate; |
145 |
154 |
146 ExprKind(String expressionTemplate) { |
155 ExprKind(String expressionTemplate) { |
147 this.expressionTemplate = expressionTemplate; |
156 this.expressionTemplate = expressionTemplate; |
148 } |
157 } |
149 |
158 |
150 String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) { |
159 @Override |
151 return expressionTemplate |
160 public String expand(String optParameter) { |
152 .replaceAll("#R", rk.getReferenceString(qk, gk)) |
161 return expressionTemplate; |
153 .replaceAll("#S", sk.subExpression); |
162 } |
154 } |
163 } |
155 } |
164 |
156 |
165 enum SubExprKind implements ComboParameter { |
157 enum SubExprKind { |
|
158 NONE(""), |
166 NONE(""), |
159 SELECT_FIELD(".f"), |
167 SELECT_FIELD(".f"), |
160 SELECT_METHOD(".f()"), |
168 SELECT_METHOD(".f()"), |
161 SELECT_NEW(".new Foo()"), |
169 SELECT_NEW(".new Foo()"), |
162 POSTINC("++"), |
170 POSTINC("++"), |
165 String subExpression; |
173 String subExpression; |
166 |
174 |
167 SubExprKind(String subExpression) { |
175 SubExprKind(String subExpression) { |
168 this.subExpression = subExpression; |
176 this.subExpression = subExpression; |
169 } |
177 } |
|
178 |
|
179 @Override |
|
180 public String expand(String optParameter) { |
|
181 return subExpression; |
|
182 } |
170 } |
183 } |
171 |
184 |
172 public static void main(String... args) throws Exception { |
185 public static void main(String... args) throws Exception { |
173 for (ReferenceKind rk : ReferenceKind.values()) { |
186 new ComboTestHelper<MethodReferenceParserTest>() |
174 for (QualifierKind qk : QualifierKind.values()) { |
187 .withDimension("MREF", (x, ref) -> x.rk = ref, ReferenceKind.values()) |
175 for (GenericKind gk : GenericKind.values()) { |
188 .withDimension("QUAL", QualifierKind.values()) |
176 for (SubExprKind sk : SubExprKind.values()) { |
189 .withDimension("TARGS", GenericKind.values()) |
177 for (ExprKind ek : ExprKind.values()) { |
190 .withDimension("EXPR", ExprKind.values()) |
178 for (ContextKind ck : ContextKind.values()) { |
191 .withDimension("SUBEXPR", SubExprKind.values()) |
179 pool.execute(new MethodReferenceParserTest(rk, qk, gk, sk, ek, ck)); |
192 .withDimension("CTX", ContextKind.values()) |
180 } |
193 .run(MethodReferenceParserTest::new); |
181 } |
|
182 } |
|
183 } |
|
184 } |
|
185 } |
|
186 |
|
187 checkAfterExec(); |
|
188 } |
194 } |
189 |
195 |
190 ReferenceKind rk; |
196 ReferenceKind rk; |
191 QualifierKind qk; |
197 |
192 GenericKind gk; |
198 String template = "class Test {\n" + |
193 SubExprKind sk; |
199 " void test() {\n" + |
194 ExprKind ek; |
200 " #{CTX}\n" + |
195 ContextKind ck; |
201 " }" + |
196 JavaSource source; |
202 "}"; |
197 DiagnosticChecker diagChecker; |
|
198 |
|
199 MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek, ContextKind ck) { |
|
200 this.rk = rk; |
|
201 this.qk = qk; |
|
202 this.gk = gk; |
|
203 this.sk = sk; |
|
204 this.ek = ek; |
|
205 this.ck = ck; |
|
206 this.source = new JavaSource(); |
|
207 this.diagChecker = new DiagnosticChecker(); |
|
208 } |
|
209 |
|
210 class JavaSource extends SimpleJavaFileObject { |
|
211 |
|
212 String template = "class Test {\n" + |
|
213 " void test() {\n" + |
|
214 " #C\n" + |
|
215 " }" + |
|
216 "}"; |
|
217 |
|
218 String source; |
|
219 |
|
220 public JavaSource() { |
|
221 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
|
222 source = template.replaceAll("#C", ck.contextString(ek, rk, qk, gk, sk)); |
|
223 } |
|
224 |
|
225 @Override |
|
226 public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
|
227 return source; |
|
228 } |
|
229 } |
|
230 |
203 |
231 @Override |
204 @Override |
232 public void run() { |
205 public void doWork() throws IOException { |
233 JavacTask ct = (JavacTask)comp.getTask(null, fm.get(), diagChecker, |
206 check(newCompilationTask() |
234 null, null, Arrays.asList(source)); |
207 .withSourceFromTemplate(template) |
235 try { |
208 .parse()); |
236 ct.parse(); |
209 } |
237 } catch (Throwable ex) { |
210 |
238 processException(ex); |
211 void check(Result<?> res) { |
239 return; |
212 if (res.hasErrors() != rk.erroneous()) { |
240 } |
213 fail("invalid diagnostics for source:\n" + |
241 check(); |
214 res.compilationInfo() + |
242 } |
215 "\nFound error: " + res.hasErrors() + |
243 |
|
244 void check() { |
|
245 checkCount.incrementAndGet(); |
|
246 |
|
247 if (diagChecker.errorFound != rk.erroneous()) { |
|
248 throw new Error("invalid diagnostics for source:\n" + |
|
249 source.getCharContent(true) + |
|
250 "\nFound error: " + diagChecker.errorFound + |
|
251 "\nExpected error: " + rk.erroneous()); |
216 "\nExpected error: " + rk.erroneous()); |
252 } |
217 } |
253 } |
218 } |
254 |
|
255 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
|
256 |
|
257 boolean errorFound; |
|
258 |
|
259 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
|
260 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { |
|
261 errorFound = true; |
|
262 } |
|
263 } |
|
264 } |
|
265 |
|
266 } |
219 } |