package org.smoothbuild.parse;
import static org.smoothbuild.parse.DependencyCollector.collectDependencies;
import static org.smoothbuild.parse.DependencySorter.sortDependencies;
import static org.smoothbuild.parse.FunctionsCollector.collectFunctions;
import static org.smoothbuild.parse.ScriptParser.parseScript;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.smoothbuild.antlr.SmoothParser.FunctionContext;
import org.smoothbuild.antlr.SmoothParser.ModuleContext;
import org.smoothbuild.cli.Console;
import org.smoothbuild.io.fs.base.FileSystem;
import org.smoothbuild.io.fs.base.FileSystemException;
import org.smoothbuild.io.fs.base.Path;
import org.smoothbuild.lang.function.Functions;
import org.smoothbuild.lang.function.base.Name;
public class ModuleLoader {
private final FileSystem fileSystem;
private final Functions functions;
private final DefinedFunctionsCreator definedFunctionsCreator;
private final Console console;
@Inject
public ModuleLoader(FileSystem fileSystem, Functions functions,
DefinedFunctionsCreator definedFunctionsCreator, Console console) {
this.fileSystem = fileSystem;
this.functions = functions;
this.definedFunctionsCreator = definedFunctionsCreator;
this.console = console;
}
public void loadFunctions(Path smoothFile) {
loadFunctions(scriptInputStream(smoothFile), smoothFile);
}
private InputStream scriptInputStream(Path scriptFile) {
try {
return fileSystem.openInputStream(scriptFile);
} catch (FileSystemException e) {
console.error("Cannot read build script file " + scriptFile + ". " + e.getMessage());
throw new ParsingException();
}
}
private void loadFunctions(InputStream inputStream, Path scriptFile) {
ModuleContext module = parseScript(console, inputStream, scriptFile);
Map<Name, FunctionContext> functionContexts = collectFunctions(console, functions, module);
Map<Name, Set<Dependency>> dependencies = collectDependencies(module);
detectUndefinedFunctions(console, functions, dependencies);
List<Name> sorted = sortDependencies(functions, dependencies, console);
definedFunctionsCreator.createDefinedFunctions(console, functionContexts, sorted);
}
public static void detectUndefinedFunctions(Console console, Functions functions,
Map<Name, Set<Dependency>> dependencies) {
Set<Name> declaredFunctions = dependencies.keySet();
for (Set<Dependency> functionDependecies : dependencies.values()) {
for (Dependency dependency : functionDependecies) {
Name name = dependency.functionName();
if (!functions.contains(name) && !declaredFunctions.contains(name)) {
console.error(dependency.location(), "Call to unknown function " + name + ".");
}
}
}
if (console.isErrorReported()) {
throw new ParsingException();
}
}
}