001/*
002 * Copyright (c) 2012-2018 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.IParameterValidator;
014import com.beust.jcommander.Parameter;
015import com.beust.jcommander.ParameterException;
016import com.beust.jcommander.Parameters;
017import com.beust.jcommander.ParametersDelegate;
018import org.eclipse.golo.cli.command.spi.CliCommand;
019import org.eclipse.golo.compiler.GoloCompiler;
020import org.eclipse.golo.compiler.GoloCompilationException;
021import org.eclipse.golo.doc.AbstractProcessor;
022import org.eclipse.golo.doc.CtagsProcessor;
023import org.eclipse.golo.doc.HtmlProcessor;
024import org.eclipse.golo.doc.MarkdownProcessor;
025import org.eclipse.golo.doc.ModuleDocumentation;
026
027import java.io.File;
028import java.io.IOException;
029import java.nio.file.Paths;
030import java.util.function.Supplier;
031import java.util.*;
032
033import static gololang.Messages.*;
034
035@Parameters(commandNames = {"doc"}, commandDescriptionKey = "doc", resourceBundle = "commands")
036public class DocCommand implements CliCommand {
037
038  @Parameter(names = "--format", descriptionKey = "doc.format", validateWith = DocFormatValidator.class)
039  String format = "html";
040
041  @Parameter(names = "--output", descriptionKey = "doc.output")
042  String output = ".";
043
044  @Parameter(descriptionKey = "source_files")
045  List<String> sources = new LinkedList<>();
046
047  @ParametersDelegate
048  ClasspathOption classpath = new ClasspathOption();
049
050  private static final Map<String, Supplier<? extends AbstractProcessor>> FORMATS = new HashMap<>();
051  static {
052    FORMATS.put("markdown", MarkdownProcessor::new);
053    FORMATS.put("html", HtmlProcessor::new);
054    FORMATS.put("ctags", CtagsProcessor::new);
055  }
056
057  private GoloCompiler compiler;
058
059  @Override
060  public void execute() throws Throwable {
061    compiler = classpath.initGoloClassLoader().getCompiler();
062    AbstractProcessor processor = FORMATS.get(this.format).get();
063    HashSet<ModuleDocumentation> modules = new HashSet<>();
064    for (String source : this.sources) {
065      loadGoloFile(source, modules);
066    }
067    try {
068      processor.process(modules, Paths.get(this.output));
069    } catch (Throwable throwable) {
070      handleThrowable(throwable);
071    }
072  }
073
074  private void loadGoloFile(String goloFile, HashSet<ModuleDocumentation> modules) {
075    File file = new File(goloFile);
076    if (file.isDirectory()) {
077      File[] directoryFiles = file.listFiles();
078      if (directoryFiles != null) {
079        for (File directoryFile : directoryFiles) {
080          loadGoloFile(directoryFile.getAbsolutePath(), modules);
081        }
082      }
083    } else if (file.getName().endsWith(".golo")) {
084      try {
085        modules.add(ModuleDocumentation.load(goloFile, compiler));
086      } catch (IOException e) {
087        error(message("file_not_found", goloFile));
088        return;
089      } catch (GoloCompilationException e) {
090        handleCompilationException(e);
091      } catch (Throwable t) {
092        handleThrowable(t);
093      }
094    }
095  }
096
097  public static class DocFormatValidator implements IParameterValidator {
098
099    @Override
100    public void validate(String name, String value) throws ParameterException {
101      if (!FORMATS.keySet().contains(value)) {
102        throw new ParameterException(message("format_error", FORMATS.keySet()));
103      }
104    }
105  }
106}