001/*
002 * Copyright (c) 2012-2021 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others
003 *
004 * This program and the accompanying materials are made available under the
005 * terms of the Eclipse Public License 2.0 which is available at
006 * http://www.eclipse.org/legal/epl-2.0.
007 *
008 * SPDX-License-Identifier: EPL-2.0
009 */
010
011package org.eclipse.golo.cli.command;
012
013import com.beust.jcommander.Parameter;
014import com.beust.jcommander.Parameters;
015import com.beust.jcommander.ParametersDelegate;
016import com.beust.jcommander.converters.FileConverter;
017
018import org.eclipse.golo.cli.GoloFilesManager;
019import org.eclipse.golo.cli.command.spi.CliCommand;
020import org.eclipse.golo.compiler.GoloClassLoader;
021import org.eclipse.golo.compiler.GoloCompiler;
022
023import java.io.File;
024import java.util.Collection;
025import java.util.LinkedList;
026import java.util.List;
027import java.util.Objects;
028
029import static gololang.Messages.*;
030
031@Parameters(commandNames = "golo", resourceBundle = "commands", commandDescriptionKey = "golo")
032public final class GoloGoloCommand implements CliCommand {
033
034  @Parameter(names = "--files", variableArity = true, descriptionKey = "golo.files", required = true, converter = FileConverter.class)
035  List<File> files = new LinkedList<>();
036
037  @Parameter(names = "--module", descriptionKey = "main_module")
038  String module;
039
040  @Parameter(names = "--args", variableArity = true, descriptionKey = "arguments")
041  List<String> arguments = new LinkedList<>();
042
043  @ParametersDelegate
044  ClasspathOption classpath = new ClasspathOption();
045
046  @Parameter(names = "--verbose", descriptionKey = "verbose")
047  boolean verbose = false;
048
049  @Override
050  public boolean verbose() {
051    return this.verbose;
052  }
053
054  @Override
055  public void execute() throws Throwable {
056    GoloClassLoader loader = classpath.initGoloClassLoader();
057    GoloCompiler compiler = loader.getCompiler();
058    Class<?> lastClass = GoloFilesManager.goloFiles(this.files)
059      .filter(this::canRead)
060      .map(wrappedTreatment(compiler::parse))
061      .map(wrappedTreatment(compiler::transform))
062      .sorted(CliCommand.MODULE_COMPARATOR)
063      .map(wrappedTreatment(compiler::expand))
064      .map(wrappedTreatment(compiler::refine))
065      .map(wrappedTreatment(compiler::generate))
066      .filter(Objects::nonNull)
067      .flatMap(Collection::stream)
068      .map(displayInfo("Loading %s"))
069      .map(loader::load)
070      .reduce(null, this::selectMainModule);
071
072    if (lastClass == null && this.module != null) {
073      error(message("module_not_found", this.module));
074      return;
075    }
076    if (lastClass == null) {
077      return;
078    }
079    try {
080      callRun(lastClass, this.arguments.toArray(new String[this.arguments.size()]));
081    } catch (NoMainMethodException e) {
082      error(message("module_no_main", lastClass.getName()));
083    }
084  }
085
086  private Class<?> selectMainModule(Class<?> old, Class<?> loaded) {
087    if (this.module == null || this.module.equals(loaded.getCanonicalName())) {
088      return loaded;
089    }
090    return old;
091  }
092}