langtools/test/tools/javac/6402516/Checker.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 10 06bc494ca11e
child 5520 86e4b9a9da40
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10
06bc494ca11e Initial load
duke
parents:
diff changeset
     1
/*
06bc494ca11e Initial load
duke
parents:
diff changeset
     2
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
06bc494ca11e Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
06bc494ca11e Initial load
duke
parents:
diff changeset
     4
 *
06bc494ca11e Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
06bc494ca11e Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
06bc494ca11e Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
06bc494ca11e Initial load
duke
parents:
diff changeset
     8
 *
06bc494ca11e Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
06bc494ca11e Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
06bc494ca11e Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
06bc494ca11e Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
06bc494ca11e Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
06bc494ca11e Initial load
duke
parents:
diff changeset
    14
 *
06bc494ca11e Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
06bc494ca11e Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
06bc494ca11e Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
06bc494ca11e Initial load
duke
parents:
diff changeset
    18
 *
06bc494ca11e Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
06bc494ca11e Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
06bc494ca11e Initial load
duke
parents:
diff changeset
    21
 * have any questions.
06bc494ca11e Initial load
duke
parents:
diff changeset
    22
 */
06bc494ca11e Initial load
duke
parents:
diff changeset
    23
06bc494ca11e Initial load
duke
parents:
diff changeset
    24
import java.io.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    25
import java.util.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    26
import javax.lang.model.util.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    27
import javax.tools.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    28
import com.sun.tools.javac.api.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    29
import com.sun.source.tree.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    30
import com.sun.source.util.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    31
import com.sun.tools.javac.tree.JCTree;
06bc494ca11e Initial load
duke
parents:
diff changeset
    32
import com.sun.tools.javac.tree.JCTree.*;
06bc494ca11e Initial load
duke
parents:
diff changeset
    33
import com.sun.tools.javac.util.Position;
06bc494ca11e Initial load
duke
parents:
diff changeset
    34
06bc494ca11e Initial load
duke
parents:
diff changeset
    35
/*
06bc494ca11e Initial load
duke
parents:
diff changeset
    36
 * Abstract class to help check the scopes in a parsed source file.
06bc494ca11e Initial load
duke
parents:
diff changeset
    37
 * -- parse source file
06bc494ca11e Initial load
duke
parents:
diff changeset
    38
 * -- scan trees looking for string literals
06bc494ca11e Initial load
duke
parents:
diff changeset
    39
 * -- check the scope at that point against the string, using
06bc494ca11e Initial load
duke
parents:
diff changeset
    40
 *      boolean check(Scope s, String ref)
06bc494ca11e Initial load
duke
parents:
diff changeset
    41
 */
06bc494ca11e Initial load
duke
parents:
diff changeset
    42
abstract class Checker {
06bc494ca11e Initial load
duke
parents:
diff changeset
    43
    // parse the source file and call check(scope, string) for each string literal found
06bc494ca11e Initial load
duke
parents:
diff changeset
    44
    void check(String... fileNames) throws IOException {
06bc494ca11e Initial load
duke
parents:
diff changeset
    45
        File testSrc = new File(System.getProperty("test.src"));
06bc494ca11e Initial load
duke
parents:
diff changeset
    46
06bc494ca11e Initial load
duke
parents:
diff changeset
    47
        DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
06bc494ca11e Initial load
duke
parents:
diff changeset
    48
            public void report(Diagnostic d) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    49
                System.err.println(d);
06bc494ca11e Initial load
duke
parents:
diff changeset
    50
                if (d.getKind() == Diagnostic.Kind.ERROR)
06bc494ca11e Initial load
duke
parents:
diff changeset
    51
                    errors = true;
06bc494ca11e Initial load
duke
parents:
diff changeset
    52
                new Exception().printStackTrace();
06bc494ca11e Initial load
duke
parents:
diff changeset
    53
            }
06bc494ca11e Initial load
duke
parents:
diff changeset
    54
        };
06bc494ca11e Initial load
duke
parents:
diff changeset
    55
06bc494ca11e Initial load
duke
parents:
diff changeset
    56
        JavacTool tool = JavacTool.create();
06bc494ca11e Initial load
duke
parents:
diff changeset
    57
        StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null);
06bc494ca11e Initial load
duke
parents:
diff changeset
    58
        Iterable<? extends JavaFileObject> files =
06bc494ca11e Initial load
duke
parents:
diff changeset
    59
            fm.getJavaFileObjectsFromFiles(getFiles(testSrc, fileNames));
06bc494ca11e Initial load
duke
parents:
diff changeset
    60
        task = tool.getTask(null, fm, dl, null, null, files);
06bc494ca11e Initial load
duke
parents:
diff changeset
    61
        Iterable<? extends CompilationUnitTree> units = task.parse();
06bc494ca11e Initial load
duke
parents:
diff changeset
    62
06bc494ca11e Initial load
duke
parents:
diff changeset
    63
        if (errors)
06bc494ca11e Initial load
duke
parents:
diff changeset
    64
            throw new AssertionError("errors occurred creating trees");
06bc494ca11e Initial load
duke
parents:
diff changeset
    65
06bc494ca11e Initial load
duke
parents:
diff changeset
    66
        ScopeScanner s = new ScopeScanner();
06bc494ca11e Initial load
duke
parents:
diff changeset
    67
        for (CompilationUnitTree unit: units) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    68
            TreePath p = new TreePath(unit);
06bc494ca11e Initial load
duke
parents:
diff changeset
    69
            s.scan(p, getTrees());
06bc494ca11e Initial load
duke
parents:
diff changeset
    70
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
    71
        task = null;
06bc494ca11e Initial load
duke
parents:
diff changeset
    72
06bc494ca11e Initial load
duke
parents:
diff changeset
    73
        if (errors)
06bc494ca11e Initial load
duke
parents:
diff changeset
    74
            throw new AssertionError("errors occurred checking scopes");
06bc494ca11e Initial load
duke
parents:
diff changeset
    75
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
    76
06bc494ca11e Initial load
duke
parents:
diff changeset
    77
    // default impl: split ref at ";" and call checkLocal(scope, ref_segment) on scope and its enclosing scopes
06bc494ca11e Initial load
duke
parents:
diff changeset
    78
    protected boolean check(Scope s, String ref) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    79
        // System.err.println("check scope: " + s);
06bc494ca11e Initial load
duke
parents:
diff changeset
    80
        // System.err.println("check ref: " + ref);
06bc494ca11e Initial load
duke
parents:
diff changeset
    81
        if (s == null && (ref == null || ref.trim().length() == 0))
06bc494ca11e Initial load
duke
parents:
diff changeset
    82
            return true;
06bc494ca11e Initial load
duke
parents:
diff changeset
    83
06bc494ca11e Initial load
duke
parents:
diff changeset
    84
        if (s == null) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    85
            error(s, ref, "scope missing");
06bc494ca11e Initial load
duke
parents:
diff changeset
    86
            return false;
06bc494ca11e Initial load
duke
parents:
diff changeset
    87
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
    88
06bc494ca11e Initial load
duke
parents:
diff changeset
    89
        if (ref == null) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    90
            error(s, ref, "scope unexpected");
06bc494ca11e Initial load
duke
parents:
diff changeset
    91
            return false;
06bc494ca11e Initial load
duke
parents:
diff changeset
    92
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
    93
06bc494ca11e Initial load
duke
parents:
diff changeset
    94
        String local;
06bc494ca11e Initial load
duke
parents:
diff changeset
    95
        String encl;
06bc494ca11e Initial load
duke
parents:
diff changeset
    96
        int semi = ref.indexOf(';');
06bc494ca11e Initial load
duke
parents:
diff changeset
    97
        if (semi == -1) {
06bc494ca11e Initial load
duke
parents:
diff changeset
    98
            local = ref;
06bc494ca11e Initial load
duke
parents:
diff changeset
    99
            encl = null;
06bc494ca11e Initial load
duke
parents:
diff changeset
   100
        } else {
06bc494ca11e Initial load
duke
parents:
diff changeset
   101
            local = ref.substring(0, semi);
06bc494ca11e Initial load
duke
parents:
diff changeset
   102
            encl = ref.substring(semi + 1);
06bc494ca11e Initial load
duke
parents:
diff changeset
   103
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
   104
06bc494ca11e Initial load
duke
parents:
diff changeset
   105
        return checkLocal(s, local.trim())
06bc494ca11e Initial load
duke
parents:
diff changeset
   106
            & check(s.getEnclosingScope(), encl);
06bc494ca11e Initial load
duke
parents:
diff changeset
   107
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   108
06bc494ca11e Initial load
duke
parents:
diff changeset
   109
    // override if using default check(Scope,String)
06bc494ca11e Initial load
duke
parents:
diff changeset
   110
    boolean checkLocal(Scope s, String ref) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   111
        throw new IllegalStateException();
06bc494ca11e Initial load
duke
parents:
diff changeset
   112
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   113
06bc494ca11e Initial load
duke
parents:
diff changeset
   114
    void error(Scope s, String ref, String msg) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   115
        System.err.println("Error: " + msg);
06bc494ca11e Initial load
duke
parents:
diff changeset
   116
        System.err.println("Scope: " + (s == null ? null : asList(s.getLocalElements())));
06bc494ca11e Initial load
duke
parents:
diff changeset
   117
        System.err.println("Expect: " + ref);
06bc494ca11e Initial load
duke
parents:
diff changeset
   118
        System.err.println("javac: " + (s == null ? null : ((JavacScope) s).getEnv()));
06bc494ca11e Initial load
duke
parents:
diff changeset
   119
        errors = true;
06bc494ca11e Initial load
duke
parents:
diff changeset
   120
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   121
06bc494ca11e Initial load
duke
parents:
diff changeset
   122
    protected Elements getElements() {
06bc494ca11e Initial load
duke
parents:
diff changeset
   123
        return task.getElements();
06bc494ca11e Initial load
duke
parents:
diff changeset
   124
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   125
06bc494ca11e Initial load
duke
parents:
diff changeset
   126
    protected Trees getTrees() {
06bc494ca11e Initial load
duke
parents:
diff changeset
   127
        return Trees.instance(task);
06bc494ca11e Initial load
duke
parents:
diff changeset
   128
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   129
06bc494ca11e Initial load
duke
parents:
diff changeset
   130
    boolean errors = false;
06bc494ca11e Initial load
duke
parents:
diff changeset
   131
    protected JavacTask task;
06bc494ca11e Initial load
duke
parents:
diff changeset
   132
06bc494ca11e Initial load
duke
parents:
diff changeset
   133
    // scan a parse tree, and for every string literal found, call check(scope, string) with
06bc494ca11e Initial load
duke
parents:
diff changeset
   134
    // the string value at the scope at that point
06bc494ca11e Initial load
duke
parents:
diff changeset
   135
    class ScopeScanner extends TreePathScanner<Boolean,Trees> {
06bc494ca11e Initial load
duke
parents:
diff changeset
   136
        public Boolean  visitLiteral(LiteralTree tree, Trees trees) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   137
            TreePath path = getCurrentPath();
06bc494ca11e Initial load
duke
parents:
diff changeset
   138
            CompilationUnitTree unit = path.getCompilationUnit();
06bc494ca11e Initial load
duke
parents:
diff changeset
   139
            Position.LineMap lineMap = ((JCCompilationUnit)unit).lineMap;
06bc494ca11e Initial load
duke
parents:
diff changeset
   140
//          long line = lineMap.getLineNumber(((JCTree)tree).pos/*trees.getSourcePositions().getStartPosition(tree)*/);
06bc494ca11e Initial load
duke
parents:
diff changeset
   141
//          System.err.println(line + ": " + abbrev(tree));
06bc494ca11e Initial load
duke
parents:
diff changeset
   142
            Scope s = trees.getScope(path);
06bc494ca11e Initial load
duke
parents:
diff changeset
   143
            if (tree.getKind() == Tree.Kind.STRING_LITERAL)
06bc494ca11e Initial load
duke
parents:
diff changeset
   144
                check(s, tree.getValue().toString().trim());
06bc494ca11e Initial load
duke
parents:
diff changeset
   145
            return null;
06bc494ca11e Initial load
duke
parents:
diff changeset
   146
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
   147
06bc494ca11e Initial load
duke
parents:
diff changeset
   148
        private String abbrev(Tree tree) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   149
            int max = 48;
06bc494ca11e Initial load
duke
parents:
diff changeset
   150
            String s = tree.toString().replaceAll("[ \n]+", " ");
06bc494ca11e Initial load
duke
parents:
diff changeset
   151
            return (s.length() < max ? s : s.substring(0, max-3) + "...");
06bc494ca11e Initial load
duke
parents:
diff changeset
   152
        }
06bc494ca11e Initial load
duke
parents:
diff changeset
   153
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   154
06bc494ca11e Initial load
duke
parents:
diff changeset
   155
    // prefix filenames with a directory
06bc494ca11e Initial load
duke
parents:
diff changeset
   156
    static Iterable<File> getFiles(File dir, String... names) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   157
        List<File> files = new ArrayList<File>(names.length);
06bc494ca11e Initial load
duke
parents:
diff changeset
   158
        for (String name: names)
06bc494ca11e Initial load
duke
parents:
diff changeset
   159
            files.add(new File(dir, name));
06bc494ca11e Initial load
duke
parents:
diff changeset
   160
        return files;
06bc494ca11e Initial load
duke
parents:
diff changeset
   161
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   162
06bc494ca11e Initial load
duke
parents:
diff changeset
   163
    static private <T> List<T> asList(Iterable<T> iter) {
06bc494ca11e Initial load
duke
parents:
diff changeset
   164
        List<T> l = new ArrayList<T>();
06bc494ca11e Initial load
duke
parents:
diff changeset
   165
        for (T t: iter)
06bc494ca11e Initial load
duke
parents:
diff changeset
   166
            l.add(t);
06bc494ca11e Initial load
duke
parents:
diff changeset
   167
        return l;
06bc494ca11e Initial load
duke
parents:
diff changeset
   168
    }
06bc494ca11e Initial load
duke
parents:
diff changeset
   169
}