/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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 org.codehaus.groovy.ant;

import groovy.lang.GroovyClassLoader;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.apache.groovy.io.StringBuilderWriter;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.RuntimeConfigurable;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.Javac;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.GlobPatternMapper;
import org.apache.tools.ant.util.SourceFileScanner;
import org.codehaus.groovy.GroovyBugError;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.SourceExtensionHandler;
import org.codehaus.groovy.runtime.DefaultGroovyMethods;
import org.codehaus.groovy.runtime.DefaultGroovyStaticMethods;
import org.codehaus.groovy.tools.ErrorReporter;
import org.codehaus.groovy.tools.FileSystemCompiler;
import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
import org.objectweb.asm.ClassVisitor;
import picocli.CommandLine;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.StringTokenizer;

/**
 * Compiles Groovy source files using Ant.
 * <p>
 * Typically involves using Ant from the command-line and an Ant build file such as:
 * <pre>
 * &lt;?xml version="1.0"?&gt;
 * &lt;project name="MyGroovyBuild" default="compile"&gt;
 *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
 *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
 *
 *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
 *     &lt;classpath&gt;
 *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
 *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
 *     &lt;/classpath&gt;
 *   &lt;/taskdef&gt;
 *
 *   &lt;target name="compile" description="compile groovy sources"&gt;
 *     &lt;groovyc srcdir="src" destdir="bin" fork="true" listfiles="true" includeantruntime="false"/&gt;
 *       &lt;classpath&gt;
 *         &lt;fileset dir="${groovy.home}/lib" includes="groovy-*${groovy.version}.jar" excludes="groovy-ant-${groovy.version}.jar"/&gt;
 *       &lt;/classpath&gt;
 *     &lt;/groovyc&gt;
 *   &lt;/target&gt;
 * &lt;/project&gt;
 * </pre>
 * <p>
 * This task can take the following arguments:
 * <ul>
 * <li>srcdir</li>
 * <li>destdir</li>
 * <li>sourcepath</li>
 * <li>sourcepathRef</li>
 * <li>classpath</li>
 * <li>classpathRef</li>
 * <li>scriptExtension</li>
 * <li>targetBytecode</li>
 * <li>listfiles</li>
 * <li>failonerror</li>
 * <li>proceed</li>
 * <li>memoryInitialSize</li>
 * <li>memoryMaximumSize</li>
 * <li>encoding</li>
 * <li>verbose</li>
 * <li>includeantruntime</li>
 * <li>includejavaruntime</li>
 * <li>fork</li>
 * <li>javaHome</li>
 * <li>executable</li>
 * <li>updatedProperty</li>
 * <li>errorProperty</li>
 * <li>includeDestClasses</li>
 * <li>jointCompilationOptions</li>
 * <li>stacktrace</li>
 * <li>indy</li>
 * <li>scriptBaseClass</li>
 * <li>stubdir</li>
 * <li>keepStubs</li>
 * <li>forceLookupUnnamedFiles</li>
 * <li>configscript</li>
 * <li>parameters</li>
 * </ul>
 * And these nested tasks:
 * <ul>
 * <li>javac</li>
 * </ul>
 * Of these arguments, the <b>srcdir</b> and <b>destdir</b> are required.
 * <p>
 * When this task executes, it will recursively scan srcdir and destdir looking
 * for Groovy source files to compile. This task makes its compile decision based
 * on timestamp.
 * <p>
 * A more elaborate build file showing joint compilation:
 * <pre>
 * &lt;?xml version="1.0"?&gt;
 * &lt;project name="MyJointBuild" default="compile"&gt;
 *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
 *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
 *
 *   &lt;path id="classpath.main"&gt;
 *     &lt;fileset dir="${groovy.home}/lib"&gt;
 *       &lt;include name="groovy-*${groovy.version}.jar"/&gt;
 *       &lt;exclude name="groovy-ant-${groovy.version}.jar"/&gt;
 *     &lt;/fileset&gt;
 *   &lt;/path&gt;
 *
 *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
 *     &lt;classpath&gt;
 *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
 *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
 *     &lt;/classpath&gt;
 *   &lt;/taskdef&gt;
 *
 *   &lt;target name="clean"&gt;
 *     &lt;delete dir="bin" failonerror="false"/&gt;
 *   &lt;/target&gt;
 *
 *   &lt;target name="compile" depends="clean" description="compile java and groovy sources"&gt;
 *     &lt;mkdir dir="bin"/&gt;
 *
 *     &lt;groovyc srcdir="src" destdir="bin" stubdir="stubs" keepStubs="true"
 *      fork="true" includeantruntime="false" classpathref="classpath.main"&gt;
 *       &lt;javac debug="true" source="1.8" target="1.8"/&gt;
 *     &lt;/groovyc&gt;
 *   &lt;/target&gt;
 * &lt;/project&gt;
 * </pre>
 * <p>
 * Based on the implementation of the Javac task in Apache Ant.
 * <p>
 * Can also be used from {@link groovy.ant.AntBuilder} to allow the build file to be scripted in Groovy.
 */
public class Groovyc extends MatchingTask {

    private static final File[] EMPTY_FILE_ARRAY = new File[0];
    private static final String[] EMPTY_STRING_ARRAY = new String[0];

    private final LoggingHelper log = new LoggingHelper(this);

    private Path src;
    private File destDir;
    private Path compileClasspath;
    private Path compileSourcepath;
    private String encoding;
    private boolean stacktrace;
    private boolean verbose;
    private boolean includeAntRuntime = true;
    private boolean includeJavaRuntime;
    private boolean fork;
    private File forkJavaHome;
    private String forkedExecutable;
    private String memoryInitialSize;
    private String memoryMaximumSize;
    private String scriptExtension = "*.groovy";
    private String targetBytecode;

    protected boolean failOnError = true;
    protected boolean listFiles;
    protected File[] compileList = EMPTY_FILE_ARRAY;

    private String updatedProperty;
    private String errorProperty;
    private boolean taskSuccess = true;
    private boolean includeDestClasses = true;

    protected CompilerConfiguration configuration;
    private Javac javac;
    private boolean jointCompilation;

    private final List<File> temporaryFiles = new ArrayList<>(2);
    private File stubDir;
    private boolean keepStubs;
    private boolean forceLookupUnnamedFiles;
    private boolean useIndy;
    private String scriptBaseClass;
    private String configscript;

    private Set<String> scriptExtensions = new LinkedHashSet<>();

    /**
     * If true, generates metadata for reflection on method parameter names (jdk8+ only).  Defaults to false.
     */
    private boolean parameters;

    /**
     * If true, enable preview Java features (JEP 12) (jdk12+ only). Defaults to false.
     */
    private boolean previewFeatures;

    /**
     * Adds a path for source compilation.
     *
     * @return a nested src element.
     */
    public Path createSrc() {
        if (src == null) {
            src = new Path(getProject());
        }
        return src.createPath();
    }

    /**
     * Recreate src.
     *
     * @return a nested src element.
     */
    protected Path recreateSrc() {
        src = null;
        return createSrc();
    }

    /**
     * Set the source directories to find the source Java files.
     *
     * @param srcDir the source directories as a path
     */
    public void setSrcdir(Path srcDir) {
        if (src == null) {
            src = srcDir;
        } else {
            src.append(srcDir);
        }
    }

    /**
     * Gets the source dirs to find the source java files.
     *
     * @return the source directories as a path
     */
    public Path getSrcdir() {
        return src;
    }

    /**
     * Set the extension to use when searching for Groovy source files.
     * Accepts extensions in the form *.groovy, .groovy or groovy
     *
     * @param scriptExtension the extension of Groovy source files
     */
    public void setScriptExtension(String scriptExtension) {
        if (scriptExtension.startsWith("*.")) {
            this.scriptExtension = scriptExtension;
        } else if (scriptExtension.startsWith(".")) {
            this.scriptExtension = "*" + scriptExtension;
        } else {
            this.scriptExtension = "*." + scriptExtension;
        }
    }

    /**
     * Get the extension to use when searching for Groovy source files.
     *
     * @return the extension of Groovy source files
     */
    public String getScriptExtension() {
        return scriptExtension;
    }

    /**
     * Sets the bytecode compatibility level.
     * The parameter can take one of the values in {@link CompilerConfiguration#ALLOWED_JDKS}.
     *
     * @param version the bytecode compatibility level
     */
    public void setTargetBytecode(String version) {
        for (String allowedJdk : CompilerConfiguration.ALLOWED_JDKS) {
            if (allowedJdk.equals(version)) {
                this.targetBytecode = version;
                break;
            }
        }
    }

    /**
     * Retrieves the compiler bytecode compatibility level.
     *
     * @return bytecode compatibility level. Can be one of the values in {@link CompilerConfiguration#ALLOWED_JDKS}.
     */
    public String getTargetBytecode() {
        return this.targetBytecode;
    }

    /**
     * Set the destination directory into which the Java source
     * files should be compiled.
     *
     * @param destDir the destination director
     */
    public void setDestdir(File destDir) {
        this.destDir = destDir;
    }

    /**
     * Gets the destination directory into which the java source files
     * should be compiled.
     *
     * @return the destination directory
     */
    public File getDestdir() {
        return destDir;
    }

    /**
     * Set the sourcepath to be used for this compilation.
     *
     * @param sourcepath the source path
     */
    public void setSourcepath(Path sourcepath) {
        if (compileSourcepath == null) {
            compileSourcepath = sourcepath;
        } else {
            compileSourcepath.append(sourcepath);
        }
    }

    /**
     * Gets the sourcepath to be used for this compilation.
     *
     * @return the source path
     */
    public Path getSourcepath() {
        return compileSourcepath;
    }

    /**
     * Adds a path to sourcepath.
     *
     * @return a sourcepath to be configured
     */
    public Path createSourcepath() {
        if (compileSourcepath == null) {
            compileSourcepath = new Path(getProject());
        }
        return compileSourcepath.createPath();
    }

    /**
     * Adds a reference to a source path defined elsewhere.
     *
     * @param r a reference to a source path
     */
    public void setSourcepathRef(Reference r) {
        createSourcepath().setRefid(r);
    }

    /**
     * Set the classpath to be used for this compilation.
     *
     * @param classpath an Ant Path object containing the compilation classpath.
     */
    public void setClasspath(Path classpath) {
        if (compileClasspath == null) {
            compileClasspath = classpath;
        } else {
            compileClasspath.append(classpath);
        }
    }

    /**
     * Gets the classpath to be used for this compilation.
     *
     * @return the class path
     */
    public Path getClasspath() {
        return compileClasspath;
    }

    /**
     * Adds a path to the classpath.
     *
     * @return a class path to be configured
     */
    public Path createClasspath() {
        if (compileClasspath == null) {
            compileClasspath = new Path(getProject());
        }
        return compileClasspath.createPath();
    }

    /**
     * Adds a reference to a classpath defined elsewhere.
     *
     * @param r a reference to a classpath
     */
    public void setClasspathRef(Reference r) {
        createClasspath().setRefid(r);
    }

    /**
     * If true, list the source files being handed off to the compiler.
     * Default is false.
     *
     * @param list if true list the source files
     */
    public void setListfiles(boolean list) {
        listFiles = list;
    }

    /**
     * Get the listfiles flag.
     *
     * @return the listfiles flag
     */
    public boolean getListfiles() {
        return listFiles;
    }

    /**
     * Indicates whether the build will continue
     * even if there are compilation errors; defaults to true.
     *
     * @param fail if true halt the build on failure
     */
    public void setFailonerror(boolean fail) {
        failOnError = fail;
    }

    /**
     * @param proceed inverse of failonerror
     */
    public void setProceed(boolean proceed) {
        failOnError = !proceed;
    }

    /**
     * Gets the failonerror flag.
     *
     * @return the failonerror flag
     */
    public boolean getFailonerror() {
        return failOnError;
    }

    /**
     * The initial size of the memory for the underlying VM
     * if javac is run externally; ignored otherwise.
     * Defaults to the standard VM memory setting.
     * (Examples: 83886080, 81920k, or 80m)
     *
     * @param memoryInitialSize string to pass to VM
     */
    public void setMemoryInitialSize(String memoryInitialSize) {
        this.memoryInitialSize = memoryInitialSize;
    }

    /**
     * Gets the memoryInitialSize flag.
     *
     * @return the memoryInitialSize flag
     */
    public String getMemoryInitialSize() {
        return memoryInitialSize;
    }

    /**
     * The maximum size of the memory for the underlying VM
     * if javac is run externally; ignored otherwise.
     * Defaults to the standard VM memory setting.
     * (Examples: 83886080, 81920k, or 80m)
     *
     * @param memoryMaximumSize string to pass to VM
     */
    public void setMemoryMaximumSize(String memoryMaximumSize) {
        this.memoryMaximumSize = memoryMaximumSize;
    }

    /**
     * Gets the memoryMaximumSize flag.
     *
     * @return the memoryMaximumSize flag
     */
    public String getMemoryMaximumSize() {
        return memoryMaximumSize;
    }

    /**
     * Sets the file encoding for generated files.
     *
     * @param encoding the file encoding to be used
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * Returns the encoding to be used when creating files.
     *
     * @return the file encoding to use
     */
    public String getEncoding() {
        return encoding;
    }

    /**
     * Enable verbose compiling which will display which files
     * are being compiled. Default is false.
     */
    public void setVerbose(boolean verbose) {
        this.verbose = verbose;
    }

    /**
     * Gets the verbose flag.
     *
     * @return the verbose flag
     */
    public boolean getVerbose() {
        return verbose;
    }

    /**
     * If true, includes Ant's own classpath in the classpath. Default is true.
     * If setting to false and using groovyc in conjunction with AntBuilder
     * you might need to explicitly add the Groovy jar(s) to the groovyc
     * classpath using a nested classpath task.
     *
     * @param include if true, includes Ant's own classpath in the classpath
     */
    public void setIncludeantruntime(boolean include) {
        includeAntRuntime = include;
    }

    /**
     * Gets whether or not the ant classpath is to be included in the classpath.
     *
     * @return whether or not the ant classpath is to be included in the classpath
     */
    public boolean getIncludeantruntime() {
        return includeAntRuntime;
    }

    /**
     * If true, includes the Java runtime libraries in the classpath. Default is false.
     *
     * @param include if true, includes the Java runtime libraries in the classpath
     */
    public void setIncludejavaruntime(boolean include) {
        includeJavaRuntime = include;
    }

    /**
     * Gets whether or not the java runtime should be included in this
     * task's classpath.
     *
     * @return the includejavaruntime attribute
     */
    public boolean getIncludejavaruntime() {
        return includeJavaRuntime;
    }

    /**
     * If true forks the Groovy compiler. Default is false.
     *
     * @param f "true|false|on|off|yes|no"
     */
    public void setFork(boolean f) {
        fork = f;
    }

    /**
     * The JDK Home to use when forked.
     * Ignored if "executable" is specified.
     *
     * @param home the java.home value to use, default is the current JDK's home
     */
    public void setJavaHome(File home) {
        forkJavaHome = home;
    }

    /**
     * Sets the name of the java executable to use when
     * invoking the compiler in forked mode, ignored otherwise.
     *
     * @param forkExecPath the name of the executable
     * @since Groovy 1.8.7
     */
    public void setExecutable(String forkExecPath) {
        forkedExecutable = forkExecPath;
    }

    /**
     * The value of the executable attribute, if any.
     *
     * @return the name of the java executable
     * @since Groovy 1.8.7
     */
    public String getExecutable() {
        return forkedExecutable;
    }

    /**
     * The property to set on compilation success.
     * This property will not be set if the compilation
     * fails, or if there are no files to compile.
     *
     * @param updatedProperty the property name to use.
     */
    public void setUpdatedProperty(String updatedProperty) {
        this.updatedProperty = updatedProperty;
    }

    /**
     * The property to set on compilation failure.
     * This property will be set if the compilation
     * fails.
     *
     * @param errorProperty the property name to use.
     */
    public void setErrorProperty(String errorProperty) {
        this.errorProperty = errorProperty;
    }

    /**
     * This property controls whether to include the
     * destination classes directory in the classpath
     * given to the compiler.
     * The default value is "true".
     *
     * @param includeDestClasses the value to use.
     */
    public void setIncludeDestClasses(boolean includeDestClasses) {
        this.includeDestClasses = includeDestClasses;
    }

    /**
     * Get the value of the includeDestClasses property.
     *
     * @return the value.
     */
    public boolean isIncludeDestClasses() {
        return includeDestClasses;
    }

    /**
     * Get the result of the groovyc task (success or failure).
     *
     * @return true if compilation succeeded, or
     * was not necessary, false if the compilation failed.
     */
    public boolean getTaskSuccess() {
        return taskSuccess;
    }

    /**
     * Add the configured nested javac task if present to initiate joint compilation.
     */
    public void addConfiguredJavac(final Javac javac) {
        this.javac = javac;
        jointCompilation = true;
    }

    /**
     * Enable compiler to report stack trace information if a problem occurs
     * during compilation. Default is false.
     */
    public void setStacktrace(boolean stacktrace) {
        this.stacktrace = stacktrace;
    }

    /**
     * Set the indy flag.
     *
     * @param useIndy the indy flag
     */
    public void setIndy(boolean useIndy) {
        this.useIndy = useIndy;
    }

    /**
     * Get the value of the indy flag.
     *
     * @return if to use indy
     */
    public boolean getIndy() {
        return this.useIndy;
    }

    /**
     * Set the base script class name for the scripts (must derive from Script)
     *
     * @param scriptBaseClass Base class name for scripts (must derive from Script)
     */
    public void setScriptBaseClass(String scriptBaseClass) {
        this.scriptBaseClass = scriptBaseClass;
    }

    /**
     * Get the base script class name for the scripts (must derive from Script)
     *
     * @return Base class name for scripts (must derive from Script)
     */
    public String getScriptBaseClass() {
        return this.scriptBaseClass;
    }

    /**
     * Get the configuration file used to customize the compilation configuration.
     *
     * @return a path to a configuration script
     */
    public String getConfigscript() {
        return configscript;
    }

    /**
     * Set the configuration file used to customize the compilation configuration.
     *
     * @param configscript a path to a configuration script
     */
    public void setConfigscript(final String configscript) {
        this.configscript = configscript;
    }

    /**
     * Set the stub directory into which the Java source stub
     * files should be generated. The directory need not exist
     * and will not be deleted automatically - though its contents
     * will be cleared unless 'keepStubs' is true. Ignored when forked.
     *
     * @param stubDir the stub directory
     */
    public void setStubdir(File stubDir) {
        jointCompilation = true;
        this.stubDir = stubDir;
    }

    /**
     * Gets the stub directory into which the Java source stub
     * files should be generated
     *
     * @return the stub directory
     */
    public File getStubdir() {
        return stubDir;
    }

    /**
     * Set the keepStubs flag. Defaults to false. Set to true for debugging.
     * Ignored when forked.
     *
     * @param keepStubs should stubs be retained
     */
    public void setKeepStubs(boolean keepStubs) {
        this.keepStubs = keepStubs;
    }

    /**
     * Gets the keepStubs flag.
     *
     * @return the keepStubs flag
     */
    public boolean getKeepStubs() {
        return keepStubs;
    }

    /**
     * Set the forceLookupUnnamedFiles flag. Defaults to false.
     * <p>
     * The Groovyc Ant task is frequently used in the context of a build system
     * that knows the complete list of source files to be compiled. In such a
     * context, it is wasteful for the Groovy compiler to go searching the
     * classpath when looking for source files and hence by default the
     * Groovyc Ant task calls the compiler in a special mode with such searching
     * turned off. If you wish the compiler to search for source files then
     * you need to set this flag to {@code true}.
     *
     * @param forceLookupUnnamedFiles should unnamed source files be searched for on the classpath
     */
    public void setForceLookupUnnamedFiles(boolean forceLookupUnnamedFiles) {
        this.forceLookupUnnamedFiles = forceLookupUnnamedFiles;
    }

    /**
     * Gets the forceLookupUnnamedFiles flag.
     *
     * @return the forceLookupUnnamedFiles flag
     */
    public boolean getForceLookupUnnamedFiles() {
        return forceLookupUnnamedFiles;
    }

    /**
     * If true, generates metadata for reflection on method parameter names (jdk8+ only).  Defaults to false.
     *
     * @param parameters set to true to generate metadata.
     */
    public void setParameters(boolean parameters) {
        this.parameters = parameters;
    }

    /**
     * Returns true if parameter metadata generation has been enabled.
     */
    public boolean getParameters() {
        return this.parameters;
    }

    /**
     * If true, enable preview Java features (JEP 12) (jdk12+ only).
     *
     * @param previewFeatures set to true to enable preview features
     */
    public void setPreviewFeatures(boolean previewFeatures) {
        this.previewFeatures = previewFeatures;
    }

    /**
     * Returns true if preview features has been enabled.
     */
    public boolean getPreviewFeatures() {
        return previewFeatures;
    }

    /**
     * Executes the task.
     *
     * @throws BuildException if an error occurs
     */
    public void execute() throws BuildException {
        checkParameters();
        resetFileLists();
        loadRegisteredScriptExtensions();

        if (javac != null) jointCompilation = true;

        // scan source directories and dest directory to build up
        // compile lists
        String[] list = src.list();
        for (String filename : list) {
            File file = getProject().resolveFile(filename);
            if (!file.exists()) {
                throw new BuildException("srcdir \"" + file.getPath() + "\" does not exist!", getLocation());
            }
            DirectoryScanner ds = this.getDirectoryScanner(file);
            String[] files = ds.getIncludedFiles();
            scanDir(file, destDir != null ? destDir : file, files);
        }

        compile();
        if (updatedProperty != null
                && taskSuccess
                && compileList.length != 0) {
            getProject().setNewProperty(updatedProperty, "true");
        }
    }

    /**
     * Clear the list of files to be compiled and copied.
     */
    protected void resetFileLists() {
        compileList = EMPTY_FILE_ARRAY;
        scriptExtensions = new LinkedHashSet<>();
    }

    /**
     * Scans the directory looking for source files to be compiled.
     * The results are returned in the class variable compileList
     *
     * @param srcDir  The source directory
     * @param destDir The destination directory
     * @param files   An array of filenames
     */
    protected void scanDir(File srcDir, File destDir, String[] files) {
        GlobPatternMapper m = new GlobPatternMapper();
        SourceFileScanner sfs = new SourceFileScanner(this);
        File[] newFiles;
        for (String extension : getScriptExtensions()) {
            m.setFrom("*." + extension);
            m.setTo("*.class");
            newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
            addToCompileList(newFiles);
        }

        if (jointCompilation) {
            m.setFrom("*.java");
            m.setTo("*.class");
            newFiles = sfs.restrictAsFiles(files, srcDir, destDir, m);
            addToCompileList(newFiles);
        }
    }

    protected void addToCompileList(File[] newFiles) {
        if (newFiles.length > 0) {
            File[] newCompileList = new File[compileList.length + newFiles.length];
            System.arraycopy(compileList, 0, newCompileList, 0, compileList.length);
            System.arraycopy(newFiles, 0, newCompileList, compileList.length, newFiles.length);
            compileList = newCompileList;
        }
    }

    /**
     * Gets the list of files to be compiled.
     *
     * @return the list of files as an array
     */
    public File[] getFileList() {
        return compileList;
    }

    protected void checkParameters() throws BuildException {
        if (src == null) {
            throw new BuildException("srcdir attribute must be set!", getLocation());
        }
        if (src.size() == 0) {
            throw new BuildException("srcdir attribute must be set!", getLocation());
        }

        if (destDir != null && !destDir.isDirectory()) {
            throw new BuildException("destination directory \""
                    + destDir
                    + "\" does not exist or is not a directory",
                    getLocation());
        }

        if (encoding != null && !Charset.isSupported(encoding)) {
            throw new BuildException("encoding \"" + encoding + "\" not supported.");
        }
    }

    private void listFiles() {
        if (listFiles) {
            for (File srcFile : compileList) {
                log.info(srcFile.getAbsolutePath());
            }
        }
    }

    /**
     * If {@code groovyc} task includes a nested {@code javac} task, check for
     * shareable configuration.  {@code FileSystemCompiler} supports several
     * command-line arguments for configuring joint compilation:
     * <ul>
     * <li><tt>-j</tt> enables joint compile
     * <li><tt>-F</tt> is used to pass flags
     * <li><tt>-J</tt> is used to pass name=value pairs
     * </ul>
     * Joint compilation options are transferred from {@link FileSystemCompiler}
     * to {@link CompilerConfiguration}'s jointCompileOptions property.  Flags
     * are saved to key "flags" (with the inclusion of "parameters" if enabled
     * on groovyc), pairs are saved to key "namedValues" and the key "memStub"
     * may also be set to {@link Boolean#TRUE} to influence joint compilation.
     *
     * @see org.codehaus.groovy.tools.javac.JavacJavaCompiler
     * @see javax.tools.JavaCompiler
     */
    private List<String> extractJointOptions(Path classpath) {
        List<String> jointOptions = new ArrayList<>();
        if (!jointCompilation) return jointOptions;

        // map "debug" and "debuglevel" to "-Fg"
        if (javac.getDebug()) {
            jointOptions.add("-Fg" + Optional.ofNullable(javac.getDebugLevel()).map(level -> ":" + level).orElse(""));
        } else {
            jointOptions.add("-Fg:none");
        }

        // map "deprecation" to "-Fdeprecation"
        if (javac.getDeprecation()) {
            jointOptions.add("-Fdeprecation");
        }

        // map "nowarn" to "-Fnowarn"
        if (javac.getNowarn()) {
            jointOptions.add("-Fnowarn");
        }

        // map "verbose" to "-Fverbose"
        if (javac.getVerbose()) {
            jointOptions.add("-Fverbose");
        }

        RuntimeConfigurable rc = javac.getRuntimeConfigurableWrapper();

        for (Map.Entry<String, Object> e : rc.getAttributeMap().entrySet()) {
            String key = e.getKey();
            if (key.equals("depend")
                    || key.equals("encoding")
                    || key.equals("extdirs")
                    || key.equals("nativeheaderdir")
                    || key.equals("release")
                    || key.equals("source")
                    || key.equals("target")) {
                switch (key) {
                case "nativeheaderdir":
                    key = "h"; break;
                case "release":
                    key = "-" + key; // to get "--" when passed to javac
                }
                // map "depend", "encoding", etc. to "-Jkey=val"
                jointOptions.add("-J" + key + "=" + getProject().replaceProperties(e.getValue().toString()));

            } else if (key.contains("classpath")) {
                if (key.startsWith("boot")) {
                    // map "bootclasspath" or "bootclasspathref" to "-Jbootclasspath="
                    jointOptions.add("-Jbootclasspath=" + javac.getBootclasspath());
                } else {
                    // map "classpath" or "classpathref" to "--classpath"
                    classpath.add(javac.getClasspath());
                }
            } else if (key.contains("module") && key.contains("path")) {
                if (key.startsWith("upgrade")) {
                    // map "upgrademodulepath" or "upgrademodulepathref" to "-J-upgrade-module-path="
                    jointOptions.add("-J-upgrade-module-path=" + javac.getUpgrademodulepath());
                } else if (key.contains("source")) {
                    // map "modulesourcepath" or "modulesourcepathref" to "-J-module-source-path="
                    jointOptions.add("-J-module-source-path=" + javac.getModulesourcepath());
                } else {
                    // map "modulepath" or "modulepathref" to "-J-module-path="
                    jointOptions.add("-J-module-path=" + javac.getModulepath());
                }
            } else if (!key.contains("debug") && !key.equals("deprecation") && !key.equals("nowarn") && !key.equals("verbose")) {
                log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored.");
            }
            // TODO: defaultexcludes, excludes(file)?, includes(file)?, includeDestClasses, tempdir
        }

        // Ant's <javac> supports nested <compilerarg value=""> elements (there
        // can be multiple of them) for additional options to be passed to javac.
        for (RuntimeConfigurable childrc : Collections.list(rc.getChildren())) {
            if (childrc.getElementTag().equals("compilerarg")) {
                for (Map.Entry<String, Object> e : childrc.getAttributeMap().entrySet()) {
                    String key = e.getKey();
                    if (key.equals("value")) {
                        String value = getProject().replaceProperties(e.getValue().toString());
                        StringTokenizer st = new StringTokenizer(value, " ");
                        while (st.hasMoreTokens()) {
                            String option = st.nextToken();
                            // GROOVY-5063: map "-Werror", etc. to "-FWerror"
                            jointOptions.add(option.replaceFirst("^-(W|X|proc:)", "-F$1"));
                        }
                    }
                }
            }
        }

        return jointOptions;
    }

    private void doForkCommandLineList(List<String> commandLineList, Path classpath, String separator) {
        if (forkedExecutable != null && !forkedExecutable.isEmpty()) {
            commandLineList.add(forkedExecutable);
        } else {
            String javaHome;
            if (forkJavaHome != null) {
                javaHome = forkJavaHome.getPath();
            } else {
                javaHome = System.getProperty("java.home");
            }
            commandLineList.add(javaHome + separator + "bin" + separator + "java");
        }

        String[] bootstrapClasspath;
        ClassLoader loader = getClass().getClassLoader();
        if (loader instanceof AntClassLoader) {
            bootstrapClasspath = ((AntClassLoader) loader).getClasspath().split(File.pathSeparator);
        } else {
            Class<?>[] bootstrapClasses = {
                FileSystemCompilerFacade.class,
                FileSystemCompiler.class,
                ParseTreeVisitor.class,
                ClassVisitor.class,
                CommandLine.class,
            };
            bootstrapClasspath = Arrays.stream(bootstrapClasses).map(Groovyc::getLocation)
                .map(uri -> new File(uri).getAbsolutePath()).distinct().toArray(String[]::new);
        }
        if (bootstrapClasspath.length > 0) {
            commandLineList.add("-classpath");
            commandLineList.add(getClasspathRelative(bootstrapClasspath));
        }

        if (memoryInitialSize != null && !memoryInitialSize.isEmpty()) {
            commandLineList.add("-Xms" + memoryInitialSize);
        }
        if (memoryMaximumSize != null && !memoryMaximumSize.isEmpty()) {
            commandLineList.add("-Xmx" + memoryMaximumSize);
        }
        if (targetBytecode != null) {
            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
        }
        if (!"*.groovy".equals(getScriptExtension())) {
            String tmpExtension = getScriptExtension();
            if (tmpExtension.startsWith("*."))
                tmpExtension = tmpExtension.substring(1);
            commandLineList.add("-Dgroovy.default.scriptExtension=" + tmpExtension);
        }

        commandLineList.add(FileSystemCompilerFacade.class.getName());
        commandLineList.add("--classpath");
        if (includeAntRuntime) {
            classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
        }
        if (includeJavaRuntime) {
            classpath.addJavaRuntime();
        }
        commandLineList.add(getClasspathRelative(classpath.list()));
        if (forceLookupUnnamedFiles) {
            commandLineList.add("--forceLookupUnnamedFiles");
        }
    }

    private String getClasspathRelative(String[] classpath) {
        String baseDir = getProject().getBaseDir().getAbsolutePath();
        StringBuilder sb = new StringBuilder();
        for (String next : classpath) {
            if (sb.length() > 0) {
                sb.append(File.pathSeparatorChar);
            }
            if (next.startsWith(baseDir)) {
                sb.append(".").append(next, baseDir.length(), next.length());
            } else {
                sb.append(next);
            }
        }
        return sb.toString();
    }

    private static URI getLocation(Class<?> clazz) {
        try {
            return clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Add "groovyc" parameters to the commandLineList, based on the ant configuration.
     *
     * @param commandLineList
     * @param jointOptions
     * @param classpath
     */
    private void doNormalCommandLineList(List<String> commandLineList, List<String> jointOptions, Path classpath) {
        if (!fork) {
            commandLineList.add("--classpath");
            commandLineList.add(classpath.toString());
        }
        if (jointCompilation) {
            commandLineList.add("-j");
            commandLineList.addAll(jointOptions);
        }
        if (destDir != null) {
            commandLineList.add("-d");
            commandLineList.add(destDir.getPath());
        }
        if (encoding != null) {
            commandLineList.add("--encoding");
            commandLineList.add(encoding);
        }
        if (stacktrace) {
            commandLineList.add("-e");
        }
        if (parameters) {
            commandLineList.add("--parameters");
        }
        if (previewFeatures) {
            commandLineList.add("--enable-preview");
        }
        if (useIndy) {
            commandLineList.add("--indy");
        }
        if (scriptBaseClass != null) {
            commandLineList.add("-b");
            commandLineList.add(scriptBaseClass);
        }
        if (configscript != null) {
            commandLineList.add("--configscript");
            commandLineList.add(configscript);
        }
    }

    private void addSourceFiles(List<String> commandLineList) {
        // check to see if an external file is needed
        int count = 0;
        if (fork) {
            for (File srcFile : compileList) {
                count += srcFile.getPath().length();
            }
            for (Object commandLineArg : commandLineList) {
                count += commandLineArg.toString().length();
            }
            count += compileList.length;
            count += commandLineList.size();
        }
        // 32767 is the command line length limit on Windows
        if (fork && (count > 32767)) {
            try {
                File tempFile = File.createTempFile("groovyc-files-", ".txt");
                temporaryFiles.add(tempFile);
                PrintWriter pw = new PrintWriter(new FileWriter(tempFile));
                for (File srcFile : compileList) {
                    pw.println(srcFile.getPath());
                }
                pw.close();
                commandLineList.add("@" + tempFile.getPath());
            } catch (IOException e) {
                log.error("Error creating file list", e);
            }
        } else {
            for (File srcFile : compileList) {
                commandLineList.add(srcFile.getPath());
            }
        }
    }

    private String[] makeCommandLine(List<String> commandLineList) {
        log.info("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
        return commandLineList.toArray(EMPTY_STRING_ARRAY);
    }

    private void runForked(String[] commandLine) {
        Execute executor = new Execute();
        executor.setAntRun(getProject());
        executor.setWorkingDirectory(getProject().getBaseDir());
        executor.setCommandline(commandLine);
        try {
            executor.execute();
        } catch (final IOException ioe) {
            throw new BuildException("Error running forked groovyc.", ioe);
        }
        int returnCode = executor.getExitValue();
        if (returnCode != 0) {
            taskSuccess = false;
            if (errorProperty != null) {
                getProject().setNewProperty(errorProperty, "true");
            }
            if (failOnError) {
                throw new BuildException("Forked groovyc returned error code: " + returnCode);
            } else {
                log.error("Forked groovyc returned error code: " + returnCode);
            }
        }
    }

    private void runCompiler(String[] commandLine) {
        // hand crank it so we can add our own compiler configuration
        try {
            FileSystemCompiler.CompilationOptions options = new FileSystemCompiler.CompilationOptions();
            CommandLine parser = FileSystemCompiler.configureParser(options);
            parser.parseArgs(commandLine);
            configuration = options.toCompilerConfiguration();
            configuration.setScriptExtensions(getScriptExtensions());
            String tmpExtension = getScriptExtension();
            if (tmpExtension.startsWith("*."))
                tmpExtension = tmpExtension.substring(1);
            configuration.setDefaultScriptExtension(tmpExtension);
            if (targetBytecode != null) {
                configuration.setTargetBytecode(targetBytecode);
            }

            // Load the file name list
            String[] fileNames = options.generateFileNames();
            boolean fileNameErrors = (fileNames == null || !FileSystemCompiler.validateFiles(fileNames));
            if (!fileNameErrors) {
                try (GroovyClassLoader loader = buildClassLoaderFor()) {
                    FileSystemCompiler.doCompilation(configuration, makeCompileUnit(loader), fileNames, forceLookupUnnamedFiles);
                }
            }
        } catch (Exception e) {
            Throwable t = e;
            if (e.getClass() == RuntimeException.class && e.getCause() != null) {
                // unwrap to the real exception
                t = e.getCause();
            }
            Writer writer = new StringBuilderWriter();
            new ErrorReporter(t, false).write(new PrintWriter(writer));
            String message = writer.toString();

            taskSuccess = false;
            if (errorProperty != null) {
                getProject().setNewProperty(errorProperty, "true");
            }

            if (failOnError) {
                log.error(message);
                throw new BuildException("Compilation Failed", t, getLocation());
            } else {
                log.error(message);
            }
        }
    }

    protected void compile() {
        if (compileList.length == 0) return;

        try {
            log.info("Compiling " + compileList.length + " source file"
                    + (compileList.length == 1 ? "" : "s")
                    + (destDir != null ? " to " + destDir : ""));

            listFiles();

            Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
            List<String> jointOptions = extractJointOptions(classpath);
            List<String> commandLineList = new ArrayList<>();

            if (fork) doForkCommandLineList(commandLineList, classpath, File.separator);
            doNormalCommandLineList(commandLineList, jointOptions, classpath);
            addSourceFiles(commandLineList);

            String[] commandLine = makeCommandLine(commandLineList);

            if (fork) {
                runForked(commandLine);
            } else {
                runCompiler(commandLine);
            }
        } finally {
            for (File temporaryFile : temporaryFiles) {
                try {
                    FileSystemCompiler.deleteRecursive(temporaryFile);
                } catch (Throwable t) {
                    System.err.println("error: could not delete temp files - " + temporaryFile.getPath());
                }
            }
        }
    }

    /**
     * @deprecated This method is not in use anymore. Use {@link Groovyc#makeCompileUnit(GroovyClassLoader)} instead.
     */
    @Deprecated
    protected CompilationUnit makeCompileUnit() {
        return makeCompileUnit(buildClassLoaderFor());
    }

    protected CompilationUnit makeCompileUnit(GroovyClassLoader loader) {
        Map<String, Object> options = configuration.getJointCompilationOptions();
        if (options != null) {
            if (keepStubs) {
                options.put("keepStubs", Boolean.TRUE);
            }
            if (stubDir != null) {
                options.put("stubDir", stubDir);
            } else {
                try {
                    File tempStubDir = DefaultGroovyStaticMethods.createTempDir(null, "groovy-generated-", "-java-source");
                    temporaryFiles.add(tempStubDir);
                    options.put("stubDir", tempStubDir);
                } catch (IOException ioe) {
                    throw new BuildException(ioe);
                }
            }
            return new JavaAwareCompilationUnit(configuration, loader);
        } else {
            return new CompilationUnit(configuration, null, loader);
        }
    }

    protected GroovyClassLoader buildClassLoaderFor() {
        if (fork) {
            throw new GroovyBugError("Cannot use Groovyc#buildClassLoaderFor() for forked compilation");
        }
        // GROOVY-5044
        if (!getIncludeantruntime()) {
            throw new IllegalArgumentException("The includeAntRuntime=false option is not compatible with fork=false");
        }

        ClassLoader loader = getClass().getClassLoader();
        if (loader instanceof AntClassLoader) {
            AntClassLoader antLoader = (AntClassLoader) loader;
            String[] pathElm = antLoader.getClasspath().split(File.pathSeparator);
            List<String> classpath = configuration.getClasspath();
            /*
             * Iterate over the classpath provided to groovyc, and add any missing path
             * entries to the AntClassLoader.  This is a workaround, since for some reason
             * 'directory' classpath entries were not added to the AntClassLoader' classpath.
             */
            for (String cpEntry : classpath) {
                boolean found = false;
                for (String path : pathElm) {
                    if (cpEntry.equals(path)) {
                        found = true;
                        break;
                    }
                }
                /*
                 * fix for GROOVY-2284
                 * seems like AntClassLoader doesn't check if the file
                 * may not exist in the classpath yet
                 */
                if (!found && new File(cpEntry).exists()) {
                    try {
                        antLoader.addPathElement(cpEntry);
                    } catch (BuildException e) {
                        log.warn("The classpath entry " + cpEntry + " is not a valid Java resource");
                    }
                }
            }
        }

        GroovyClassLoader groovyLoader = AccessController.doPrivileged(
                (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(loader, configuration));
        if (!forceLookupUnnamedFiles) {
            // in normal case we don't need to do script lookups
            groovyLoader.setResourceLoader(filename -> null);
        }
        return groovyLoader;
    }

    private Set<String> getScriptExtensions() {
        return scriptExtensions;
    }

    private void loadRegisteredScriptExtensions() {
        if (scriptExtensions.isEmpty()) {
            scriptExtensions.add(getScriptExtension().substring(2)); // first extension will be the one set explicitly on <groovyc>

            Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
            try (GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader())) {
                for (String element : classpath.list()) {
                    loader.addClasspath(element);
                }
                scriptExtensions.addAll(SourceExtensionHandler.getRegisteredExtensions(loader));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
