// Copyright 2011 The Bazel Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.devtools.build.buildjar.javac.plugins; import com.google.devtools.build.buildjar.InvalidCommandLineException; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.main.JavaCompiler; import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.PropagatedException; import java.util.List; /** * An interface for additional static analyses that need access to the javac compiler's AST at * specific points in the compilation process. This class provides callbacks after the attribute and * flow phases of the javac compilation process. A static analysis may be implemented by subclassing * this abstract class and performing the analysis in the callback methods. The analysis may then be * registered with the BlazeJavaCompiler to be run during the compilation process. See * {@link com.google.devtools.build.buildjar.javac.plugins.dependency.StrictJavaDepsPlugin} for an * example. */ public abstract class BlazeJavaCompilerPlugin { /** * Allows plugins to pass errors through javac.Main to BlazeJavacMain and cleanly shut down the * compiler. */ public static final class PluginException extends RuntimeException { private final Result result; private final String message; /** The compiler's exit status. */ public Result getResult() { return result; } /** The message that will be printed to stderr before shutting down. */ @Override public String getMessage() { return message; } private PluginException(Result result, String message) { this.result = result; this.message = message; } } /** * Pass an error through javac.Main to BlazeJavacMain and cleanly shut down the compiler. */ protected static Exception throwError(Result result, String message) { // Javac re-throws exceptions wrapped by PropagatedException. throw new PropagatedException(new PluginException(result, message)); } protected Context context; protected Log log; protected JavaCompiler compiler; /** * Preprocess the command-line flags that were passed to javac. This is called before * {@link #init(Context, Log, JavaCompiler)} and {@link #initializeContext(Context)}. * * @param args The command-line flags that javac was invoked with. * @throws InvalidCommandLineException if the arguments are invalid * @returns The flags that do not belong to this plugin. */ public List processArgs(List args) throws InvalidCommandLineException { return args; } /** * Called after all plugins have processed arguments and can be used to customize the Java * compiler context. */ public void initializeContext(Context context) { this.context = context; } /** * Performs analysis actions after the attribute phase of the javac compiler. * The attribute phase performs symbol resolution on the parse tree. * * @param env The attributed parse tree (after symbol resolution) */ public void postAttribute(Env env) {} /** * Performs analysis actions after the flow phase of the javac compiler. * The flow phase performs dataflow checks, such as finding unreachable * statements. * * @param env The attributed parse tree (after symbol resolution) */ public void postFlow(Env env) {} /** * Performs analysis actions when the compiler is done and is about to wipe * clean its internal data structures (such as the symbol table). */ public void finish() {} /** * Initializes the plugin. Called by * {@link com.google.devtools.build.buildjar.javac.BlazeJavaCompiler}'s constructor. * * @param context The Context object from the enclosing BlazeJavaCompiler instance * @param log The Log object from the enclosing BlazeJavaCompiler instance * @param compiler The enclosing BlazeJavaCompiler instance */ public void init(Context context, Log log, JavaCompiler compiler) { this.context = context; this.log = log; this.compiler = compiler; } }