package driver;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import files.Require;
import source.Source;
import source.SourceFileText;
import compiler.Macro;
import files.RootedSourcePath;
/**
* Represents a source file. Either a macro file (.javam) or a regular source
* file (.java).
*
* Each instance uniquely represents file. Instances should be obtained trough
* the {@link SourceRepository} instance held in {@link Context#repo()}.
*/
public class SourceFile
{
/****************************************************************************/
public static final String MACRO_EXT = "javam";
/****************************************************************************/
private static final LinkedHashMap<String, Macro> EMPTY_MAP
= new LinkedHashMap<>();
/****************************************************************************/
private final RootedSourcePath path;
/****************************************************************************/
private final SourceParseManager parser;
/****************************************************************************/
private final Requires requires;
/*****************************************************************************
* Holds the macros and preserve the order in which they were inserted.
*/
private final LinkedHashMap<String, Macro> macros;
/****************************************************************************/
private final Source source;
/****************************************************************************/
private final List<String> imports = new ArrayList<>();
/****************************************************************************/
private boolean isCompileTimeDependency = false;
/****************************************************************************/
SourceFile(RootedSourcePath path)
{
try {
this.source = new SourceFileText(path.absolutePath().toFile());
}
catch (IOException e) {
throw new Error(e);
}
this.path = path;
this.parser = new SourceParseManager(this);
this.requires = new Requires();
this.macros = isMacro() ? new LinkedHashMap<String, Macro>() : EMPTY_MAP;
List<Require> requiresl = new ArrayList<>();
parser.parseRequires(requiresl, imports);
// This will recursively create required SourceFile that don't exist yet.
requires.addAll(requiresl);
imports.addAll(requires.imports());
}
/****************************************************************************/
public RootedSourcePath path()
{
return path;
}
/****************************************************************************/
public SourceParseManager parser()
{
return parser;
}
/****************************************************************************/
public Requires requires()
{
return requires;
}
/****************************************************************************/
public Source source()
{
return source;
}
/****************************************************************************/
public boolean isCompileTimeDependency()
{
return isCompileTimeDependency;
}
/****************************************************************************/
public void declareUsedAtCompileTime()
{
isCompileTimeDependency = true;
}
/*****************************************************************************
* Returns a list of import statement for the file under string form.
*/
public List<String> imports()
{
return imports;
}
/****************************************************************************/
public boolean isMacro()
{
return path.fileExt().equals(MACRO_EXT);
}
/****************************************************************************/
public void addMacro(Macro macro)
{
if (macros.put(macro.rule.name, macro) != null)
{
throw new Error("Duplicate macro name \"" + macro.rule.name
+ "\" in file:" + this);
}
}
/****************************************************************************/
public void enableMacro(String macroName)
{
xxableMacro(macroName, true);
}
/****************************************************************************/
public void disableMacro(String macroName)
{
xxableMacro(macroName, false);
}
/****************************************************************************/
public void xxableMacro(String macroName, boolean enable)
{
if (macroName.equals("*")) {
for (Macro macro : macros.values()) {
xxableMacro(macro, enable);
}
}
else {
Macro macro = macros.get(macroName);
if (macro == null) {
throw new Error("Requested macro cannot be found: \"" + macroName
+ "\" in file: " + this);
}
xxableMacro(macro, enable);
}
}
/****************************************************************************/
private void xxableMacro(Macro macro, boolean enable)
{
if (enable) {
macro.enable();
}
else {
macro.disable();
}
}
/****************************************************************************/
public void disableMacros()
{
for (Macro macro : macros.values()) {
macro.disable();
}
}
/*****************************************************************************
* Return the macro defined in this file, iterable in the order they were
* defined.
*/
public Collection<Macro> macros()
{
return macros.values();
}
/****************************************************************************/
@Override public String toString()
{
return path.toString();
}
}