// Copyright 2017 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.bazel.rules;

import com.google.devtools.build.lib.analysis.AliasProvider;
import com.google.devtools.build.lib.analysis.AliasProvider.TargetMode;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.PackageGroup;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.RequiredProviders;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.syntax.Type;

/** Ensures that a target's prerequisites are visible to it and match its testonly status. */
public class BazelPrerequisiteValidator
    implements ConfiguredRuleClassProvider.PrerequisiteValidator {

  @Override
  public void validate(
      RuleContext.Builder context, ConfiguredTargetAndData prerequisite, Attribute attribute) {
    validateDirectPrerequisiteVisibility(context, prerequisite, attribute.getName());
    validateDirectPrerequisiteForTestOnly(context, prerequisite);
    ConfiguredRuleClassProvider.DeprecationValidator.validateDirectPrerequisiteForDeprecation(
        context, context.getRule(), prerequisite, context.forAspect());
  }

  private void validateDirectPrerequisiteVisibility(
      RuleContext.Builder context, ConfiguredTargetAndData prerequisite, String attrName) {
    Rule rule = context.getRule();
    Target prerequisiteTarget = prerequisite.getTarget();
    if (!context
            .getRule()
            .getLabel()
            .getPackageIdentifier()
            .equals(
                AliasProvider.getDependencyLabel(prerequisite.getConfiguredTarget())
                    .getPackageIdentifier())
        && !context.isVisible(prerequisite.getConfiguredTarget())) {
      String errorMessage;
      if (!context.getConfiguration().checkVisibility()) {
        errorMessage =
            String.format(
                "Target '%s' violates visibility of "
                    + "%s. Continuing because --nocheck_visibility is active",
                rule.getLabel(), AliasProvider.describeTargetWithAliases(prerequisite,
                    TargetMode.WITHOUT_KIND));
        context.ruleWarning(errorMessage);
      } else {
        // Oddly enough, we use reportError rather than ruleError here.
        errorMessage =
            String.format(
                "%s is not visible from target '%s'. Check "
                    + "the visibility declaration of the former target if you think "
                    + "the dependency is legitimate",
                AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITHOUT_KIND),
                rule.getLabel());
        context.reportError(rule.getLocation(), errorMessage);
      }
      // We can always post the visibility error as, regardless of the value of keep going,
      // that target will not be built.
      context.post(
          new VisibilityErrorEvent(context.getConfiguration(), rule.getLabel(), errorMessage));
    }

    if (prerequisiteTarget instanceof PackageGroup) {
      RequiredProviders requiredProviders =
          RawAttributeMapper.of(rule).getAttributeDefinition(attrName).getRequiredProviders();
      boolean containsPackageSpecificationProvider =
          requiredProviders.getDescription().contains("PackageSpecificationProvider");
      // TODO(plf): Add the PackageSpecificationProvider to the 'visibility' attribute.
      if (!attrName.equals("visibility") && !containsPackageSpecificationProvider) {
        context.reportError(
            rule.getAttributeLocation(attrName),
            "in "
                + attrName
                + " attribute of "
                + rule.getRuleClass()
                + " rule "
                + rule.getLabel()
                + ": "
                + AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITH_KIND)
                + " is misplaced here "
                + "(they are only allowed in the visibility attribute)");
      }
    }
  }

  private void validateDirectPrerequisiteForTestOnly(
      RuleContext.Builder context, ConfiguredTargetAndData prerequisite) {
    Rule rule = context.getRule();

    if (rule.getRuleClassObject().getAdvertisedProviders().canHaveAnyProvider()) {
      // testonly-ness will be checked directly between the depender and the target of the alias;
      // getTarget() called by the depender will not return the alias rule, but its actual target
      return;
    }

    Target prerequisiteTarget = prerequisite.getTarget();
    String thisPackage = rule.getLabel().getPackageName();

    if (isTestOnlyRule(prerequisiteTarget) && !isTestOnlyRule(rule)) {
      String message =
          "non-test target '"
              + rule.getLabel()
              + "' depends on testonly "
              + AliasProvider.describeTargetWithAliases(prerequisite, TargetMode.WITHOUT_KIND)
              + " and doesn't have testonly attribute set";
      if (thisPackage.startsWith("experimental/")) {
        context.ruleWarning(message);
      } else {
        context.ruleError(message);
      }
    }
  }

  private static boolean isTestOnlyRule(Target target) {
    return (target instanceof Rule)
        && (NonconfigurableAttributeMapper.of((Rule) target)).has("testonly", Type.BOOLEAN)
        && (NonconfigurableAttributeMapper.of((Rule) target)).get("testonly", Type.BOOLEAN);
  }
}
