/* * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
/** * This class represents a compilation task associated with a combo test instance. This is a small * wrapper around {@link JavacTask} which allows for fluent setup style and which makes use of * the shared compilation context to speedup performances.
*/ publicclass ComboTask {
/** Sources to be compiled in this task. */ private List<JavaFileObject> sources = List.nil();
/** Options associated with this task. */ private List<String> options = List.nil();
/** Diagnostic collector. */ private DiagnosticCollector diagsCollector = new DiagnosticCollector();
/** Output writer. */ private Writer out;
/** Listeners associated with this task. */ private List<TaskListener> listeners = List.nil();
/** Listener factories associated with this task. */ private List<Function<Context, TaskListener>> listenerFactories = List.nil();
/** * Add a new source to this task.
*/ public ComboTask withSource(JavaFileObject comboSource) {
sources = sources.prepend(comboSource); returnthis;
}
/** * Add a new template source with given name to this task; the template is replaced with * corresponding combo parameters (as defined in the combo test environment).
*/ public ComboTask withSourceFromTemplate(String name, String template) { return withSource(new ComboTemplateSource(name, template));
}
/** * Add a new template source with default name ("Test") to this task; the template is replaced with * corresponding combo parameters (as defined in the combo test environment).
*/ public ComboTask withSourceFromTemplate(String template) { return withSource(new ComboTemplateSource("Test", template));
}
/** * Add a new template source with given name to this task; the template is replaced with * corresponding combo parameters (as defined in the combo test environment). A custom resolver * is used to add combo parameter mappings to the current combo test environment.
*/ public ComboTask withSourceFromTemplate(String name, String template, Resolver resolver) { return withSource(new ComboTemplateSource(name, template, resolver));
}
/** * Add a new template source with default name ("Test") to this task; the template is replaced with * corresponding combo parameters (as defined in the combo test environment). A custom resolver * is used to add combo parameter mappings to the current combo test environment.
*/ public ComboTask withSourceFromTemplate(String template, Resolver resolver) { return withSource(new ComboTemplateSource("Test", template, resolver));
}
/** * Add a new option to this task.
*/ public ComboTask withOption(String opt) {
options = options.append(opt); returnthis;
}
/** * Add a set of options to this task.
*/ public ComboTask withOptions(String[] opts) { for (String opt : opts) {
options = options.append(opt);
} returnthis;
}
/** * Add a set of options to this task.
*/ public ComboTask withOptions(Iterable<? extends String> opts) { for (String opt : opts) {
options = options.append(opt);
} returnthis;
}
/** * Set the output writer associated with this task.
*/ public ComboTask withWriter(Writer out) { this.out = out; returnthis;
}
/** * Add a task listener to this task.
*/ public ComboTask withListener(TaskListener listener) {
listeners = listeners.prepend(listener); returnthis;
}
/** * Add a task listener factory to this task.
*/ public ComboTask withListenerFactory(Function<Context, TaskListener> factory) {
listenerFactories = listenerFactories.prepend(factory); returnthis;
}
/** * Parse the sources associated with this task.
*/ publicvoid parse(Consumer<Result<Iterable<? extends CompilationUnitTree>>> c) {
doRunTest(c, JavacTask::parse);
}
/** * Parse and analyzes the sources associated with this task.
*/ publicvoid analyze(Consumer<Result<Iterable<? extends Element>>> c) {
doRunTest(c, JavacTask::analyze);
}
/** * Parse, analyze and perform code generation for the sources associated with this task.
*/ publicvoid generate(Consumer<Result<Iterable<? extends JavaFileObject>>> c) {
doRunTest(c, JavacTask::generate);
}
/** * This class represents an execution task. It allows the execution of one or more classes previously * added to a given class loader. This class uses reflection to execute any given static public method * in any given class. It's not restricted to the execution of the {@code main} method
*/ publicclass ExecutionTask { private ClassLoader classLoader; private String methodName = "main"; privateClass<?>[] parameterTypes = newClass<?>[]{String[].class}; private Object[] args = new String[0]; private Consumer<Throwable> handler; privateClass<?> c;
/** * Set the name of the class to be loaded.
*/ public ExecutionTask withClass(String className) { Assert.check(className != null, "class name value is null, impossible to proceed"); try {
c = classLoader.loadClass(className);
} catch (Throwable t) { thrownew IllegalStateException(t);
} returnthis;
}
/** * Set the name of the method to be executed along with the parameter types to * reflectively obtain the method.
*/ public ExecutionTask withMethod(String methodName, Class<?>... parameterTypes) { this.methodName = methodName; this.parameterTypes = parameterTypes; returnthis;
}
/** * Set the arguments to be passed to the method.
*/ public ExecutionTask withArguments(Object... args) { this.args = args; returnthis;
}
/** * Set a handler to handle any exception thrown.
*/ public ExecutionTask withHandler(Consumer<Throwable> handler) { this.handler = handler; returnthis;
}
/** * Executes the given method in the given class. Returns true if the execution was * successful, false otherwise.
*/ public Object run() { try {
java.lang.reflect.Method meth = c.getMethod(methodName, parameterTypes);
meth.invoke(null, (Object)args); returntrue;
} catch (Throwable t) { if (handler != null) {
handler.accept(t);
} returnfalse;
}
}
}
/** * This class is used to help clients accessing the results of a given compilation task. * Contains several helper methods to inspect diagnostics generated during the task execution.
*/ publicclass Result<D> {
/** The underlying compilation results. */ privatefinal D data;
public Result(D data) { this.data = data;
}
public D get() { return data;
}
/** * Did this task generate any error diagnostics?
*/ publicboolean hasErrors() { return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.ERROR);
}
/** * Did this task generate any warning diagnostics?
*/ publicboolean hasWarnings() { return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.WARNING);
}
/** * Did this task generate any note diagnostics?
*/ publicboolean hasNotes() { return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.NOTE);
}
/** * Did this task generate any diagnostic with given key?
*/ publicboolean containsKey(String key) { return diagsCollector.diagsByKeys.containsKey(key);
}
/** * Retrieve the list of diagnostics of a given kind.
*/ public List<Diagnostic<? extends JavaFileObject>> diagnosticsForKind(Diagnostic.Kind kind) {
List<Diagnostic<? extends JavaFileObject>> diags = diagsCollector.diagsByKind.get(kind); return diags != null ? diags : List.nil();
}
/** * Retrieve the list of diagnostics with given key.
*/ public List<Diagnostic<? extends JavaFileObject>> diagnosticsForKey(String key) {
List<Diagnostic<? extends JavaFileObject>> diags = diagsCollector.diagsByKeys.get(key); return diags != null ? diags : List.nil();
}
/** * This class represents a Java source file whose contents are defined in terms of a template * string. The holes in such template are expanded using corresponding combo parameter * instances which can be retrieved using a resolver object.
*/ class ComboTemplateSource extends SimpleJavaFileObject {
String source;
Map<String, ComboParameter> localParametersCache = new HashMap<>();
@Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return source;
}
/** * Combo parameter resolver function. First parameters are looked up in the global environment, * then the local environment is looked up as a fallback.
*/
ComboParameter resolveParameter(String pname, Resolver resolver) { //first search the env
ComboParameter parameter = env.parametersCache.get(pname); if (parameter == null) { //then lookup local cache
parameter = localParametersCache.get(pname); if (parameter == null && resolver != null) { //if still null and we have a custom resolution function, try that
parameter = resolver.lookup(pname); if (parameter != null) { //if a match was found, store it in the local cache to aviod redundant recomputation
localParametersCache.put(pname, parameter);
}
}
} return parameter;
}
}
/** * Helper class to collect all diagnostic generated during the execution of a given compilation task.
*/ class DiagnosticCollector implements DiagnosticListener<JavaFileObject> {
Map<Diagnostic.Kind, List<Diagnostic<? extends JavaFileObject>>> diagsByKind = new HashMap<>();
Map<String, List<Diagnostic<? extends JavaFileObject>>> diagsByKeys = new HashMap<>();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.