JavacMessager.java revision 2601:8e638f046bf0
1254219Scy/*
2254219Scy * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3254219Scy * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4254219Scy *
5254219Scy * This code is free software; you can redistribute it and/or modify it
6254219Scy * under the terms of the GNU General Public License version 2 only, as
7254219Scy * published by the Free Software Foundation.  Oracle designates this
8254219Scy * particular file as subject to the "Classpath" exception as provided
9254219Scy * by Oracle in the LICENSE file that accompanied this code.
10254219Scy *
11254219Scy * This code is distributed in the hope that it will be useful, but WITHOUT
12254219Scy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13254219Scy * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14254219Scy * version 2 for more details (a copy is included in the LICENSE file that
15254219Scy * accompanied this code).
16254219Scy *
17254219Scy * You should have received a copy of the GNU General Public License version
18254219Scy * 2 along with this work; if not, write to the Free Software Foundation,
19254219Scy * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20254219Scy *
21254219Scy * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22254219Scy * or visit www.oracle.com if you need additional information or have any
23254219Scy * questions.
24254219Scy */
25
26package com.sun.tools.javac.processing;
27
28import com.sun.tools.javac.model.JavacElements;
29import com.sun.tools.javac.util.*;
30import com.sun.tools.javac.util.DefinedBy.Api;
31import com.sun.tools.javac.tree.JCTree;
32import com.sun.tools.javac.tree.JCTree.*;
33import javax.lang.model.element.*;
34import javax.tools.JavaFileObject;
35import javax.tools.Diagnostic;
36import javax.annotation.processing.*;
37
38/**
39 * An implementation of the Messager built on top of log.
40 *
41 * <p><b>This is NOT part of any supported API.
42 * If you write code that depends on this, you do so at your own risk.
43 * This code and its internal interfaces are subject to change or
44 * deletion without notice.</b>
45 */
46public class JavacMessager implements Messager {
47    Log log;
48    JavacProcessingEnvironment processingEnv;
49    int errorCount = 0;
50    int warningCount = 0;
51
52    JavacMessager(Context context, JavacProcessingEnvironment processingEnv) {
53        log = Log.instance(context);
54        this.processingEnv = processingEnv;
55    }
56
57    // processingEnv.getElementUtils()
58
59    @DefinedBy(Api.ANNOTATION_PROCESSING)
60    public void printMessage(Diagnostic.Kind kind, CharSequence msg) {
61        printMessage(kind, msg, null, null, null);
62    }
63
64    @DefinedBy(Api.ANNOTATION_PROCESSING)
65    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
66                      Element e) {
67        printMessage(kind, msg, e, null, null);
68    }
69
70    /**
71     * Prints a message of the specified kind at the location of the
72     * annotation mirror of the annotated element.
73     *
74     * @param kind the kind of message
75     * @param msg  the message, or an empty string if none
76     * @param e    the annotated element
77     * @param a    the annotation to use as a position hint
78     */
79    @DefinedBy(Api.ANNOTATION_PROCESSING)
80    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
81                      Element e, AnnotationMirror a) {
82        printMessage(kind, msg, e, a, null);
83    }
84
85    /**
86     * Prints a message of the specified kind at the location of the
87     * annotation value inside the annotation mirror of the annotated
88     * element.
89     *
90     * @param kind the kind of message
91     * @param msg  the message, or an empty string if none
92     * @param e    the annotated element
93     * @param a    the annotation containing the annotaiton value
94     * @param v    the annotation value to use as a position hint
95     */
96    @DefinedBy(Api.ANNOTATION_PROCESSING)
97    public void printMessage(Diagnostic.Kind kind, CharSequence msg,
98                      Element e, AnnotationMirror a, AnnotationValue v) {
99        JavaFileObject oldSource = null;
100        JavaFileObject newSource = null;
101        JCDiagnostic.DiagnosticPosition pos = null;
102        JavacElements elemUtils = processingEnv.getElementUtils();
103        Pair<JCTree, JCCompilationUnit> treeTop = elemUtils.getTreeAndTopLevel(e, a, v);
104        if (treeTop != null) {
105            newSource = treeTop.snd.sourcefile;
106            if (newSource != null) {
107                // save the old version and reinstate it later
108                oldSource = log.useSource(newSource);
109                pos = treeTop.fst.pos();
110            }
111        }
112        try {
113            switch (kind) {
114            case ERROR:
115                errorCount++;
116                boolean prev = log.multipleErrors;
117                log.multipleErrors = true;
118                try {
119                    log.error(pos, "proc.messager", msg.toString());
120                } finally {
121                    log.multipleErrors = prev;
122                }
123                break;
124
125            case WARNING:
126                warningCount++;
127                log.warning(pos, "proc.messager", msg.toString());
128                break;
129
130            case MANDATORY_WARNING:
131                warningCount++;
132                log.mandatoryWarning(pos, "proc.messager", msg.toString());
133                break;
134
135            default:
136                log.note(pos, "proc.messager", msg.toString());
137                break;
138            }
139        } finally {
140            // reinstate the saved version, only if it was saved earlier
141            if (newSource != null)
142                log.useSource(oldSource);
143        }
144    }
145
146    /**
147     * Prints an error message.
148     * Equivalent to {@code printError(null, msg)}.
149     * @param msg  the message, or an empty string if none
150     */
151    public void printError(String msg) {
152        printMessage(Diagnostic.Kind.ERROR, msg);
153    }
154
155    /**
156     * Prints a warning message.
157     * Equivalent to {@code printWarning(null, msg)}.
158     * @param msg  the message, or an empty string if none
159     */
160    public void printWarning(String msg) {
161        printMessage(Diagnostic.Kind.WARNING, msg);
162    }
163
164    /**
165     * Prints a notice.
166     * @param msg  the message, or an empty string if none
167     */
168    public void printNotice(String msg) {
169        printMessage(Diagnostic.Kind.NOTE, msg);
170    }
171
172    public boolean errorRaised() {
173        return errorCount > 0;
174    }
175
176    public int errorCount() {
177        return errorCount;
178    }
179
180    public int warningCount() {
181        return warningCount;
182    }
183
184    public void newRound() {
185        errorCount = 0;
186    }
187
188    public String toString() {
189        return "javac Messager";
190    }
191}
192