
gosu.tools.ant.Gosuc Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gosu-ant-compiler Show documentation
Show all versions of gosu-ant-compiler Show documentation
Gosu Compiler support for Ant
The newest version!
package gosu.tools.ant;
import gw.lang.gosuc.simple.ICompilerDriver;
import gw.lang.gosuc.simple.IGosuCompiler;
import gw.lang.gosuc.simple.SoutCompilerDriver;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.GlobPatternMapper;
import org.apache.tools.ant.util.SourceFileScanner;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Ant task for compiling Gosu files to disk.
* The following parameters are available:
*
* - "srcdir" : A Path containing one or more source directories
* - "destdir" : A File representing the output destination of the compilation
* - "checkedarithmetic" : Compile with checked arithmetic if true. Defaults to {@code false}.
* - "failonerror" : Ignore compile errors and continue if true. Defaults to {@code true}.
*
*/
public class Gosuc extends GosuMatchingTask {
private Path _src;
private File _destDir;
private Path _compileClasspath;
private boolean _failOnError = true;
private boolean _checkedArithmetic = false;
private boolean _force = true;
private Set _scriptExtensions = new HashSet<>(Arrays.asList("gs", "gsx", "gst", "gsp"));
protected List compileList = new ArrayList<>();
/**
* Set the source directories to find the source Gosu 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 Gosu files.
*
* @return the source directories as a path
*/
public Path getSrcdir() {
return _src;
}
/**
* Set the destination directory into which the Gosu source
* files should be compiled.
*
* @param destDir the destination directory
*/
public void setDestdir(File destDir) {
_destDir = destDir;
}
/**
* Gets the destination directory into which the Gosu source files
* should be compiled.
*
* @return the destination directory
*/
public File getDestdir() {
return _destDir;
}
/**
* Adds a path to the classpath.
*
* @return a classpath 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 ref a reference to a classpath
*/
public void setClasspathRef(Reference ref) {
createClasspath().setRefid(ref);
}
private Set getScriptExtensions() {
return _scriptExtensions;
}
/**
* 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;
}
/**
* Gets the FailOnError flag.
*
* @return the FailOnError flag
*/
public boolean getFailOnError() {
return _failOnError;
}
public boolean isCheckedArithmetic() {
return _checkedArithmetic;
}
public void setCheckedArithmetic( boolean checkedArithmetic ) {
_checkedArithmetic = checkedArithmetic;
}
/**
* Gets the Force flag.
* ant's directory scanner is timestamp based. Without proper tasks, this could result in successful, but incomplete compilation.
* Therefore we default 'force' to true, which causes compilation of all matching source files, regardless of the timestamp comparison between source and target.
*
* @return
*/
public boolean isForce() {
return _force;
}
public void setForce( boolean force ) {
_force = force;
}
/**
* 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);
List newFiles;
if(!isForce()) {
log("Relying on ant's SourceFileScanner, which only looks at timestamps. If broken references result, try setting option 'force' to true.", Project.MSG_WARN);
}
for (String extension : getScriptExtensions()) {
m.setFrom("*." + extension);
m.setTo("*.class");
log("Scanning for *." + extension + " files...", Project.MSG_DEBUG);
if(isForce()) {
newFiles = asFiles(srcDir, files, m);
} else {
newFiles = Arrays.asList(sfs.restrictAsFiles(files, srcDir, destDir, m));
}
log("Found these files:", Project.MSG_DEBUG);
for(File newFile : newFiles) {
log('\t' + newFile.getAbsolutePath(), Project.MSG_DEBUG);
}
compileList.addAll(newFiles);
}
}
/**
* Converts an array of relative String filenames to a {@code List}
* @param srcDir The root directory of all files
* @param files All files are relative to srcDir
* @return a List of Files by joining srcDir to each file
*/
private List asFiles(File srcDir, String[] files, FileNameMapper m) {
List newFiles = new ArrayList<>();
for(String file : files) {
boolean hasMatchingExtension = m.mapFileName(file) != null; //use mapFileName as a check to validate if the source file extension is recognized by the mapper or not
if(hasMatchingExtension) {
newFiles.add(new File(srcDir, file));
}
}
return newFiles;
}
/**
* Gets the list of files to be compiled.
*
* @return the list of files
*/
public List getFileList() {
return compileList;
}
/**
* Executes the task.
*
* @throws BuildException if an error occurs
*/
public void execute() throws BuildException {
log("srcdir=" + getSrcdir(), Project.MSG_DEBUG);
log("destdir=" + getDestdir(), Project.MSG_DEBUG);
log("failOnError=" + getFailOnError(), Project.MSG_DEBUG);
log("checkedArithmetic=" + isCheckedArithmetic(), Project.MSG_DEBUG);
log("_compileClasspath=" + _compileClasspath, Project.MSG_DEBUG);
if(isCheckedArithmetic()) {
System.setProperty("checkedArithmetic", "true");
}
ICompilerDriver driver = new SoutCompilerDriver();
IGosuCompiler gosuc = new gw.lang.gosuc.simple.GosuCompiler();
List classpath = new ArrayList<>();
classpath.addAll(Arrays.asList(_compileClasspath.list()));
classpath.addAll(getJreJars());
log("Initializing Gosu compiler...", Project.MSG_INFO);
log("\tsourceFolders:" + Arrays.asList(getSrcdir().list()), Project.MSG_DEBUG);
log("\tclasspath:" + classpath, Project.MSG_DEBUG);
log("\toutputPath:" + getDestdir().getAbsolutePath(), Project.MSG_DEBUG);
String[] list = getSrcdir().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);
}
gosuc.initializeGosu(Arrays.asList(getSrcdir().list()), classpath, getDestdir().getAbsolutePath());
log("About to compile these files:", Project.MSG_DEBUG);
for(File file : compileList) {
log("\t" + file.getAbsolutePath() , Project.MSG_DEBUG);
}
for(File file : compileList) {
try {
gosuc.compile(file, driver);
} catch (Exception e) {
log(e.getMessage(), Project.MSG_ERR);
throw new BuildException(e);
}
}
gosuc.unitializeGosu();
List warnings = ((SoutCompilerDriver) driver).getWarnings();
boolean errorsInCompilation = ((SoutCompilerDriver) driver).hasErrors();
List errors = ((SoutCompilerDriver) driver).getErrors();
List warningMessages = new ArrayList<>();
List errorMessages = new ArrayList<>();
warnings.forEach(warning -> warningMessages.add("[WARNING] " + warning));
int numWarnings = warningMessages.size();
int numErrors = 0;
if(errorsInCompilation) {
errors.forEach(error -> errorMessages.add("[ERROR] " + error));
numErrors = errorMessages.size();
}
boolean hasWarningsOrErrors = numWarnings > 0 || errorsInCompilation;
StringBuilder sb;
sb = new StringBuilder();
sb.append("Gosu compilation completed");
if(hasWarningsOrErrors) {
sb.append(" with ");
if(numWarnings > 0) {
sb.append(numWarnings).append(" warning").append(numWarnings == 1 ? "" : 's');
}
if(errorsInCompilation) {
sb.append(numWarnings > 0 ? " and " : "");
sb.append(numErrors).append(" error").append(numErrors == 1 ? "" : 's');
}
} else {
sb.append(" successfully.");
}
sb.append(hasWarningsOrErrors ? ':' : "");
log(sb.toString(), hasWarningsOrErrors ? Project.MSG_WARN : Project.MSG_INFO);
warningMessages.forEach(this::log);
errorMessages.forEach(this::log);
if(errorsInCompilation) {
if(getFailOnError()) {
buildError("Gosu compilation failed with errors; see compiler output for details.");
} else {
log("Gosu Compiler: Ignoring compilation failure(s) as 'failOnError' was set to false", Project.MSG_WARN);
}
}
}
/**
* Get all JARs from the lib directory of the System's java.home property
* @return List of absolute paths to all JRE libraries
*/
private List getJreJars() {
String javaHome = System.getProperty("java.home");
java.nio.file.Path libsDir = FileSystems.getDefault().getPath(javaHome, "/lib");
try {
return Files.walk(libsDir)
.filter( path -> path.toFile().isFile())
.filter( path -> path.toString().endsWith(".jar"))
.map( java.nio.file.Path::toString )
.collect(Collectors.toList());
} catch (SecurityException | IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy