JavacMessager.java revision 2571:10fc81ac75b4
1121054Semax/*
2121054Semax * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3121054Semax * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4121054Semax *
5121054Semax * This code is free software; you can redistribute it and/or modify it
6121054Semax * under the terms of the GNU General Public License version 2 only, as
7121054Semax * published by the Free Software Foundation.  Oracle designates this
8121054Semax * particular file as subject to the "Classpath" exception as provided
9121054Semax * by Oracle in the LICENSE file that accompanied this code.
10121054Semax *
11121054Semax * This code is distributed in the hope that it will be useful, but WITHOUT
12121054Semax * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13121054Semax * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14121054Semax * version 2 for more details (a copy is included in the LICENSE file that
15121054Semax * accompanied this code).
16121054Semax *
17121054Semax * You should have received a copy of the GNU General Public License version
18121054Semax * 2 along with this work; if not, write to the Free Software Foundation,
19121054Semax * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20121054Semax *
21121054Semax * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22121054Semax * or visit www.oracle.com if you need additional information or have any
23121054Semax * questions.
24121054Semax */
25121054Semax
26121054Semaxpackage com.sun.tools.javac.processing;
27121054Semax
28121054Semaximport com.sun.tools.javac.model.JavacElements;
29121054Semaximport com.sun.tools.javac.util.*;
30121054Semaximport com.sun.tools.javac.tree.JCTree;
31121054Semaximport com.sun.tools.javac.tree.JCTree.*;
32121054Semaximport javax.lang.model.element.*;
33121054Semaximport javax.tools.JavaFileObject;
34121054Semaximport javax.tools.Diagnostic;
35121054Semaximport javax.annotation.processing.*;
36121054Semax
37121054Semax/**
38121054Semax * An implementation of the Messager built on top of log.
39121054Semax *
40121054Semax * <p><b>This is NOT part of any supported API.
41121054Semax * If you write code that depends on this, you do so at your own risk.
42121054Semax * This code and its internal interfaces are subject to change or
43121054Semax * deletion without notice.</b>
44121054Semax */
45121054Semaxpublic class JavacMessager implements Messager {
46121054Semax    Log log;
47121054Semax    JavacProcessingEnvironment processingEnv;
48121054Semax    int errorCount = 0;
49121054Semax    int warningCount = 0;
50121054Semax
51121054Semax    JavacMessager(Context context, JavacProcessingEnvironment processingEnv) {
52121054Semax        log = Log.instance(context);
53121054Semax        this.processingEnv = processingEnv;
54121054Semax    }
55121054Semax
56121054Semax    // processingEnv.getElementUtils()
57121054Semax
58121054Semax    public void printMessage(Diagnostic.Kind kind, CharSequence msg) {
59121054Semax        printMessage(kind, msg, null, null, null);
60121054Semax    }
61121054Semax
62121054Semax    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
63121054Semax                      Element e) {
64121054Semax        printMessage(kind, msg, e, null, null);
65121054Semax    }
66121054Semax
67121054Semax    /**
68121054Semax     * Prints a message of the specified kind at the location of the
69121054Semax     * annotation mirror of the annotated element.
70121054Semax     *
71121054Semax     * @param kind the kind of message
72121054Semax     * @param msg  the message, or an empty string if none
73121054Semax     * @param e    the annotated element
74121054Semax     * @param a    the annotation to use as a position hint
75121054Semax     */
76121054Semax    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
77121054Semax                      Element e, AnnotationMirror a) {
78121054Semax        printMessage(kind, msg, e, a, null);
79121054Semax    }
80121054Semax
81121054Semax    /**
82121054Semax     * Prints a message of the specified kind at the location of the
83121054Semax     * annotation value inside the annotation mirror of the annotated
84121054Semax     * element.
85121054Semax     *
86121054Semax     * @param kind the kind of message
87121054Semax     * @param msg  the message, or an empty string if none
88121054Semax     * @param e    the annotated element
89121054Semax     * @param a    the annotation containing the annotaiton value
90121054Semax     * @param v    the annotation value to use as a position hint
91121054Semax     */
92121054Semax    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
93121054Semax                      Element e, AnnotationMirror a, AnnotationValue v) {
94121054Semax        JavaFileObject oldSource = null;
95121054Semax        JavaFileObject newSource = null;
96121054Semax        JCDiagnostic.DiagnosticPosition pos = null;
97121054Semax        JavacElements elemUtils = processingEnv.getElementUtils();
98121054Semax        Pair<JCTree, JCCompilationUnit> treeTop = elemUtils.getTreeAndTopLevel(e, a, v);
99121054Semax        if (treeTop != null) {
100121054Semax            newSource = treeTop.snd.sourcefile;
101121054Semax            if (newSource != null) {
102121054Semax                // save the old version and reinstate it later
103121054Semax                oldSource = log.useSource(newSource);
104121054Semax                pos = treeTop.fst.pos();
105121054Semax            }
106121054Semax        }
107121054Semax        try {
108121054Semax            switch (kind) {
109121054Semax            case ERROR:
110121054Semax                errorCount++;
111121054Semax                boolean prev = log.multipleErrors;
112121054Semax                log.multipleErrors = true;
113121054Semax                try {
114121054Semax                    log.error(pos, "proc.messager", msg.toString());
115121054Semax                } finally {
116121054Semax                    log.multipleErrors = prev;
117121054Semax                }
118121054Semax                break;
119121054Semax
120121054Semax            case WARNING:
121121054Semax                warningCount++;
122121054Semax                log.warning(pos, "proc.messager", msg.toString());
123121054Semax                break;
124121054Semax
125121054Semax            case MANDATORY_WARNING:
126121054Semax                warningCount++;
127121054Semax                log.mandatoryWarning(pos, "proc.messager", msg.toString());
128121054Semax                break;
129121054Semax
130121054Semax            default:
131121054Semax                log.note(pos, "proc.messager", msg.toString());
132121054Semax                break;
133121054Semax            }
134121054Semax        } finally {
135121054Semax            // reinstate the saved version, only if it was saved earlier
136121054Semax            if (newSource != null)
137121054Semax                log.useSource(oldSource);
138121054Semax        }
139121054Semax    }
140121054Semax
141121054Semax    /**
142121054Semax     * Prints an error message.
143     * Equivalent to {@code printError(null, msg)}.
144     * @param msg  the message, or an empty string if none
145     */
146    public void printError(String msg) {
147        printMessage(Diagnostic.Kind.ERROR, msg);
148    }
149
150    /**
151     * Prints a warning message.
152     * Equivalent to {@code printWarning(null, msg)}.
153     * @param msg  the message, or an empty string if none
154     */
155    public void printWarning(String msg) {
156        printMessage(Diagnostic.Kind.WARNING, msg);
157    }
158
159    /**
160     * Prints a notice.
161     * @param msg  the message, or an empty string if none
162     */
163    public void printNotice(String msg) {
164        printMessage(Diagnostic.Kind.NOTE, msg);
165    }
166
167    public boolean errorRaised() {
168        return errorCount > 0;
169    }
170
171    public int errorCount() {
172        return errorCount;
173    }
174
175    public int warningCount() {
176        return warningCount;
177    }
178
179    public void newRound() {
180        errorCount = 0;
181    }
182
183    public String toString() {
184        return "javac Messager";
185    }
186}
187