Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openjdk/test/langtools/tools/javac/lib/combo/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 15 kB image not shown  

Quelle  ComboTask.java   Sprache: JAVA

 
/*
 * 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.
 */


package combo;

import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskListener;
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import combo.ComboParameter.Resolver;

import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 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.
 */

public class 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();

    /** Combo execution environment. */
    private ComboTestHelper<?>.Env env;

    ComboTask(ComboTestHelper<?>.Env env) {
        this.env = env;
    }

    /**
     * Add a new source to this task.
     */

    public ComboTask withSource(JavaFileObject comboSource) {
        sources = sources.prepend(comboSource);
        return this;
    }

    /**
     * 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);
        return this;
    }

    /**
     * Add a set of options to this task.
     */

    public ComboTask withOptions(String[] opts) {
        for (String opt : opts) {
            options = options.append(opt);
        }
        return this;
    }

    /**
     * Add a set of options to this task.
     */

    public ComboTask withOptions(Iterable<? extends String> opts) {
        for (String opt : opts) {
            options = options.append(opt);
        }
        return this;
    }

    /**
     * Set the output writer associated with this task.
     */

    public ComboTask withWriter(Writer out) {
        this.out = out;
        return this;
    }

    /**
     * Add a task listener to this task.
     */

    public ComboTask withListener(TaskListener listener) {
        listeners = listeners.prepend(listener);
        return this;
    }

    /**
     * Add a task listener factory to this task.
     */

    public ComboTask withListenerFactory(Function<Context, TaskListener> factory) {
        listenerFactories = listenerFactories.prepend(factory);
        return this;
    }

    /**
     * Parse the sources associated with this task.
     */

    public void parse(Consumer<Result<Iterable<? extends CompilationUnitTree>>> c) {
        doRunTest(c, JavacTask::parse);
    }

    /**
     * Parse and analyzes the sources associated with this task.
     */

    public void analyze(Consumer<Result<Iterable<? extends Element>>> c) {
        doRunTest(c, JavacTask::analyze);
    }

    /**
     * Parse, analyze and perform code generation for the sources associated with this task.
     */

    public void generate(Consumer<Result<Iterable<? extends JavaFileObject>>> c) {
        doRunTest(c, JavacTask::generate);
    }

    private <V> void doRunTest(Consumer<Result<Iterable<? extends V>>> c,
                               Convertor<V> task2Data) {
        env.pool().getTask(out, env.fileManager(),
                diagsCollector, options, null, sources, task -> {
            try {
                for (TaskListener l : listeners) {
                    task.addTaskListener(l);
                }
                for (Function<Context, TaskListener> f : listenerFactories) {
                    task.addTaskListener(f.apply(((JavacTaskImpl) task).getContext()));
                }
                c.accept(new Result<>(task2Data.convert(task)));
                return null;
            } catch (IOException ex) {
                throw new AssertionError(ex);
            }
        });
    }

    public List<JavaFileObject> getSources() {
        return sources;
    }

    interface Convertor<V> {
        public Iterable<? extends V> convert(JavacTask task) throws IOException;
    }

    /**
     * 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
     */

    public class ExecutionTask {
        private ClassLoader classLoader;
        private String methodName = "main";
        private Class<?>[] parameterTypes = new Class<?>[]{String[].class};
        private Object[] args = new String[0];
        private Consumer<Throwable> handler;
        private Class<?> c;

        private ExecutionTask(ClassLoader classLoader) {
            this.classLoader = classLoader;
        }

        /**
         * 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) {
                throw new IllegalStateException(t);
            }
            return this;
        }

        /**
         * 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;
            return this;
        }

        /**
         * Set the arguments to be passed to the method.
         */

        public ExecutionTask withArguments(Object... args) {
            this.args = args;
            return this;
        }

        /**
         * Set a handler to handle any exception thrown.
         */

        public ExecutionTask withHandler(Consumer<Throwable> handler) {
            this.handler = handler;
            return this;
        }

        /**
         * 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);
                return true;
            } catch (Throwable t) {
                if (handler != null) {
                    handler.accept(t);
                }
                return false;
            }
        }
    }

    /**
     * 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.
     */

    public class Result<D> {

        /** The underlying compilation results. */
        private final D data;

        public Result(D data) {
            this.data = data;
        }

        public D get() {
            return data;
        }

        /**
         * Did this task generate any error diagnostics?
         */

        public boolean hasErrors() {
            return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.ERROR);
        }

        /**
         * Did this task generate any warning diagnostics?
         */

        public boolean hasWarnings() {
            return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.WARNING);
        }

        /**
         * Did this task generate any note diagnostics?
         */

        public boolean hasNotes() {
            return diagsCollector.diagsByKind.containsKey(Diagnostic.Kind.NOTE);
        }

        /**
         * Did this task generate any diagnostic with given key?
         */

        public boolean 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();
        }

        /**
         * Dump useful info associated with this task.
         */

        public String compilationInfo() {
            return "instance#" + env.info().comboCount + ":[ options = " + options
                    + ", diagnostics = " + diagsCollector.diagsByKeys.keySet()
                    + ", dimensions = " + env.bindings
                    + ", sources = \n" + sources.stream().map(s -> {
                try {
                    return s.getCharContent(true);
                } catch (IOException ex) {
                    return "";
                }
            }).collect(Collectors.joining(",")) + "]";
        }
    }

    /**
     * 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<>();

        protected ComboTemplateSource(String name, String template) {
            this(name, template, null);
        }

        protected ComboTemplateSource(String name, String template, Resolver resolver) {
            super(URI.create("myfo:/" + env.info().comboCount + "/" + name + ".java"), Kind.SOURCE);
            source = ComboParameter.expandTemplate(template, pname -> resolveParameter(pname, resolver));
        }

        @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<>();

        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
            List<Diagnostic<? extends JavaFileObject>> diags =
                    diagsByKeys.getOrDefault(diagnostic.getCode(), List.nil());
            diagsByKeys.put(diagnostic.getCode(), diags.prepend(diagnostic));
            Diagnostic.Kind kind = diagnostic.getKind();
            diags = diagsByKind.getOrDefault(kind, List.nil());
            diagsByKind.put(kind, diags.prepend(diagnostic));
        }
    }
}

Messung V0.5
C=95 H=91 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.