// 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 static com.google.devtools.build.lib.analysis.test.ExecutionInfo.DEFAULT_TEST_RUNNER_EXEC_GROUP;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.DISTRIBUTIONS;
import static com.google.devtools.build.lib.packages.BuildType.LABEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import static com.google.devtools.build.lib.packages.BuildType.LICENSE;
import static com.google.devtools.build.lib.packages.BuildType.NODEP_LABEL_LIST;
import static com.google.devtools.build.lib.packages.Type.BOOLEAN;
import static com.google.devtools.build.lib.packages.Type.INTEGER;
import static com.google.devtools.build.lib.packages.Type.STRING;
import static com.google.devtools.build.lib.packages.Type.STRING_DICT;
import static com.google.devtools.build.lib.packages.Type.STRING_LIST;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationValue;
import com.google.devtools.build.lib.analysis.config.ExecutionTransitionFactory;
import com.google.devtools.build.lib.analysis.config.RunUnder;
import com.google.devtools.build.lib.analysis.constraints.ConstraintConstants;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.test.CoverageConfiguration;
import com.google.devtools.build.lib.analysis.test.TestConfiguration;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.Attribute.LabelLateBoundDefault;
import com.google.devtools.build.lib.packages.Attribute.LabelListLateBoundDefault;
import com.google.devtools.build.lib.packages.Attribute.LateBoundDefault.Resolver;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy;
import com.google.devtools.build.lib.packages.RuleClass;
import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
import com.google.devtools.build.lib.packages.TestSize;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.packages.Type.ConversionException;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.util.FileTypeSet;
import javax.annotation.Nullable;
import net.starlark.java.eval.StarlarkInt;

/**
 * Rule class definitions used by (almost) every rule.
 */
public class BaseRuleClasses {

  private BaseRuleClasses() {}

  @SerializationConstant @AutoCodec.VisibleForSerialization
  static final Attribute.ComputedDefault testonlyDefault =
      new Attribute.ComputedDefault() {
        @Override
        public Object getDefault(AttributeMap rule) {
          return rule.getPackageArgs().defaultTestOnly();
        }

        @Override
        public boolean resolvableWithRawAttributes() {
          return true;
        }
      };

  @SerializationConstant @AutoCodec.VisibleForSerialization
  static final Attribute.ComputedDefault deprecationDefault =
      new Attribute.ComputedDefault() {
        @Override
        public Object getDefault(AttributeMap rule) {
          return rule.getPackageArgs().defaultDeprecation();
        }

        @Override
        public boolean resolvableWithRawAttributes() {
          return true;
        }
      };

  @SerializationConstant @AutoCodec.VisibleForSerialization
  public static final Attribute.ComputedDefault TIMEOUT_DEFAULT =
      new Attribute.ComputedDefault() {
        @Override
        public Object getDefault(AttributeMap rule) {
          TestSize size = TestSize.getTestSize(rule.get("size", Type.STRING));
          if (size != null) {
            String timeout = size.getDefaultTimeout().toString();
            if (timeout != null) {
              return timeout;
            }
          }
          return "illegal";
        }

        @Override
        public boolean resolvableWithRawAttributes() {
          return true;
        }
      };

  // TODO(b/65746853): provide a way to do this without passing the entire configuration
  /**
   * Implementation for the :action_listener attribute.
   *
   * <p>action_listeners are special rules; they tell the build system to add extra_actions to
   * existing rules. As such they need an edge to every ConfiguredTarget with the limitation that
   * they only run on the target configuration and should not operate on action_listeners and
   * extra_actions themselves (to avoid cycles).
   */
  @SerializationConstant @AutoCodec.VisibleForSerialization @VisibleForTesting
  static final LabelListLateBoundDefault<?> ACTION_LISTENER =
      LabelListLateBoundDefault.fromTargetConfiguration(
          BuildConfigurationValue.class,
          (rule, attributes, configuration) -> configuration.getActionListeners());

  public static final String DEFAULT_COVERAGE_SUPPORT_VALUE = "//tools/test:coverage_support";

  @SerializationConstant @AutoCodec.VisibleForSerialization
  static final Resolver<TestConfiguration, Label> COVERAGE_SUPPORT_CONFIGURATION_RESOLVER =
      (rule, attributes, configuration) -> configuration.getCoverageSupport();

  public static LabelLateBoundDefault<TestConfiguration> coverageSupportAttribute(
      Label defaultValue) {
    return LabelLateBoundDefault.fromTargetConfiguration(
        TestConfiguration.class, defaultValue, COVERAGE_SUPPORT_CONFIGURATION_RESOLVER);
  }

  public static final String DEFAULT_COVERAGE_REPORT_GENERATOR_VALUE =
      "//tools/test:coverage_report_generator";

  @SerializationConstant @AutoCodec.VisibleForSerialization
  static final Resolver<CoverageConfiguration, Label>
      COVERAGE_REPORT_GENERATOR_CONFIGURATION_RESOLVER =
          (rule, attributes, configuration) -> configuration.reportGenerator();

  public static LabelLateBoundDefault<CoverageConfiguration> coverageReportGeneratorAttribute(
      Label defaultValue) {
    return LabelLateBoundDefault.fromTargetConfiguration(
        CoverageConfiguration.class,
        defaultValue,
        COVERAGE_REPORT_GENERATOR_CONFIGURATION_RESOLVER);
  }

  public static LabelLateBoundDefault<CoverageConfiguration> getCoverageOutputGeneratorLabel() {
    return LabelLateBoundDefault.fromTargetConfiguration(
        CoverageConfiguration.class, null, COVERAGE_OUTPUT_GENERATOR_RESOLVER);
  }

  @SerializationConstant @AutoCodec.VisibleForSerialization
  static final Resolver<CoverageConfiguration, Label> COVERAGE_OUTPUT_GENERATOR_RESOLVER =
      (rule, attributes, configuration) -> configuration.outputGenerator();

  // TODO(b/65746853): provide a way to do this without passing the entire configuration
  /** Implementation for the :run_under attribute. */
  @SerializationConstant @AutoCodec.VisibleForSerialization
  public static final LabelLateBoundDefault<?> RUN_UNDER =
      LabelLateBoundDefault.fromTargetConfiguration(
          BuildConfigurationValue.class,
          null,
          (rule, attributes, configuration) -> {
            RunUnder runUnder = configuration.getRunUnder();
            return runUnder != null ? runUnder.getLabel() : null;
          });

  /**
   * A base rule for all test rules.
   */
  public static final class TestBaseRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      builder
          .addExecGroup(DEFAULT_TEST_RUNNER_EXEC_GROUP)
          .requiresConfigurationFragments(TestConfiguration.class)
          // TestConfiguration only needed to create TestAction and TestProvider
          // Only necessary at top-level and can be skipped if trimmed.
          .setMissingFragmentPolicy(TestConfiguration.class, MissingFragmentPolicy.IGNORE)
          .add(
              attr("size", STRING)
                  .value("medium")
                  .taggable()
                  .nonconfigurable("policy decision: should be consistent across configurations"))
          .add(
              attr("timeout", STRING)
                  .taggable()
                  .nonconfigurable("policy decision: should be consistent across configurations")
                  .value(TIMEOUT_DEFAULT))
          .add(
              attr("flaky", BOOLEAN)
                  .value(false)
                  .taggable()
                  .nonconfigurable("policy decision: should be consistent across configurations"))
          .add(attr("shard_count", INTEGER).value(StarlarkInt.of(-1)))
          .add(
              attr("local", BOOLEAN)
                  .value(false)
                  .taggable()
                  .nonconfigurable("policy decision: should be consistent across configurations"))
          .add(attr("args", STRING_LIST))
          .add(attr("env", STRING_DICT))
          .add(attr("env_inherit", STRING_LIST))
          // Input files for every test action
          .add(
              attr("$test_wrapper", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .singleArtifact()
                  .value(env.getToolsLabel("//tools/test:test_wrapper")))
          .add(
              attr("$xml_writer", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .singleArtifact()
                  .value(env.getToolsLabel("//tools/test:xml_writer")))
          .add(
              attr("$test_runtime", LABEL_LIST)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .value(getTestRuntimeLabelList(env)))
          .add(
              attr("$test_setup_script", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .singleArtifact()
                  .value(env.getToolsLabel("//tools/test:test_setup")))
          .add(
              attr("$xml_generator_script", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .singleArtifact()
                  .value(env.getToolsLabel("//tools/test:test_xml_generator")))
          .add(
              attr("$collect_coverage_script", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .singleArtifact()
                  .value(env.getToolsLabel("//tools/test:collect_coverage")))
          // Input files for test actions collecting code coverage
          .add(
              attr(":coverage_support", LABEL)
                  .value(
                      coverageSupportAttribute(env.getToolsLabel(DEFAULT_COVERAGE_SUPPORT_VALUE))))
          // Used in the one-per-build coverage report generation action.
          .add(
              attr(":coverage_report_generator", LABEL)
                  .cfg(ExecutionTransitionFactory.createFactory())
                  .value(
                      coverageReportGeneratorAttribute(
                          env.getToolsLabel(DEFAULT_COVERAGE_REPORT_GENERATOR_VALUE))))
          // The target itself and run_under both run on the same machine.
          .add(attr(":run_under", LABEL).value(RUN_UNDER).skipPrereqValidatorCheck());

      env.getNetworkAllowlistForTests()
          .ifPresent(
              label ->
                  builder.add(
                      Allowlist.getAttributeFromAllowlistName("external_network").value(label)));

      return builder.build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$test_base_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(MakeVariableExpandingRule.class)
          .build();
    }
  }

  private static final String TOOLS_TEST_RUNTIME_TARGET_PATTERN = "//tools/test:runtime";
  private static ImmutableList<Label> testRuntimeLabelList = null;

  // Always return the same ImmutableList<Label> for every $test_runtime attribute's default value.
  public static synchronized ImmutableList<Label> getTestRuntimeLabelList(
      RuleDefinitionEnvironment env) {
    if (testRuntimeLabelList == null) {
      testRuntimeLabelList =
          ImmutableList.of(
              Label.parseCanonicalUnchecked(
                  env.getToolsRepository() + TOOLS_TEST_RUNTIME_TARGET_PATTERN));
    }
    return testRuntimeLabelList;
  }

  /**
   * The attribute used to list the configuration properties used by a target and its transitive
   * dependencies. Currently only supports config_feature_flag.
   *
   * <p>A special value of "//command_line_option/fragments:test" instructs
   * TestTrimmingTransitionFactory to skip trimming for this rule.
   */
  public static final String TAGGED_TRIMMING_ATTR = "transitive_configs";

  /** Share common attributes across both base and Starlark base rules. */
  // TODO(bazel-team): replace this with a common RuleDefinition ancestor of NativeBuildRule
  // and StarlarkRuleClassFunctions.baseRule. This requires refactoring StarlarkRuleClassFunctions
  // to instantiate its RuleClasses through RuleDefinition.
  public static RuleClass.Builder commonCoreAndStarlarkAttributes(RuleClass.Builder builder) {
    return builder
        // The visibility attribute is special: it is a nodep label, and loading the
        // necessary package groups is handled by {@link LabelVisitor#visitTargetVisibility}.
        // Package groups always have the null configuration so that they are not duplicated
        // needlessly.
        .add(
            attr("visibility", NODEP_LABEL_LIST)
                .orderIndependent()
                .cfg(ExecutionTransitionFactory.createFactory())
                .nonconfigurable(
                    "special attribute integrated more deeply into Bazel's core logic"))
        .add(
            attr(TAGGED_TRIMMING_ATTR, NODEP_LABEL_LIST)
                .orderIndependent()
                .nonconfigurable("Used in determining configuration"))
        .add(
            attr("deprecation", STRING)
                .value(deprecationDefault)
                .nonconfigurable("Used in core loading phase logic with no access to configs"))
        .add(
            attr("tags", STRING_LIST)
                .orderIndependent()
                .taggable()
                .nonconfigurable("low-level attribute, used in TargetUtils without configurations"))
        .add(
            attr("generator_name", STRING)
                .undocumented("internal")
                .nonconfigurable("static structure of a rule"))
        .add(
            attr("generator_function", STRING)
                .undocumented("internal")
                .nonconfigurable("static structure of a rule"))
        .add(
            attr("generator_location", STRING)
                .undocumented("internal")
                .nonconfigurable("static structure of a rule"))
        .add(
            attr("testonly", BOOLEAN)
                .value(testonlyDefault)
                .nonconfigurable("policy decision: rules testability should be consistent"))
        .add(attr("features", STRING_LIST).orderIndependent())
        .add(
            attr(":action_listener", LABEL_LIST)
                .cfg(ExecutionTransitionFactory.createFactory())
                .value(ACTION_LISTENER))
        .add(
            attr(RuleClass.COMPATIBLE_ENVIRONMENT_ATTR, LABEL_LIST)
                .allowedRuleClasses(ConstraintConstants.ENVIRONMENT_RULE)
                .cfg(ExecutionTransitionFactory.createFactory())
                .allowedFileTypes(FileTypeSet.NO_FILE)
                .dontCheckConstraints()
                .nonconfigurable(
                    "special logic for constraints and select: see ConstraintSemantics"))
        .add(
            attr(RuleClass.RESTRICTED_ENVIRONMENT_ATTR, LABEL_LIST)
                .allowedRuleClasses(ConstraintConstants.ENVIRONMENT_RULE)
                .cfg(ExecutionTransitionFactory.createFactory())
                .allowedFileTypes(FileTypeSet.NO_FILE)
                .dontCheckConstraints()
                .nonconfigurable(
                    "special logic for constraints and select: see ConstraintSemantics"))
        .add(
            attr(RuleClass.CONFIG_SETTING_DEPS_ATTRIBUTE, LABEL_LIST)
                .nonconfigurable("stores configurability keys"))
        .add(
            attr(RuleClass.APPLICABLE_LICENSES_ATTR, LABEL_LIST)
                .cfg(ExecutionTransitionFactory.createFactory())
                .allowedFileTypes(FileTypeSet.NO_FILE)
                // TODO(b/148601291): Require provider to be "LicenseInfo".
                .dontCheckConstraints()
                .nonconfigurable("applicable_licenses is not configurable"))
        .add(
            attr("aspect_hints", LABEL_LIST)
                .allowedFileTypes(FileTypeSet.NO_FILE)
                .undocumented("experimental attribute"));
  }

  public static RuleClass.Builder execPropertiesAttribute(RuleClass.Builder builder)
      throws ConversionException {
    return builder.add(
        attr(RuleClass.EXEC_PROPERTIES_ATTR, STRING_DICT).defaultValue(ImmutableMap.of()));
  }

  /**
   * Ancestor of every native rule in BUILD files (not WORKSPACE files).
   *
   * <p>This includes:
   *
   * <ul>
   *   <li>rules that create actions ({@link NativeActionCreatingRule})
   *   <li>rules that encapsulate toolchain and build environment context
   *   <li>rules that aggregate other rules (like file groups, test suites, or aliases)
   * </ul>
   */
  public static final class NativeBuildRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return commonCoreAndStarlarkAttributes(builder)
          .add(
              attr("licenses", LICENSE)
                  .nonconfigurable("Used in core loading phase logic with no access to configs"))
          .add(
              attr("distribs", DISTRIBUTIONS)
                  .nonconfigurable("Used in core loading phase logic with no access to configs"))
          // Any rule that provides its own meaning for the "target_compatible_with" attribute
          // has to be excluded in `IncompatibleTargetChecker`.
          .add(
              attr(RuleClass.TARGET_COMPATIBLE_WITH_ATTR, LABEL_LIST)
                  .mandatoryProviders(ConstraintValueInfo.PROVIDER.id())
                  // This should be configurable to allow for complex types of restrictions.
                  .tool(
                      "target_compatible_with exists for constraint checking, not to create an"
                          + " actual dependency")
                  .allowedFileTypes(FileTypeSet.NO_FILE))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$native_build_rule")
          .type(RuleClassType.ABSTRACT)
          .build();
    }
  }

  /**
   * A rule that contains a {@code variables=} attribute to allow referencing Make variables.
   */
  public static final class MakeVariableExpandingRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          // Documented in
          // com/google/devtools/build/docgen/templates/attributes/common/toolchains.html.
          .add(
              attr("toolchains", LABEL_LIST)
                  .allowedFileTypes(FileTypeSet.NO_FILE)
                  .mandatoryProviders(ImmutableList.of(TemplateVariableInfo.PROVIDER.id()))
                  .dontCheckConstraints())
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$make_variable_expanding_rule")
          .type(RuleClassType.ABSTRACT)
          .build();
    }
  }

  /**
   * Ancestor of every native BUILD rule that creates actions.
   *
   * <p>This is a subset of all BUILD rules. Filegroups and aliases, for example, simply encapsulate
   * other rules. Toolchain rules provide metadata for actions of other rules. See {@link
   * NativeBuildRule} for these.
   */
  public static final class NativeActionCreatingRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(attr("deps", LABEL_LIST).legacyAllowAnyFileType())
          .add(
              attr("data", LABEL_LIST)
                  .allowedFileTypes(FileTypeSet.ANY_FILE)
                  .dontCheckConstraints())
          .add(attr(RuleClass.EXEC_PROPERTIES_ATTR, Type.STRING_DICT).value(ImmutableMap.of()))
          .add(
              attr(RuleClass.EXEC_COMPATIBLE_WITH_ATTR, BuildType.LABEL_LIST)
                  .allowedFileTypes()
                  .nonconfigurable("Used in toolchain resolution")
                  .tool(
                      "exec_compatible_with exists for constraint checking, not to create an"
                          + " actual dependency")
                  .value(ImmutableList.of()))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$native_buildable_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(BaseRuleClasses.NativeBuildRule.class)
          .build();
    }
  }

  /** A base rule for all binary rules. */
  public static final class BinaryBaseRule implements RuleDefinition {
    @Override
    public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment env) {
      return builder
          .add(attr("args", STRING_LIST))
          .add(attr("env", STRING_DICT))
          .add(attr("output_licenses", LICENSE))
          .add(
              attr("$is_executable", BOOLEAN)
                  .value(true)
                  .nonconfigurable("Called from RunCommand.isExecutable, which takes a Target"))
          .build();
    }

    @Override
    public Metadata getMetadata() {
      return RuleDefinition.Metadata.builder()
          .name("$binary_base_rule")
          .type(RuleClassType.ABSTRACT)
          .ancestors(MakeVariableExpandingRule.class)
          .build();
    }
  }

  /**
   * Factory used by rules' definitions that exist for the sole purpose of providing documentation.
   * For most of these rules, the actual rule is implemented in Starlark but the documentation
   * generation mechanism does not work yet for Starlark rules. TODO(bazel-team): Delete once
   * documentation tools work for Starlark.
   */
  public static class EmptyRuleConfiguredTargetFactory implements RuleConfiguredTargetFactory {
    @Override
    @Nullable
    public ConfiguredTarget create(RuleContext ruleContext) {
      ruleContext.ruleError("Rule is unimplemented.");
      return null;
    }
  }
}
