// 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.lib.analysis;

import com.google.common.base.CharMatcher;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.Label.PackageContext;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Helper class encapsulating string scanning state used during "heuristic" expansion of labels
 * embedded within rules.
 */
public final class LabelExpander {
  /**
   * An exception that is thrown when a label is expanded to zero or multiple files during
   * expansion.
   */
  public static class NotUniqueExpansionException extends Exception {
    public NotUniqueExpansionException(int sizeOfResultSet, String labelText) {
      super(
          "heuristic label expansion found '"
              + labelText
              + "', which expands to "
              + sizeOfResultSet
              + " files"
              + (sizeOfResultSet > 1 ? ", please use $(locations " + labelText + ") instead" : ""));
    }
  }

  // This is a utility class, no need to instantiate.
  private LabelExpander() {}

  /**
   * CharMatcher to determine if a given character is valid for labels.
   *
   * <p>The Build Concept Reference additionally allows '=' and ',' to appear in labels, but for the
   * purposes of the heuristic, this function does not, as it would cause "--foo=:rule1,:rule2" to
   * scan as a single possible label, instead of three ("--foo", ":rule1", ":rule2").
   */
  private static final CharMatcher LABEL_CHAR_MATCHER =
      CharMatcher.inRange('a', 'z')
          .or(CharMatcher.inRange('A', 'Z'))
          .or(CharMatcher.inRange('0', '9'))
          .or(CharMatcher.anyOf(":/_.-+" + PathFragment.SEPARATOR_CHAR))
          .precomputed();

  /**
   * Expands all references to labels embedded within a string using the provided expansion mapping
   * from labels to artifacts.
   *
   * <p>Since this pass is heuristic, references to non-existent labels (such as arbitrary words) or
   * invalid labels are simply ignored and are unchanged in the output. However, if the heuristic
   * discovers a label, which identifies an existing target producing zero or multiple files, an
   * error is reported.
   *
   * @param expression the expression to expand.
   * @param labelMap the mapping from labels to artifacts, whose relative path is to be used as the
   *     expansion.
   * @param labelResolver the {@code Label} that can resolve label strings to {@code Label} objects.
   *     The resolved label is either relative to {@code labelResolver} or is a global label (i.e.
   *     starts with "//").
   * @return the expansion of the string.
   * @throws NotUniqueExpansionException if a label that is present in the mapping expands to zero
   *     or multiple files.
   */
  public static <T extends Iterable<Artifact>> String expand(
      @Nullable String expression, Map<Label, T> labelMap, Label labelResolver)
      throws NotUniqueExpansionException {
    if (Strings.isNullOrEmpty(expression)) {
      return "";
    }
    Preconditions.checkNotNull(labelMap);
    Preconditions.checkNotNull(labelResolver);

    int offset = 0;
    StringBuilder result = new StringBuilder();
    while (offset < expression.length()) {
      String labelText = scanLabel(expression, offset);
      if (labelText != null) {
        offset += labelText.length();
        result.append(tryResolvingLabelTextToArtifactPath(labelText, labelMap, labelResolver));
      } else {
        result.append(expression.charAt(offset));
        offset++;
      }
    }
    return result.toString();
  }

  /**
   * Tries resolving a label text to a full label for the associated {@code Artifact}, using the
   * provided mapping.
   *
   * <p>The method succeeds if the label text can be resolved to a {@code Label} object, which is
   * present in the {@code labelMap} and maps to exactly one {@code Artifact}.
   *
   * @param labelText the text to resolve.
   * @param labelMap the mapping from labels to artifacts, whose relative path is to be used as the
   *     expansion.
   * @param labelResolver the {@code Label} that can resolve label strings to {@code Label} objects.
   *     The resolved label is either relative to {@code labelResolver} or is a global label (i.e.
   *     starts with "//").
   * @return an absolute label to an {@code Artifact} if the resolving was successful or the
   *     original label text.
   * @throws NotUniqueExpansionException if a label that is present in the mapping expands to zero
   *     or multiple files.
   */
  private static <T extends Iterable<Artifact>> String tryResolvingLabelTextToArtifactPath(
      String labelText, Map<Label, T> labelMap, Label labelResolver)
      throws NotUniqueExpansionException {
    Label resolvedLabel = resolveLabelText(labelText, labelResolver);
    if (resolvedLabel != null) {
      Iterable<Artifact> artifacts = labelMap.get(resolvedLabel);
      if (artifacts != null) { // resolvedLabel identifies an existing target
        List<String> locations = new ArrayList<>();
        Artifact.addExecPaths(artifacts, locations);
        int resultSetSize = locations.size();
        if (resultSetSize == 1) {
          return Iterables.getOnlyElement(locations); // success!
        } else {
          throw new NotUniqueExpansionException(resultSetSize, labelText);
        }
      }
    }
    return labelText;
  }

  /**
   * Resolves a string to a label text. Uses {@code labelResolver} to do so. The result is either
   * relative to {@code labelResolver} or is an absolute label. In case of an invalid label text,
   * the return value is null.
   */
  @Nullable
  private static Label resolveLabelText(String labelText, Label labelResolver) {
    try {
      return Label.parseWithPackageContext(
          labelText,
          PackageContext.of(
              labelResolver.getPackageIdentifier(), RepositoryMapping.ALWAYS_FALLBACK));
    } catch (LabelSyntaxException e) {
      // It's a heuristic, so quietly ignore "errors".
      return null;
    }
  }

  /**
   * Scans the argument string from a given start position until the name of a potential label has
   * been consumed, then returns the label text. If the expression contains no possible label
   * starting at the start position, the return value is null.
   */
  @Nullable
  private static String scanLabel(String expression, int start) {
    int offset = start;
    while (offset < expression.length() && LABEL_CHAR_MATCHER.matches(expression.charAt(offset))) {
      ++offset;
    }
    if (offset > start) {
      return expression.substring(start, offset);
    } else {
      return null;
    }
  }
}
