/*
 *  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 edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
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.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>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 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(final String version) {
        this.targetBytecode = version;
    }

    /**
     * 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 the ant classpath is to be included in the classpath.
     *
     * @return whether 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 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;
    }

    /**
     * Legacy method to set the indy flag (only true is allowed)
     *
     * @param indy true means invokedynamic support is active
     */
    @Deprecated
    public void setIndy(final boolean indy) {
        if (!indy) {
            throw new BuildException("Disabling indy is no longer supported!", getLocation());
        }
    }

    /**
     * Get the value of the indy flag (always true).
     */
    @Deprecated
    public boolean getIndy() {
        return true;
    }

    /**
     * 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
     */
    @Override
    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 Arrays.copyOf(compileList, compileList.length);
    }

    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
                        break;
                    default:
                }
                // 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) {
            CompilerConfiguration cc = new CompilerConfiguration();
            cc.setTargetBytecode(targetBytecode); // GROOVY-10278: nearest valid value
            commandLineList.add("-Dgroovy.target.bytecode=" + cc.getTargetBytecode());
        }
        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 (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 = printWriter(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());
            }
        }
    }

    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "This is only used to store filenames when exceeding a particular length limit when in fork mode")
    private PrintWriter printWriter(File tempFile) throws IOException {
        // we could make a forkFileListEncoding but seems like a rare scenario
        return new PrintWriter(new FileWriter(tempFile));
    }

    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, -1);
            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");
                    }
                }
            }
        }

        @SuppressWarnings("removal") // TODO a future Groovy version should perform the operation not as a privileged action
        GroovyClassLoader groovyLoader = java.security.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);
            }
        }
    }
}
