JavacParserTest.java revision 2745:64f03461bb0e
1200062Sed/*
2200062Sed * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
3200062Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4200062Sed *
5200062Sed * This code is free software; you can redistribute it and/or modify it
6200062Sed * under the terms of the GNU General Public License version 2 only, as
7200062Sed * published by the Free Software Foundation.
8200062Sed *
9200062Sed * This code is distributed in the hope that it will be useful, but WITHOUT
10200062Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11200062Sed * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12200062Sed * version 2 for more details (a copy is included in the LICENSE file that
13200062Sed * accompanied this code).
14200062Sed *
15200062Sed * You should have received a copy of the GNU General Public License version
16200062Sed * 2 along with this work; if not, write to the Free Software Foundation,
17200062Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18200062Sed *
19200062Sed * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20200062Sed * or visit www.oracle.com if you need additional information or have any
21200062Sed * questions.
22200062Sed */
23200062Sed
24200062Sed/*
25200062Sed * @test
26200062Sed * @bug 7073631 7159445 7156633 8028235 8065753
27200062Sed * @summary tests error and diagnostics positions
28200062Sed * @author  Jan Lahoda
29200062Sed */
30200062Sed
31200062Sedimport com.sun.source.tree.BinaryTree;
32200062Sedimport com.sun.source.tree.BlockTree;
33200062Sedimport com.sun.source.tree.ClassTree;
34200062Sedimport com.sun.source.tree.CompilationUnitTree;
35200062Sedimport com.sun.source.tree.ErroneousTree;
36200062Sedimport com.sun.source.tree.ExpressionStatementTree;
37200062Sedimport com.sun.source.tree.ExpressionTree;
38200062Sedimport com.sun.source.tree.LambdaExpressionTree;
39200062Sedimport com.sun.source.tree.MethodInvocationTree;
40200062Sedimport com.sun.source.tree.MethodTree;
41200062Sedimport com.sun.source.tree.ModifiersTree;
42200062Sedimport com.sun.source.tree.PrimitiveTypeTree;
43200062Sedimport com.sun.source.tree.StatementTree;
44200062Sedimport com.sun.source.tree.Tree;
45200062Sedimport com.sun.source.tree.Tree.Kind;
46200062Sedimport com.sun.source.tree.VariableTree;
47200062Sedimport com.sun.source.tree.WhileLoopTree;
48200062Sedimport com.sun.source.util.SourcePositions;
49200062Sedimport com.sun.source.util.TreeScanner;
50200062Sedimport com.sun.source.util.Trees;
51200062Sedimport com.sun.tools.javac.api.JavacTaskImpl;
52200062Sedimport com.sun.tools.javac.main.Main;
53200062Sedimport com.sun.tools.javac.tree.JCTree;
54200062Sedimport java.io.IOException;
55200062Sedimport java.io.StringWriter;
56200062Sedimport java.lang.annotation.ElementType;
57200062Sedimport java.lang.annotation.Retention;
58200062Sedimport java.lang.annotation.RetentionPolicy;
59200062Sedimport java.lang.annotation.Target;
60200062Sedimport java.lang.reflect.Method;
61200062Sedimport java.net.URI;
62200062Sedimport java.util.ArrayList;
63200062Sedimport java.util.Arrays;
64200062Sedimport java.util.LinkedList;
65200062Sedimport java.util.List;
66200062Sedimport java.util.regex.Pattern;
67200062Sedimport javax.lang.model.type.TypeKind;
68200062Sedimport javax.tools.Diagnostic;
69200062Sedimport javax.tools.DiagnosticCollector;
70200062Sedimport javax.tools.DiagnosticListener;
71200062Sedimport javax.tools.JavaCompiler;
72200062Sedimport javax.tools.JavaFileManager;
73200062Sedimport javax.tools.JavaFileObject;
74200062Sedimport javax.tools.SimpleJavaFileObject;
75200062Sedimport javax.tools.ToolProvider;
76200062Sed
77200062Sedpublic class JavacParserTest extends TestCase {
78200062Sed    static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
79200062Sed    static final JavaFileManager fm = tool.getStandardFileManager(null, null, null);
80200062Sed
81200062Sed    private JavacParserTest(){}
82200062Sed
83200062Sed    public static void main(String... args) throws Exception {
84200062Sed        try {
85200062Sed            new JavacParserTest().run(args);
86200062Sed        } finally {
87200062Sed            fm.close();
88200062Sed        }
89200062Sed    }
90200062Sed
91200062Sed    class MyFileObject extends SimpleJavaFileObject {
92200062Sed
93200062Sed        private String text;
94200062Sed
95200062Sed        public MyFileObject(String text) {
96200062Sed            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
97200062Sed            this.text = text;
98200062Sed        }
99200062Sed
100200062Sed        @Override
101200062Sed        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
102200062Sed            return text;
103200062Sed        }
104200062Sed    }
105200062Sed    /*
106200062Sed     * converts Windows to Unix style LFs for comparing strings
107200062Sed     */
108200062Sed    String normalize(String in) {
109200062Sed        return in.replace(System.getProperty("line.separator"), "\n");
110200062Sed    }
111200062Sed
112200062Sed    CompilationUnitTree getCompilationUnitTree(String code) throws IOException {
113200062Sed
114200062Sed        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
115200062Sed                null, Arrays.asList(new MyFileObject(code)));
116200062Sed        CompilationUnitTree cut = ct.parse().iterator().next();
117200062Sed        return cut;
118200062Sed    }
119200062Sed
120200062Sed    List<String> getErroneousTreeValues(ErroneousTree node) {
121200062Sed
122200062Sed        List<String> values = new ArrayList<>();
123200062Sed        if (node.getErrorTrees() != null) {
124200062Sed            for (Tree t : node.getErrorTrees()) {
125200062Sed                values.add(t.toString());
126200062Sed            }
127200062Sed        } else {
128200062Sed            throw new RuntimeException("ERROR: No Erroneous tree "
129200062Sed                    + "has been created.");
130200062Sed        }
131200062Sed        return values;
132200062Sed    }
133200062Sed
134200062Sed    @Test
135200062Sed    void testPositionForSuperConstructorCalls() throws IOException {
136        assert tool != null;
137
138        String code = "package test; public class Test {public Test() {super();}}";
139
140        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
141                null, Arrays.asList(new MyFileObject(code)));
142        CompilationUnitTree cut = ct.parse().iterator().next();
143        SourcePositions pos = Trees.instance(ct).getSourcePositions();
144
145        MethodTree method =
146                (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0);
147        ExpressionStatementTree es =
148                (ExpressionStatementTree) method.getBody().getStatements().get(0);
149
150        final int esStartPos = code.indexOf(es.toString());
151        final int esEndPos = esStartPos + es.toString().length();
152        assertEquals("testPositionForSuperConstructorCalls",
153                esStartPos, pos.getStartPosition(cut, es));
154        assertEquals("testPositionForSuperConstructorCalls",
155                esEndPos, pos.getEndPosition(cut, es));
156
157        MethodInvocationTree mit = (MethodInvocationTree) es.getExpression();
158
159        final int mitStartPos = code.indexOf(mit.toString());
160        final int mitEndPos = mitStartPos + mit.toString().length();
161        assertEquals("testPositionForSuperConstructorCalls",
162                mitStartPos, pos.getStartPosition(cut, mit));
163        assertEquals("testPositionForSuperConstructorCalls",
164                mitEndPos, pos.getEndPosition(cut, mit));
165
166        final int methodStartPos = mitStartPos;
167        final int methodEndPos = methodStartPos + mit.getMethodSelect().toString().length();
168        assertEquals("testPositionForSuperConstructorCalls",
169                methodStartPos, pos.getStartPosition(cut, mit.getMethodSelect()));
170        assertEquals("testPositionForSuperConstructorCalls",
171                methodEndPos, pos.getEndPosition(cut, mit.getMethodSelect()));
172    }
173
174    @Test
175    void testPositionForEnumModifiers() throws IOException {
176        final String theString = "public";
177        String code = "package test; " + theString + " enum Test {A;}";
178
179        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
180                null, Arrays.asList(new MyFileObject(code)));
181        CompilationUnitTree cut = ct.parse().iterator().next();
182        SourcePositions pos = Trees.instance(ct).getSourcePositions();
183
184        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
185        ModifiersTree mt = clazz.getModifiers();
186        int spos = code.indexOf(theString);
187        int epos = spos + theString.length();
188        assertEquals("testPositionForEnumModifiers",
189                spos, pos.getStartPosition(cut, mt));
190        assertEquals("testPositionForEnumModifiers",
191                epos, pos.getEndPosition(cut, mt));
192    }
193
194    @Test
195    void testNewClassWithEnclosing() throws IOException {
196
197        final String theString = "Test.this.new d()";
198        String code = "package test; class Test { " +
199                "class d {} private void method() { " +
200                "Object o = " + theString + "; } }";
201
202        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
203                null, Arrays.asList(new MyFileObject(code)));
204        CompilationUnitTree cut = ct.parse().iterator().next();
205        SourcePositions pos = Trees.instance(ct).getSourcePositions();
206
207        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
208        ExpressionTree est =
209                ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer();
210
211        final int spos = code.indexOf(theString);
212        final int epos = spos + theString.length();
213        assertEquals("testNewClassWithEnclosing",
214                spos, pos.getStartPosition(cut, est));
215        assertEquals("testNewClassWithEnclosing",
216                epos, pos.getEndPosition(cut, est));
217    }
218
219    @Test
220    void testPreferredPositionForBinaryOp() throws IOException {
221
222        String code = "package test; public class Test {"
223                + "private void test() {"
224                + "Object o = null; boolean b = o != null && o instanceof String;"
225                + "} private Test() {}}";
226
227        CompilationUnitTree cut = getCompilationUnitTree(code);
228        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
229        MethodTree method = (MethodTree) clazz.getMembers().get(0);
230        VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1);
231        BinaryTree cond = (BinaryTree) condSt.getInitializer();
232
233        JCTree condJC = (JCTree) cond;
234        int condStartPos = code.indexOf("&&");
235        assertEquals("testPreferredPositionForBinaryOp",
236                condStartPos, condJC.pos);
237    }
238
239    @Test
240    void testErrorRecoveryForEnhancedForLoop142381() throws IOException {
241
242        String code = "package test; class Test { " +
243                "private void method() { " +
244                "java.util.Set<String> s = null; for (a : s) {} } }";
245
246        final List<Diagnostic<? extends JavaFileObject>> errors =
247                new LinkedList<Diagnostic<? extends JavaFileObject>>();
248
249        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm,
250                new DiagnosticListener<JavaFileObject>() {
251            public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
252                errors.add(diagnostic);
253            }
254        }, null, null, Arrays.asList(new MyFileObject(code)));
255
256        CompilationUnitTree cut = ct.parse().iterator().next();
257
258        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
259        StatementTree forStatement =
260                ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1);
261
262        assertEquals("testErrorRecoveryForEnhancedForLoop142381",
263                Kind.ENHANCED_FOR_LOOP, forStatement.getKind());
264        assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty());
265    }
266
267    @Test
268    void testPositionAnnotationNoPackage187551() throws IOException {
269
270        String code = "\n@interface Test {}";
271
272        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
273                null, Arrays.asList(new MyFileObject(code)));
274
275        CompilationUnitTree cut = ct.parse().iterator().next();
276        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
277        Trees t = Trees.instance(ct);
278
279        assertEquals("testPositionAnnotationNoPackage187551",
280                1, t.getSourcePositions().getStartPosition(cut, clazz));
281    }
282
283    @Test
284    void testPositionsSane1() throws IOException {
285        performPositionsSanityTest("package test; class Test { " +
286                "private void method() { " +
287                "java.util.List<? extends java.util.List<? extends String>> l; " +
288                "} }");
289    }
290
291    @Test
292    void testPositionsSane2() throws IOException {
293        performPositionsSanityTest("package test; class Test { " +
294                "private void method() { " +
295                "java.util.List<? super java.util.List<? super String>> l; " +
296                "} }");
297    }
298
299    @Test
300    void testPositionsSane3() throws IOException {
301        performPositionsSanityTest("package test; class Test { " +
302                "private void method() { " +
303                "java.util.List<? super java.util.List<?>> l; } }");
304    }
305
306    private void performPositionsSanityTest(String code) throws IOException {
307
308        final List<Diagnostic<? extends JavaFileObject>> errors =
309                new LinkedList<Diagnostic<? extends JavaFileObject>>();
310
311        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm,
312                new DiagnosticListener<JavaFileObject>() {
313
314            public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
315                errors.add(diagnostic);
316            }
317        }, null, null, Arrays.asList(new MyFileObject(code)));
318
319        final CompilationUnitTree cut = ct.parse().iterator().next();
320        final Trees trees = Trees.instance(ct);
321
322        new TreeScanner<Void, Void>() {
323
324            private long parentStart = 0;
325            private long parentEnd = Integer.MAX_VALUE;
326
327            @Override
328            public Void scan(Tree node, Void p) {
329                if (node == null) {
330                    return null;
331                }
332
333                long start = trees.getSourcePositions().getStartPosition(cut, node);
334
335                if (start == (-1)) {
336                    return null; // synthetic tree
337                }
338                assertTrue(node.toString() + ":" + start + "/" + parentStart,
339                        parentStart <= start);
340
341                long prevParentStart = parentStart;
342
343                parentStart = start;
344
345                long end = trees.getSourcePositions().getEndPosition(cut, node);
346
347                assertTrue(node.toString() + ":" + end + "/" + parentEnd,
348                        end <= parentEnd);
349
350                long prevParentEnd = parentEnd;
351
352                parentEnd = end;
353
354                super.scan(node, p);
355
356                parentStart = prevParentStart;
357                parentEnd = prevParentEnd;
358
359                return null;
360            }
361
362            private void assertTrue(String message, boolean b) {
363                if (!b) fail(message);
364            }
365        }.scan(cut, null);
366    }
367
368    @Test
369    void testCorrectWilcardPositions1() throws IOException {
370        performWildcardPositionsTest("package test; import java.util.List; " +
371                "class Test { private void method() { List<? extends List<? extends String>> l; } }",
372
373                Arrays.asList("List<? extends List<? extends String>> l;",
374                "List<? extends List<? extends String>>",
375                "List",
376                "? extends List<? extends String>",
377                "List<? extends String>",
378                "List",
379                "? extends String",
380                "String"));
381    }
382
383    @Test
384    void testCorrectWilcardPositions2() throws IOException {
385        performWildcardPositionsTest("package test; import java.util.List; "
386                + "class Test { private void method() { List<? super List<? super String>> l; } }",
387                Arrays.asList("List<? super List<? super String>> l;",
388                "List<? super List<? super String>>",
389                "List",
390                "? super List<? super String>",
391                "List<? super String>",
392                "List",
393                "? super String",
394                "String"));
395    }
396
397    @Test
398    void testCorrectWilcardPositions3() throws IOException {
399        performWildcardPositionsTest("package test; import java.util.List; " +
400                "class Test { private void method() { List<? super List<?>> l; } }",
401
402                Arrays.asList("List<? super List<?>> l;",
403                "List<? super List<?>>",
404                "List",
405                "? super List<?>",
406                "List<?>",
407                "List",
408                "?"));
409    }
410
411    @Test
412    void testCorrectWilcardPositions4() throws IOException {
413        performWildcardPositionsTest("package test; import java.util.List; " +
414                "class Test { private void method() { " +
415                "List<? extends List<? extends List<? extends String>>> l; } }",
416
417                Arrays.asList("List<? extends List<? extends List<? extends String>>> l;",
418                "List<? extends List<? extends List<? extends String>>>",
419                "List",
420                "? extends List<? extends List<? extends String>>",
421                "List<? extends List<? extends String>>",
422                "List",
423                "? extends List<? extends String>",
424                "List<? extends String>",
425                "List",
426                "? extends String",
427                "String"));
428    }
429
430    @Test
431    void testCorrectWilcardPositions5() throws IOException {
432        performWildcardPositionsTest("package test; import java.util.List; " +
433                "class Test { private void method() { " +
434                "List<? extends List<? extends List<? extends String   >>> l; } }",
435                Arrays.asList("List<? extends List<? extends List<? extends String   >>> l;",
436                "List<? extends List<? extends List<? extends String   >>>",
437                "List",
438                "? extends List<? extends List<? extends String   >>",
439                "List<? extends List<? extends String   >>",
440                "List",
441                "? extends List<? extends String   >",
442                "List<? extends String   >",
443                "List",
444                "? extends String",
445                "String"));
446    }
447
448    void performWildcardPositionsTest(final String code,
449            List<String> golden) throws IOException {
450
451        final List<Diagnostic<? extends JavaFileObject>> errors =
452                new LinkedList<Diagnostic<? extends JavaFileObject>>();
453
454        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm,
455                new DiagnosticListener<JavaFileObject>() {
456                    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
457                        errors.add(diagnostic);
458                    }
459                }, null, null, Arrays.asList(new MyFileObject(code)));
460
461        final CompilationUnitTree cut = ct.parse().iterator().next();
462        final List<String> content = new LinkedList<String>();
463        final Trees trees = Trees.instance(ct);
464
465        new TreeScanner<Void, Void>() {
466            @Override
467            public Void scan(Tree node, Void p) {
468                if (node == null) {
469                    return null;
470                }
471                long start = trees.getSourcePositions().getStartPosition(cut, node);
472
473                if (start == (-1)) {
474                    return null; // synthetic tree
475                }
476                long end = trees.getSourcePositions().getEndPosition(cut, node);
477                String s = code.substring((int) start, (int) end);
478                content.add(s);
479
480                return super.scan(node, p);
481            }
482        }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null);
483
484        assertEquals("performWildcardPositionsTest",golden.toString(),
485                content.toString());
486    }
487
488    @Test
489    void testStartPositionForMethodWithoutModifiers() throws IOException {
490
491        String code = "package t; class Test { <T> void t() {} }";
492
493        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
494                null, Arrays.asList(new MyFileObject(code)));
495        CompilationUnitTree cut = ct.parse().iterator().next();
496        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
497        MethodTree mt = (MethodTree) clazz.getMembers().get(0);
498        Trees t = Trees.instance(ct);
499        int start = (int) t.getSourcePositions().getStartPosition(cut, mt);
500        int end = (int) t.getSourcePositions().getEndPosition(cut, mt);
501
502        assertEquals("testStartPositionForMethodWithoutModifiers",
503                "<T> void t() {}", code.substring(start, end));
504    }
505
506    @Test
507    void testVariableInIfThen1() throws IOException {
508
509        String code = "package t; class Test { " +
510                "private static void t(String name) { " +
511                "if (name != null) String nn = name.trim(); } }";
512
513        DiagnosticCollector<JavaFileObject> coll =
514                new DiagnosticCollector<JavaFileObject>();
515
516        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
517                null, Arrays.asList(new MyFileObject(code)));
518
519        ct.parse();
520
521        List<String> codes = new LinkedList<String>();
522
523        for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) {
524            codes.add(d.getCode());
525        }
526
527        assertEquals("testVariableInIfThen1",
528                Arrays.<String>asList("compiler.err.variable.not.allowed"),
529                codes);
530    }
531
532    @Test
533   void testVariableInIfThen2() throws IOException {
534
535        String code = "package t; class Test { " +
536                "private static void t(String name) { " +
537                "if (name != null) class X {} } }";
538        DiagnosticCollector<JavaFileObject> coll =
539                new DiagnosticCollector<JavaFileObject>();
540        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
541                null, Arrays.asList(new MyFileObject(code)));
542
543        ct.parse();
544
545        List<String> codes = new LinkedList<String>();
546
547        for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) {
548            codes.add(d.getCode());
549        }
550
551        assertEquals("testVariableInIfThen2",
552                Arrays.<String>asList("compiler.err.class.not.allowed"), codes);
553    }
554
555    @Test
556    void testVariableInIfThen3() throws IOException {
557
558        String code = "package t; class Test { "+
559                "private static void t() { " +
560                "if (true) abstract class F {} }}";
561        DiagnosticCollector<JavaFileObject> coll =
562                new DiagnosticCollector<JavaFileObject>();
563        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
564                null, Arrays.asList(new MyFileObject(code)));
565
566        ct.parse();
567
568        List<String> codes = new LinkedList<String>();
569
570        for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) {
571            codes.add(d.getCode());
572        }
573
574        assertEquals("testVariableInIfThen3",
575                Arrays.<String>asList("compiler.err.class.not.allowed"), codes);
576    }
577
578    @Test
579    void testVariableInIfThen4() throws IOException {
580
581        String code = "package t; class Test { "+
582                "private static void t(String name) { " +
583                "if (name != null) interface X {} } }";
584        DiagnosticCollector<JavaFileObject> coll =
585                new DiagnosticCollector<JavaFileObject>();
586        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
587                null, Arrays.asList(new MyFileObject(code)));
588
589        ct.parse();
590
591        List<String> codes = new LinkedList<String>();
592
593        for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) {
594            codes.add(d.getCode());
595        }
596
597        assertEquals("testVariableInIfThen4",
598                Arrays.<String>asList("compiler.err.class.not.allowed"), codes);
599    }
600
601    @Test
602    void testVariableInIfThen5() throws IOException {
603
604        String code = "package t; class Test { "+
605                "private static void t() { " +
606                "if (true) } }";
607        DiagnosticCollector<JavaFileObject> coll =
608                new DiagnosticCollector<JavaFileObject>();
609        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
610                null, Arrays.asList(new MyFileObject(code)));
611
612        ct.parse();
613
614        List<String> codes = new LinkedList<String>();
615
616        for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) {
617            codes.add(d.getCode());
618        }
619
620        assertEquals("testVariableInIfThen5",
621                Arrays.<String>asList("compiler.err.illegal.start.of.stmt"),
622                codes);
623    }
624
625    // see javac bug #6882235, NB bug #98234:
626    @Test
627    void testMissingExponent() throws IOException {
628
629        String code = "\nclass Test { { System.err.println(0e); } }";
630
631        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
632                null, Arrays.asList(new MyFileObject(code)));
633
634        assertNotNull(ct.parse().iterator().next());
635    }
636
637    @Test
638    void testTryResourcePos() throws IOException {
639
640        final String code = "package t; class Test { " +
641                "{ try (java.io.InputStream in = null) { } } }";
642
643        CompilationUnitTree cut = getCompilationUnitTree(code);
644
645        new TreeScanner<Void, Void>() {
646            @Override
647            public Void visitVariable(VariableTree node, Void p) {
648                if ("in".contentEquals(node.getName())) {
649                    JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node;
650                    assertEquals("testTryResourcePos", "in = null) { } } }",
651                            code.substring(var.pos));
652                }
653                return super.visitVariable(node, p);
654            }
655        }.scan(cut, null);
656    }
657
658    @Test
659    void testVarPos() throws IOException {
660
661        final String code = "package t; class Test { " +
662                "{ java.io.InputStream in = null; } }";
663
664        CompilationUnitTree cut = getCompilationUnitTree(code);
665
666        new TreeScanner<Void, Void>() {
667
668            @Override
669            public Void visitVariable(VariableTree node, Void p) {
670                if ("in".contentEquals(node.getName())) {
671                    JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node;
672                    assertEquals("testVarPos","in = null; } }",
673                            code.substring(var.pos));
674                }
675                return super.visitVariable(node, p);
676            }
677        }.scan(cut, null);
678    }
679
680    // expected erroneous tree: int x = y;(ERROR);
681    @Test
682    void testOperatorMissingError() throws IOException {
683
684        String code = "package test; public class ErrorTest { "
685                + "void method() { int x = y  z } }";
686        CompilationUnitTree cut = getCompilationUnitTree(code);
687        final List<String> values = new ArrayList<>();
688        final List<String> expectedValues =
689                new ArrayList<>(Arrays.asList("[z]"));
690
691        new TreeScanner<Void, Void>() {
692            @Override
693            public Void visitErroneous(ErroneousTree node, Void p) {
694                values.add(getErroneousTreeValues(node).toString());
695                return null;
696
697            }
698        }.scan(cut, null);
699
700        assertEquals("testSwitchError: The Erroneous tree "
701                + "error values: " + values
702                + " do not match expected error values: "
703                + expectedValues, values, expectedValues);
704    }
705
706    // expected erroneous tree:  String s = (ERROR);
707    @Test
708    void testMissingParenthesisError() throws IOException {
709
710        String code = "package test; public class ErrorTest { "
711                + "void f() {String s = new String; } }";
712        CompilationUnitTree cut = getCompilationUnitTree(code);
713        final List<String> values = new ArrayList<>();
714        final List<String> expectedValues =
715                new ArrayList<>(Arrays.asList("[new String()]"));
716
717        new TreeScanner<Void, Void>() {
718            @Override
719            public Void visitErroneous(ErroneousTree node, Void p) {
720                values.add(getErroneousTreeValues(node).toString());
721                return null;
722            }
723        }.scan(cut, null);
724
725        assertEquals("testSwitchError: The Erroneous tree "
726                + "error values: " + values
727                + " do not match expected error values: "
728                + expectedValues, values, expectedValues);
729    }
730
731    // expected erroneous tree: package test; (ERROR)(ERROR)
732    @Test
733    void testMissingClassError() throws IOException {
734
735        String code = "package Test; clas ErrorTest {  "
736                + "void f() {String s = new String(); } }";
737        CompilationUnitTree cut = getCompilationUnitTree(code);
738        final List<String> values = new ArrayList<>();
739        final List<String> expectedValues =
740                new ArrayList<>(Arrays.asList("[, clas]", "[]"));
741
742        new TreeScanner<Void, Void>() {
743            @Override
744            public Void visitErroneous(ErroneousTree node, Void p) {
745                values.add(getErroneousTreeValues(node).toString());
746                return null;
747            }
748        }.scan(cut, null);
749
750        assertEquals("testSwitchError: The Erroneous tree "
751                + "error values: " + values
752                + " do not match expected error values: "
753                + expectedValues, values, expectedValues);
754    }
755
756    // expected erroneous tree: void m1(int i) {(ERROR);{(ERROR);}
757    @Test
758    void testSwitchError() throws IOException {
759
760        String code = "package test; public class ErrorTest { "
761                + "int numDays; void m1(int i) { switchh {i} { case 1: "
762                + "numDays = 31; break; } } }";
763        CompilationUnitTree cut = getCompilationUnitTree(code);
764        final List<String> values = new ArrayList<>();
765        final List<String> expectedValues =
766                new ArrayList<>(Arrays.asList("[switchh]", "[i]"));
767
768        new TreeScanner<Void, Void>() {
769            @Override
770            public Void visitErroneous(ErroneousTree node, Void p) {
771                values.add(getErroneousTreeValues(node).toString());
772                return null;
773            }
774        }.scan(cut, null);
775
776        assertEquals("testSwitchError: The Erroneous tree "
777                + "error values: " + values
778                + " do not match expected error values: "
779                + expectedValues, values, expectedValues);
780    }
781
782    // expected erroneous tree: class ErrorTest {(ERROR)
783    @Test
784    void testMethodError() throws IOException {
785
786        String code = "package Test; class ErrorTest {  "
787                + "static final void f) {String s = new String(); } }";
788        CompilationUnitTree cut = cut = getCompilationUnitTree(code);
789
790        final List<String> values = new ArrayList<>();
791        final List<String> expectedValues =
792                new ArrayList<>(Arrays.asList("[\nstatic final void f();]"));
793
794        new TreeScanner<Void, Void>() {
795            @Override
796            public Void visitErroneous(ErroneousTree node, Void p) {
797                values.add(normalize(getErroneousTreeValues(node).toString()));
798                return null;
799            }
800        }.scan(cut, null);
801
802        assertEquals("testMethodError: The Erroneous tree "
803                + "error value: " + values
804                + " does not match expected error values: "
805                + expectedValues, values, expectedValues);
806    }
807
808    /*
809     * The following tests do not work just yet with nb-javac nor javac,
810     * they need further investigation, see CR: 7167356
811     */
812
813    void testPositionBrokenSource126732a() throws IOException {
814        String[] commands = new String[]{
815            "return Runnable()",
816            "do { } while (true)",
817            "throw UnsupportedOperationException()",
818            "assert true",
819            "1 + 1",};
820
821        for (String command : commands) {
822
823            String code = "package test;\n"
824                    + "public class Test {\n"
825                    + "    public static void test() {\n"
826                    + "        " + command + " {\n"
827                    + "                new Runnable() {\n"
828                    + "        };\n"
829                    + "    }\n"
830                    + "}";
831            JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null,
832                    null, null, Arrays.asList(new MyFileObject(code)));
833            CompilationUnitTree cut = ct.parse().iterator().next();
834
835            ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
836            MethodTree method = (MethodTree) clazz.getMembers().get(0);
837            List<? extends StatementTree> statements =
838                    method.getBody().getStatements();
839
840            StatementTree ret = statements.get(0);
841            StatementTree block = statements.get(1);
842
843            Trees t = Trees.instance(ct);
844            int len = code.indexOf(command + " {") + (command + " ").length();
845            assertEquals(command, len,
846                    t.getSourcePositions().getEndPosition(cut, ret));
847            assertEquals(command, len,
848                    t.getSourcePositions().getStartPosition(cut, block));
849        }
850    }
851
852    void testPositionBrokenSource126732b() throws IOException {
853        String[] commands = new String[]{
854            "break",
855            "break A",
856            "continue ",
857            "continue A",};
858
859        for (String command : commands) {
860
861            String code = "package test;\n"
862                    + "public class Test {\n"
863                    + "    public static void test() {\n"
864                    + "        while (true) {\n"
865                    + "            " + command + " {\n"
866                    + "                new Runnable() {\n"
867                    + "        };\n"
868                    + "        }\n"
869                    + "    }\n"
870                    + "}";
871
872            JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null,
873                    null, null, Arrays.asList(new MyFileObject(code)));
874            CompilationUnitTree cut = ct.parse().iterator().next();
875
876            ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
877            MethodTree method = (MethodTree) clazz.getMembers().get(0);
878            List<? extends StatementTree> statements =
879                    ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements();
880
881            StatementTree ret = statements.get(0);
882            StatementTree block = statements.get(1);
883
884            Trees t = Trees.instance(ct);
885            int len = code.indexOf(command + " {") + (command + " ").length();
886            assertEquals(command, len,
887                    t.getSourcePositions().getEndPosition(cut, ret));
888            assertEquals(command, len,
889                    t.getSourcePositions().getStartPosition(cut, block));
890        }
891    }
892
893    void testStartPositionEnumConstantInit() throws IOException {
894
895        String code = "package t; enum Test { AAA; }";
896
897        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
898                null, Arrays.asList(new MyFileObject(code)));
899        CompilationUnitTree cut = ct.parse().iterator().next();
900        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
901        VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0);
902        Trees t = Trees.instance(ct);
903        int start = (int) t.getSourcePositions().getStartPosition(cut,
904                enumAAA.getInitializer());
905
906        assertEquals("testStartPositionEnumConstantInit", -1, start);
907    }
908
909    @Test
910    void testVoidLambdaParameter() throws IOException {
911        String code = "package t; class Test { " +
912                "Runnable r = (void v) -> { };" +
913                "}";
914        DiagnosticCollector<JavaFileObject> coll =
915                new DiagnosticCollector<>();
916        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null,
917                null, Arrays.asList(new MyFileObject(code)));
918
919        CompilationUnitTree cut = ct.parse().iterator().next();
920        ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0);
921        VariableTree field = (VariableTree) clazz.getMembers().get(0);
922
923        assertEquals("actual kind: " + field.getInitializer().getKind(),
924                     field.getInitializer().getKind(),
925                     Kind.LAMBDA_EXPRESSION);
926
927        LambdaExpressionTree lambda = (LambdaExpressionTree) field.getInitializer();
928
929        assertEquals("actual parameters: " + lambda.getParameters().size(),
930                     lambda.getParameters().size(),
931                     1);
932
933        Tree paramType = lambda.getParameters().get(0).getType();
934
935        assertEquals("actual parameter type: " + paramType.getKind(),
936                     paramType.getKind(),
937                     Kind.PRIMITIVE_TYPE);
938
939        TypeKind primitiveTypeKind = ((PrimitiveTypeTree) paramType).getPrimitiveTypeKind();
940
941        assertEquals("actual parameter type: " + primitiveTypeKind,
942                     primitiveTypeKind,
943                     TypeKind.VOID);
944    }
945
946    @Test //JDK-8065753
947    void testWrongFirstToken() throws IOException {
948        String code = "<";
949        String expectedErrors = "Test.java:1:1: compiler.err.expected3: class, interface, enum\n" +
950                                "1 error\n";
951        StringWriter out = new StringWriter();
952        JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(out, fm, null,
953                Arrays.asList("-XDrawDiagnostics"), null, Arrays.asList(new MyFileObject(code)));
954
955        assertEquals("the error code is not correct", Main.Result.ERROR, ct.doCall());
956        assertEquals("the error message is not correct", expectedErrors, out.toString());
957    }
958
959    void run(String[] args) throws Exception {
960        int passed = 0, failed = 0;
961        final Pattern p = (args != null && args.length > 0)
962                ? Pattern.compile(args[0])
963                : null;
964        for (Method m : this.getClass().getDeclaredMethods()) {
965            boolean selected = (p == null)
966                    ? m.isAnnotationPresent(Test.class)
967                    : p.matcher(m.getName()).matches();
968            if (selected) {
969                try {
970                    m.invoke(this, (Object[]) null);
971                    System.out.println(m.getName() + ": OK");
972                    passed++;
973                } catch (Throwable ex) {
974                    System.out.printf("Test %s failed: %s %n", m, ex.getCause());
975                    failed++;
976                }
977            }
978        }
979        System.out.printf("Passed: %d, Failed %d%n", passed, failed);
980        if (failed > 0) {
981            throw new RuntimeException("Tests failed: " + failed);
982        }
983        if (passed == 0 && failed == 0) {
984            throw new AssertionError("No test(s) selected: passed = " +
985                    passed + ", failed = " + failed + " ??????????");
986        }
987    }
988}
989
990abstract class TestCase {
991
992    void assertEquals(String message, int i, int pos) {
993        if (i != pos) {
994            fail(message);
995        }
996    }
997
998    void assertFalse(String message, boolean bvalue) {
999        if (bvalue == true) {
1000            fail(message);
1001        }
1002    }
1003
1004    void assertEquals(String message, int i, long l) {
1005        if (i != l) {
1006            fail(message + ":" + i + ":" + l);
1007        }
1008    }
1009
1010    void assertEquals(String message, Object o1, Object o2) {
1011        if (o1 != null && o2 != null && !o1.equals(o2)) {
1012            fail(message);
1013        }
1014        if (o1 == null && o2 != null) {
1015            fail(message);
1016        }
1017    }
1018
1019    void assertNotNull(Object o) {
1020        if (o == null) {
1021            fail();
1022        }
1023    }
1024
1025    void fail() {
1026        fail("test failed");
1027    }
1028
1029    void fail(String message) {
1030        throw new RuntimeException(message);
1031    }
1032
1033    /**
1034     * Indicates that the annotated method is a test method.
1035     */
1036    @Retention(RetentionPolicy.RUNTIME)
1037    @Target(ElementType.METHOD)
1038    public @interface Test {}
1039}
1040