// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.docgen;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Ascii;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.docgen.DocgenConsts.RuleType;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.AttributeInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.ModuleInfo;
import com.google.devtools.build.skydoc.rendering.proto.StardocOutputProtos.RuleInfo;
import com.google.protobuf.ExtensionRegistry;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;

/**
 * Class that parses the documentation fragments of rule-classes and
 * generates the html format documentation.
 */
@VisibleForTesting
public class BuildDocCollector {
  private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

  private static final Splitter SHARP_SPLITTER = Splitter.on('#').limit(2).trimResults();

  private final RuleLinkExpander linkExpander;
  private final SourceUrlMapper urlMapper;
  private final ConfiguredRuleClassProvider ruleClassProvider;

  public BuildDocCollector(
      RuleLinkExpander linkExpander,
      SourceUrlMapper urlMapper,
      ConfiguredRuleClassProvider ruleClassProvider) {
    this.linkExpander = linkExpander;
    this.urlMapper = urlMapper;
    this.ruleClassProvider = ruleClassProvider;
  }

  /**
   * Parse the file containing rules blocked from documentation. The list is simply a list of rules
   * separated by new lines. Line comments can be added to the file by starting them with #.
   *
   * @param denyList The name of the file containing the denylist.
   * @return The set of denylisted rules.
   * @throws IOException
   */
  @VisibleForTesting
  public static Set<String> readDenyList(String denyList) throws IOException {
    Set<String> result = new HashSet<String>();
    if (denyList != null && !denyList.isEmpty()) {
      File file = new File(denyList);
      try (BufferedReader reader = Files.newBufferedReader(file.toPath(), UTF_8)) {
        for (String line = reader.readLine(); line != null; line = reader.readLine()) {
          String rule = SHARP_SPLITTER.split(line).iterator().next();
          if (!rule.isEmpty()) {
            result.add(rule);
          }
        }
      }
    }
    return result;
  }

  /**
   * Creates a map of rule names (keys) to rule documentation (values).
   *
   * <p>This method crawls the specified input directories for rule class definitions (as Java
   * source files) which contain the rules' and attributes' definitions as comments in a specific
   * format. The keys in the returned Map correspond to these rule classes.
   *
   * <p>In the Map's values, all references pointing to other rules, rule attributes, and general
   * documentation (e.g. common definitions, make variables, etc.) are expanded into hyperlinks. The
   * links generated follow either the multi-page or single-page Build Encyclopedia model depending
   * on the mode set for the {@link RuleLinkExpander} that was passed to the constructor.
   *
   * @param inputJavaDirs list of directories to scan for documentation in Java source code
   * @param inputStardocProtos list of file paths of stardoc_output.ModuleInfo binary proto files
   *     generated from Build Encyclopedia entry point .bzl files; documentation from these protos
   *     takes precedence over documentation from {@code inputJavaDirs}
   * @param denyList specify an optional denylist file that list some rules that should not be
   *     listed in the output.
   * @throws BuildEncyclopediaDocException
   * @throws IOException
   * @return Map of rule class to rule documentation.
   */
  public Map<String, RuleDocumentation> collect(
      List<String> inputJavaDirs, List<String> inputStardocProtos, String denyList)
      throws BuildEncyclopediaDocException, IOException {
    // Read the denyList file
    Set<String> denylistedRules = readDenyList(denyList);
    // RuleDocumentations are generated in order (based on rule type then alphabetically).
    // The ordering is also used to determine in which rule doc the common attribute docs are
    // generated (they are generated at the first appearance).
    Map<String, RuleDocumentation> ruleDocEntries = new TreeMap<>();
    // RuleDocumentationAttribute objects equal based on attributeName so they have to be
    // collected in a List instead of a Set.
    ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries =
        LinkedListMultimap.create();

    // Map of rule name to the file (Java source file or Build Encyclopedia entry point .bzl file)
    // and symbol from which its documentation was obtained.
    Map<String, DocumentationOrigin> ruleDocOrigin = new HashMap<>();

    // Set of files already processed. The same file may be encountered multiple times because
    // directories are processed recursively, and an input directory may be a subdirectory of
    // another one.
    Set<File> processedFiles = new HashSet<>();

    for (String inputJavaDir : inputJavaDirs) {
      logger.atFine().log("Processing input directory: %s", inputJavaDir);
      int ruleNum = ruleDocEntries.size();
      collectJavaSourceDocs(
          processedFiles,
          ruleDocOrigin,
          ruleDocEntries,
          denylistedRules,
          attributeDocEntries,
          new File(inputJavaDir));
      logger.atFine().log(
          "%d rule documentations found in %s", ruleDocEntries.size() - ruleNum, inputJavaDir);
    }
    processJavaSourceRuleAttributeDocs(ruleDocEntries.values(), attributeDocEntries);

    for (String stardocProtoPath : inputStardocProtos) {
      logger.atFine().log("Processing input file: %s", stardocProtoPath);
      int numRulesCollected =
          collectModuleInfoDocs(
              ruleDocOrigin,
              ruleDocEntries,
              denylistedRules,
              attributeDocEntries,
              ModuleInfo.parseFrom(
                  new FileInputStream(stardocProtoPath), ExtensionRegistry.getEmptyRegistry()),
              urlMapper);
      logger.atFine().log(
          "%d rule documentations found in %s", numRulesCollected, stardocProtoPath);
    }

    linkExpander.addIndex(buildRuleIndex(ruleDocEntries.values()));
    for (RuleDocumentation rule : ruleDocEntries.values()) {
      rule.setRuleLinkExpander(linkExpander);
    }
    return ruleDocEntries;
  }

  /**
   * Generates an index mapping rule name to its normalized rule family name.
   */
  private Map<String, String> buildRuleIndex(Iterable<RuleDocumentation> rules) {
    Map<String, String> index = new HashMap<>();
    for (RuleDocumentation rule : rules) {
      index.put(rule.getRuleName(), RuleFamily.normalize(rule.getRuleFamily()));
    }
    return index;
  }

  /**
   * Go through all attributes of native rules whose documentation was retrieved from Java sources,
   * and search the best attribute documentation if exists. The best documentation is the closest
   * documentation in the ancestor graph. E.g. if java_library.deps documented in $rule and
   * $java_rule then the one in $java_rule is going to apply since it's a closer ancestor of
   * java_library.
   *
   * <p>Note: this function should be called before any calls to collectModuleInfoDocs.
   */
  private void processJavaSourceRuleAttributeDocs(
      Iterable<RuleDocumentation> ruleDocEntries,
      ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries)
      throws BuildEncyclopediaDocException {
    for (RuleDocumentation ruleDoc : ruleDocEntries) {
      RuleClass ruleClass = ruleClassProvider.getRuleClassMap().get(ruleDoc.getRuleName());
      if (ruleClass != null) {
        if (ruleClass.isDocumented()) {
          Class<? extends RuleDefinition> ruleDefinition =
              ruleClassProvider.getRuleClassDefinition(ruleDoc.getRuleName()).getClass();
          for (Attribute attribute : ruleClass.getAttributes()) {
            if (!attribute.isDocumented()) {
              continue;
            }
            String attrName = attribute.getName();
            List<RuleDocumentationAttribute> attributeDocList =
                attributeDocEntries.get(attrName);
            if (attributeDocList != null) {
              // There are attribute docs for this attribute.
              // Search the closest one in the ancestor graph.
              // Note that there can be only one 'closest' attribute since we forbid multiple
              // inheritance of the same attribute in RuleClass.
              int minLevel = Integer.MAX_VALUE;
              RuleDocumentationAttribute bestAttributeDoc = null;
              for (RuleDocumentationAttribute attributeDoc : attributeDocList) {
                int level = attributeDoc.getDefinitionClassAncestryLevel(
                    ruleDefinition,
                    ruleClassProvider);
                if (level >= 0 && level < minLevel) {
                  bestAttributeDoc = attributeDoc;
                  minLevel = level;
                }
              }
              if (bestAttributeDoc != null) {
                // We have to copy the matching RuleDocumentationAttribute here so that we don't
                // overwrite the reference to the actual attribute later by another attribute with
                // the same ancestor but different default values.
                ruleDoc.addAttribute(bestAttributeDoc.copyAndUpdateFrom(attribute));
              // If there is no matching attribute doc try to add the common.
              } else if (ruleDoc.getRuleType().equals(RuleType.BINARY)
                  && PredefinedAttributes.BINARY_ATTRIBUTES.containsKey(attrName)) {
                ruleDoc.addAttribute(PredefinedAttributes.BINARY_ATTRIBUTES.get(attrName));
              } else if (ruleDoc.getRuleType().equals(RuleType.TEST)
                  && PredefinedAttributes.TEST_ATTRIBUTES.containsKey(attrName)) {
                ruleDoc.addAttribute(PredefinedAttributes.TEST_ATTRIBUTES.get(attrName));
              } else if (PredefinedAttributes.COMMON_ATTRIBUTES.containsKey(attrName)) {
                ruleDoc.addAttribute(PredefinedAttributes.COMMON_ATTRIBUTES.get(attrName));
              } else if (PredefinedAttributes.TYPICAL_ATTRIBUTES.containsKey(attrName)) {
                ruleDoc.addAttribute(PredefinedAttributes.TYPICAL_ATTRIBUTES.get(attrName));
              }
            }
          }
        }
      } else {
        throw ruleDoc.createException("Can't find RuleClass for " + ruleDoc.getRuleName());
      }
    }
  }

  /**
   * Crawls the specified inputPath and collects the raw rule and rule attribute documentation.
   *
   * <p>This method crawls the specified input directory (recursively calling itself for all
   * subdirectories) and reads each Java source file using {@link SourceFileReader} to extract the
   * raw rule and attribute documentation embedded in comments in a specific format. The extracted
   * documentation is then further processed, such as by {@link
   * BuildDocCollector#collect(List<String>, String, RuleLinkExpander), collect}, in order to
   * associate each rule's documentation with its attribute documentation.
   *
   * <p>This method returns the following through its parameters: the set of Java source files
   * processed, a map of rule name to the source file it was extracted from, a map of rule name to
   * the documentation to the rule, and a multimap of attribute name to attribute documentation.
   *
   * @param processedFiles The set of Java source files files that have already been processed in
   *     order to avoid reprocessing the same file.
   * @param ruleDocOrigin Map of rule name to the file and symbol from which its documentation was
   *     obtained.
   * @param ruleDocEntries Map of rule name to rule documentation.
   * @param denyList The set of denylisted rules whose documentation should not be extracted.
   * @param attributeDocEntries Multimap of rule attribute name to attribute documentation.
   * @param inputPath The File representing the Java source file or directory to read.
   * @throws BuildEncyclopediaDocException
   * @throws IOException
   */
  public void collectJavaSourceDocs(
      Set<File> processedFiles,
      Map<String, DocumentationOrigin> ruleDocOrigin,
      Map<String, RuleDocumentation> ruleDocEntries,
      Set<String> denyList,
      ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries,
      File inputPath)
      throws BuildEncyclopediaDocException, IOException {
    if (processedFiles.contains(inputPath)) {
      return;
    }

    if (inputPath.isFile()) {
      if (DocgenConsts.JAVA_SOURCE_FILE_SUFFIX.apply(inputPath.getName())) {
        SourceFileReader sfr =
            new SourceFileReader(
                ruleClassProvider, inputPath.getAbsolutePath(), urlMapper.urlOfFile(inputPath));
        sfr.readDocsFromComments();
        for (RuleDocumentation d : sfr.getRuleDocEntries()) {
          String ruleName = d.getRuleName();
          if (!denyList.contains(ruleName)) {
            if (ruleDocEntries.containsKey(ruleName)
                && !ruleDocOrigin.get(ruleName).file().equals(inputPath.toString())) {
              logger.atWarning().log(
                  "Rule '%s' from '%s' overrides previously seen rule '%s' from '%s'",
                  ruleName,
                  inputPath,
                  ruleDocOrigin.get(ruleName).symbol(),
                  ruleDocOrigin.get(ruleName).file());
            }
            ruleDocOrigin.put(ruleName, DocumentationOrigin.create(inputPath.toString(), ruleName));
            ruleDocEntries.put(ruleName, d);
          }
        }
        if (attributeDocEntries != null) {
          // Collect all attribute documentations from this file.
          attributeDocEntries.putAll(sfr.getAttributeDocEntries());
        }
      }
    } else if (inputPath.isDirectory()) {
      for (File childPath : inputPath.listFiles()) {
        collectJavaSourceDocs(
            processedFiles,
            ruleDocOrigin,
            ruleDocEntries,
            denyList,
            attributeDocEntries,
            childPath);
      }
    }

    processedFiles.add(inputPath);
  }

  /**
   * Collects rule and rule attribute documentation from a stardoc_output.ModuleInfo message
   * generated from a Build Encyclopedia entry point .bzl file.
   *
   * <p>The module doc string for the .bzl file is interpreted as the rule family name.
   *
   * <p>Any rule exported by the .bzl file is expected to be contained in a struct whose name is a
   * {@link DocgenConsts.RuleType} name suffixed with "_rules" - for example, "binary_rules",
   * "library_rules", etc.
   *
   * <p>This method returns the following through its parameters: a map of rule name to the file and
   * symbol it was extracted from, a map of rule name to the documentation of the rule, and a
   * multimap of attribute name to attribute documentation.
   *
   * @param ruleDocOrigin Map of rule name to the file and symbol from which its documentation was
   *     obtained.
   * @param ruleDocEntries Map of rule name to rule documentation.
   * @param denyList The set of denylisted rules whose documentation should not be extracted.
   * @param attributeDocEntries Multimap of rule attribute name to attribute documentation.
   * @param moduleInfo A stardoc_output.ModuleInfo message representing a Build Encyclopedia entry
   *     point .bzl file.
   * @param urlMapper Mapper from source labels to source code repository URLs
   * @return number of rules whose documentation was collected
   */
  @VisibleForTesting
  static int collectModuleInfoDocs(
      Map<String, DocumentationOrigin> ruleDocOrigin,
      Map<String, RuleDocumentation> ruleDocEntries,
      Set<String> denyList,
      ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries,
      ModuleInfo moduleInfo,
      SourceUrlMapper urlMapper)
      throws BuildEncyclopediaDocException {
    String entryPointFileLabel = moduleInfo.getFile();

    Matcher familyMatcher =
        DocgenConsts.STARDOC_OUTPUT_FAMILY_NAME_AND_SUMMARY.matcher(
            moduleInfo.getModuleDocstring().strip());
    if (!familyMatcher.matches()) {
      throw new BuildEncyclopediaDocException(
          entryPointFileLabel,
          "Module doc string is expected to be a single line representing a rule family name, "
              + "optionally followed by a blank line and summary text; for example, "
              + "`\"\"\"C / C++\"\"\"`");
    }
    String ruleFamily = familyMatcher.group("family");
    String ruleFamilySummary = Strings.nullToEmpty(familyMatcher.group("summary"));

    int numRulesCollected = 0;
    for (RuleInfo ruleInfo : moduleInfo.getRuleInfoList()) {
      Matcher ruleNameMatcher =
          DocgenConsts.STARDOC_OUTPUT_RULE_NAME.matcher(ruleInfo.getRuleName());
      if (!ruleNameMatcher.matches()) {
        throw new BuildEncyclopediaDocException(
            entryPointFileLabel,
            String.format(
                "Unexpected rule symbol: %s; rules must be exported in structs, with the struct's"
                    + " name specifying the rule type, for example, `library_rules = struct("
                    + "java_import = _java_import, ...)`",
                ruleInfo.getRuleName()));
      }
      String ruleType = Ascii.toUpperCase(ruleNameMatcher.group("type"));
      String ruleName = ruleNameMatcher.group("name");
      if (!denyList.contains(ruleName)) {
        String ruleOriginFileLabel = ruleInfo.getOriginKey().getFile();
        if (ruleDocEntries.containsKey(ruleName)) {
          logger.atWarning().log(
              "Rule '%s' from '%s' (defined in '%s') overrides previously seen rule '%s' from '%s'",
              ruleInfo.getRuleName(),
              entryPointFileLabel,
              ruleOriginFileLabel,
              ruleDocOrigin.get(ruleName).symbol(),
              ruleDocOrigin.get(ruleName).file());
        }
        ImmutableSet.Builder<String> flags = ImmutableSet.builder();
        if (ruleType.equals(DocgenConsts.STARLARK_GENERIC_RULE_TYPE)) {
          // Note that if FLAG_GENERIC_RULE is set, RuleDocumentation constructor will set the rule
          // type to OTHER.
          flags.add(DocgenConsts.FLAG_GENERIC_RULE);
        }
        RuleDocumentation ruleDoc =
            new RuleDocumentation(
                ruleName,
                ruleType,
                ruleFamily,
                ruleInfo.getDocString(),
                ruleOriginFileLabel,
                urlMapper.urlOfLabel(ruleOriginFileLabel),
                flags.build(),
                // Add family summary only to the first rule encountered, to avoid duplication in
                // final rendered output
                numRulesCollected == 0 ? ruleFamilySummary : "");

        // Inject standard inherited attributes for Starlark rules (since they always inherit from
        // one of 3 possible base rule classes; see StarlarkRuleClassFunctions#createRule). If in
        // the future we want to document native rules via ModuleInfo protos, we will need to list
        // inherited attributes in the proto.
        ruleDoc.addAttributes(PredefinedAttributes.COMMON_ATTRIBUTES.values());
        if (ruleDoc.getRuleType().equals(RuleType.TEST)) {
          ruleDoc.addAttributes(PredefinedAttributes.TEST_ATTRIBUTES.values());
        } else if (ruleDoc.getRuleType().equals(RuleType.BINARY)) {
          ruleDoc.addAttributes(PredefinedAttributes.BINARY_ATTRIBUTES.values());
        }

        for (AttributeInfo attributeInfo : ruleInfo.getAttributeList()) {
          String attributeName = attributeInfo.getName();
          if (attributeName.equals("name")) {
            // We do not want the implicit "name" attribute injected into proto output by
            // starlark_doc_extract because we inject "name" at the template level in
            // templates/be/rules.vm
            continue;
          }
          if (attributeInfo.getDocString().isEmpty()
              && PredefinedAttributes.TYPICAL_ATTRIBUTES.containsKey(attributeName)) {
            // We link empty-docstring attributes to the common table based purely on attribute name
            // (same as processJavaSourceRuleAttributeDocs does for native rule attributes).
            // TODO(arostovtsev): should we verify attribute type and default value too? That would
            // require moving the definition of common attributes from a free-text velocity template
            // to a structured format.
            ruleDoc.addAttribute(PredefinedAttributes.TYPICAL_ATTRIBUTES.get(attributeName));
          } else {
            boolean deprecated =
                DocgenConsts.STARDOC_OUTPUT_DEPRECATED_DOCSTRING
                    .matcher(attributeInfo.getDocString())
                    .find();
            ruleDoc.addAttribute(
                RuleDocumentationAttribute.createFromAttributeInfo(
                    attributeInfo,
                    ruleOriginFileLabel,
                    deprecated
                        ? ImmutableSet.of(DocgenConsts.FLAG_DEPRECATED)
                        : ImmutableSet.of()));
          }
        }

        ruleDocOrigin.put(
            ruleName, DocumentationOrigin.create(entryPointFileLabel, ruleInfo.getRuleName()));
        ruleDocEntries.put(ruleName, ruleDoc);
        numRulesCollected++;
      }
    }
    return numRulesCollected;
  }

  /** The file and symbol from which documentation was obtained. */
  @AutoValue
  abstract static class DocumentationOrigin {
    abstract String file();

    abstract String symbol();

    static DocumentationOrigin create(String file, String symbol) {
      return new AutoValue_BuildDocCollector_DocumentationOrigin(file, symbol);
    }
  }
}
