// Copyright 2018 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.packages;


import com.google.common.base.Preconditions;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkThread;

/*
 * TODO(b/236456122): We should break this class up into separate classes for each kind of Starlark
 * evaluation environment, as opposed to storing possibly inapplicable nullable fields on this
 * class. Then we can use static methods with signatures like fromOrFail(StarlarkThread, String) in
 * place of the Phase enum and its associated check* methods.
 *
 * Some kinds of evaluation environments include:
 *   - .bzl loading
 *   - BUILD evaluation (should absorb PackageFactory.PackageContext -- no need to store multiple
 *     thread-locals in StarlarkThread)
 *   - WORKSPACE evaluation (shares logic with BUILD)
 *   - implicit outputs
 *   - computed defaults
 *   - transition implementation
 *   - Args.map_each
 *   - probably others
 *
 * BazelStarlarkContext itself could probably be deleted. The only thing common to almost all Bazel
 * Starlark environments is SymbolGenerator, which in principle could be used to uniquely identify
 * depsets or even StarlarkFunction, though in practice it doesn't have nearly that widespread usage
 * yet. SymbolGenerator could be promoted to a core feature of StarlarkThread if it reaches that
 * point. If we do keep BazelStarlarkContext around as a common base class of the other context
 * classes, it should be renamed BazelThreadContext for symmetry with BazelModuleContext.
 *
 * Even if we can otherwise get rid of BazelStarlarkContext, it may still be handy to retain this
 * class as a static namespace for helper methods for storing and retrieving contexts on
 * StarlarkThreads. In particular, it'd avoid the very likely bug of a storeInThread
 * implementation in one of the context classes forgetting to setUncheckedExceptionContext(this). It
 * also would give us a place to keep javadoc about the proper way to use these context objects in
 * Bazel.
 */
/**
 * Bazel-specific contextual information associated with a Starlark evaluation thread.
 *
 * <p>This is stored in the StarlarkThread object as a thread-local. A subclass of this class may be
 * used for certain kinds of Starlark evaluations; in that case it is still keyed in the
 * thread-locals under {@code BazelStarlarkContext.class}.
 *
 * <p>This object is mutable and should not be accessed simultaneously or reused for more than one
 * Starlark thread.
 */
public class BazelStarlarkContext implements StarlarkThread.UncheckedExceptionContext {

  /** The phase to which this Starlark thread belongs. */
  // TODO(b/236456122): Eliminate.
  public enum Phase {
    WORKSPACE,
    LOADING,
    ANALYSIS
  }

  /**
   * Retrieves this context from a Starlark thread, or throws {@link EvalException} if unavailable.
   */
  public static BazelStarlarkContext fromOrFail(StarlarkThread thread) throws EvalException {
    BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class);
    if (ctx == null) {
      throw Starlark.errorf(
          "this function cannot be called from %s", thread.getContextDescription());
    }
    return ctx;
  }

  /**
   * Saves this {@code BazelStarlarkContext} in the specified Starlark thread. Call only once,
   * before evaluation begins.
   */
  public void storeInThread(StarlarkThread thread) {
    Preconditions.checkState(thread.getThreadLocal(BazelStarlarkContext.class) == null);
    thread.setThreadLocal(BazelStarlarkContext.class, this);
    // TODO(b/236456122): We can probably replace the concept of setUncheckedExceptionContext with a
    // string parameter to StarlarkThread construction. In that case, storeInThread() becomes more
    // superfluous, and there's one less reason to keep the inheritance hierarchy of
    // BazelStarlarkContext and its children.
    thread.setUncheckedExceptionContext(this);
  }

  // A generic counter for uniquely identifying symbols created in this Starlark evaluation.
  private final SymbolGenerator<?> symbolGenerator;

  // TODO(b/236456122): Eliminate Phase, migrate analysisRuleLabel to a separate context class.
  private final Phase phase;

  /**
   * @param phase the phase to which this Starlark thread belongs
   * @param symbolGenerator a {@link SymbolGenerator} to be used when creating objects to be
   *     compared using reference equality.
   */
  // TODO(b/236456122): Consider taking an owner in place of a SymbolGenerator, and constructing
  // the latter ourselves. Seems like we don't want to tempt anyone into sharing a SymbolGenerator.
  public BazelStarlarkContext(Phase phase, SymbolGenerator<?> symbolGenerator) {
    this.phase = Preconditions.checkNotNull(phase);
    this.symbolGenerator = Preconditions.checkNotNull(symbolGenerator);
  }

  /** Returns the phase associated with this context. */
  public Phase getPhase() {
    return phase;
  }

  public SymbolGenerator<?> getSymbolGenerator() {
    return symbolGenerator;
  }

  @Override
  public String getContextForUncheckedException() {
    return phase.toString();
  }

  /**
   * Checks that the Starlark thread is in the loading or the workspace phase.
   *
   * @param function name of a function that requires this check
   */
  // TODO(b/236456122): The Phase enum is incomplete. Ex: `Args.map_each` evaluation happens at
  // execution time. So this is a misnomer and possibly wrong in those contexts.
  public static void checkLoadingOrWorkspacePhase(StarlarkThread thread, String function)
      throws EvalException {
    BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class);
    if (ctx == null) {
      throw Starlark.errorf(
          "'%s' cannot be called from %s", function, thread.getContextDescription());
    }
    if (ctx.phase == Phase.ANALYSIS) {
      throw Starlark.errorf("'%s' cannot be called during the analysis phase", function);
    }
  }

  /**
   * Checks that the current StarlarkThread is in the loading phase.
   *
   * @param function name of a function that requires this check
   */
  public static void checkLoadingPhase(StarlarkThread thread, String function)
      throws EvalException {
    BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class);
    if (ctx == null) {
      throw Starlark.errorf(
          "'%s' cannot be called from %s", function, thread.getContextDescription());
    }
    if (ctx.phase != Phase.LOADING) {
      throw Starlark.errorf(
          "'%s' can only be called from a BUILD file, or a macro invoked from a BUILD file",
          function);
    }
  }

  /**
   * Checks that the current StarlarkThread is in the workspace phase.
   *
   * @param function name of a function that requires this check
   */
  public static void checkWorkspacePhase(StarlarkThread thread, String function)
      throws EvalException {
    BazelStarlarkContext ctx = thread.getThreadLocal(BazelStarlarkContext.class);
    if (ctx == null) {
      throw Starlark.errorf(
          "'%s' cannot be called from %s", function, thread.getContextDescription());
    }
    if (ctx.phase != Phase.WORKSPACE) {
      throw Starlark.errorf("'%s' can only be called during workspace loading", function);
    }
  }
}
