// Path: src/main/java/com/greghaskins/spectrum/Block.java
// @FunctionalInterface
// public interface Block {
//   void run() throws Throwable;
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/Variable.java
// public final class Variable<T> implements Supplier<T> {
// 
//   private T value;
// 
//   /**
//    * Create a Variable with a {@code null} initial value.
//    */
//   public Variable() {}
// 
//   /**
//    * Create a Variable with the given initial value.
//    *
//    * @param value starting value
//    */
//   public Variable(final T value) {
//     set(value);
//   }
// 
//   /**
//    * Get the current value of this Variable.
//    *
//    * @return current value
//    */
//   @Override
//   public T get() {
//     return this.value;
//   }
// 
//   /**
//    * Change the value of this Variable.
//    *
//    * @param value new value
//    */
//   public void set(final T value) {
//     this.value = value;
//   }
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/internal/DeclarationState.java
// public final class DeclarationState {
// 
//   private static final ThreadLocal<DeclarationState> instance =
//       ThreadLocal.withInitial(DeclarationState::new);
// 
//   public static DeclarationState instance() {
//     return instance.get();
//   }
// 
//   private final Deque<Suite> suiteStack = new ArrayDeque<>();
// 
//   private DeclarationState() {}
// 
//   public Suite getCurrentSuiteBeingDeclared() {
//     return suiteStack.peek();
//   }
// 
//   private int getCurrentDepth() {
//     return suiteStack.size();
//   }
// 
//   public void beginDeclaration(final Suite suite, final Block definitionBlock) {
//     suiteStack.push(suite);
// 
//     try {
//       definitionBlock.run();
//     } catch (final Throwable error) {
//       suite.removeAllChildren();
//       suite.addSpec("encountered an error", () -> {
//         throw error;
//       });
//     }
//     suiteStack.pop();
//   }
// 
//   public void addHook(final Hook hook, final AppliesTo appliesTo, final Precedence precedence) {
//     addHook(new HookContext(hook, instance().getCurrentDepth(), appliesTo, precedence));
//   }
// 
//   private void addHook(HookContext hook) {
//     getCurrentSuiteBeingDeclared().addHook(hook);
//   }
// 
// 
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/internal/RunReporting.java
// public interface RunReporting<T, F> {
//   /**
//    * Marks the test as ignored.
//    * @param description description of test
//    */
//   void fireTestIgnored(final T description);
// 
//   /**
//    * Markes the test as having started - call this before any test-specific results.
//    * @param description description of test
//    */
//   void fireTestStarted(final T description);
// 
//   /**
//    * Marks the test as finished - call this after any test-specific results, whether
//    * passed or failed.
//    * @param description description of test
//    */
//   void fireTestFinished(final T description);
// 
//   /**
//    * Marks a test as having failed.
//    * @param failure failure information
//    */
//   void fireTestFailure(final F failure);
// 
//   /**
//    * Marks a test as having an assumption failure.
//    * @param failure failure information
//    */
//   void fireTestAssumptionFailed(final F failure);
// }


import com.greghaskins.spectrum.Block;
import com.greghaskins.spectrum.Variable;
import com.greghaskins.spectrum.internal.DeclarationState;
import com.greghaskins.spectrum.internal.RunReporting;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
package com.greghaskins.spectrum.internal.hooks;



/**
 * A base class for {@link SupplyingHook hooks that supply a value}.
 *
 * <p>Override {@link #before} or {@link #after}. Return the singleton value from the before method.
 * You can use this to write any plugin which needs to make a value visible to the specs.
 * This is not the only way to achieve that - you can also build from {@link SupplyingHook}
 * but this captures the template for a complex hook.
 */
abstract class AbstractSupplyingHook<T> implements SupplyingHook<T> {

  private final Variable<T> value = new Variable<>();

  /**
   * Override this to supply behaviour for before the block is run.
   *
   * @return the value that the singleton will store to supply
   */
  protected abstract T before();

  /**
   * Override this to give a message for when the value from this hook gets used any time other than
   * while running a test.
   *
   * @return the IllegalStateException message to use
   */
  protected abstract String getExceptionMessageIfUsedAtDeclarationTime();

  /**
   * Override this to supply behaviour for after the block is run.
   */
  protected void after() {}

  /**
   * Template method for a hook which supplies.
   *
   * @param description description - unused here
   * @param reporting reporting - unused here
   * @param block       the inner block that will be run
   * @throws Throwable on error
   */
  @Override
  public void accept(final Description description, final RunReporting<Description, Failure> reporting,
      final Block block) throws Throwable {
    try {
      this.value.set(before());
      block.run();
    } finally {
      try {
        after();
// Path: src/main/java/com/greghaskins/spectrum/Block.java
// @FunctionalInterface
// public interface Block {
//   void run() throws Throwable;
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/Variable.java
// public final class Variable<T> implements Supplier<T> {
// 
//   private T value;
// 
//   /**
//    * Create a Variable with a {@code null} initial value.
//    */
//   public Variable() {}
// 
//   /**
//    * Create a Variable with the given initial value.
//    *
//    * @param value starting value
//    */
//   public Variable(final T value) {
//     set(value);
//   }
// 
//   /**
//    * Get the current value of this Variable.
//    *
//    * @return current value
//    */
//   @Override
//   public T get() {
//     return this.value;
//   }
// 
//   /**
//    * Change the value of this Variable.
//    *
//    * @param value new value
//    */
//   public void set(final T value) {
//     this.value = value;
//   }
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/internal/DeclarationState.java
// public final class DeclarationState {
// 
//   private static final ThreadLocal<DeclarationState> instance =
//       ThreadLocal.withInitial(DeclarationState::new);
// 
//   public static DeclarationState instance() {
//     return instance.get();
//   }
// 
//   private final Deque<Suite> suiteStack = new ArrayDeque<>();
// 
//   private DeclarationState() {}
// 
//   public Suite getCurrentSuiteBeingDeclared() {
//     return suiteStack.peek();
//   }
// 
//   private int getCurrentDepth() {
//     return suiteStack.size();
//   }
// 
//   public void beginDeclaration(final Suite suite, final Block definitionBlock) {
//     suiteStack.push(suite);
// 
//     try {
//       definitionBlock.run();
//     } catch (final Throwable error) {
//       suite.removeAllChildren();
//       suite.addSpec("encountered an error", () -> {
//         throw error;
//       });
//     }
//     suiteStack.pop();
//   }
// 
//   public void addHook(final Hook hook, final AppliesTo appliesTo, final Precedence precedence) {
//     addHook(new HookContext(hook, instance().getCurrentDepth(), appliesTo, precedence));
//   }
// 
//   private void addHook(HookContext hook) {
//     getCurrentSuiteBeingDeclared().addHook(hook);
//   }
// 
// 
// }
// 
// Path: src/main/java/com/greghaskins/spectrum/internal/RunReporting.java
// public interface RunReporting<T, F> {
//   /**
//    * Marks the test as ignored.
//    * @param description description of test
//    */
//   void fireTestIgnored(final T description);
// 
//   /**
//    * Markes the test as having started - call this before any test-specific results.
//    * @param description description of test
//    */
//   void fireTestStarted(final T description);
// 
//   /**
//    * Marks the test as finished - call this after any test-specific results, whether
//    * passed or failed.
//    * @param description description of test
//    */
//   void fireTestFinished(final T description);
// 
//   /**
//    * Marks a test as having failed.
//    * @param failure failure information
//    */
//   void fireTestFailure(final F failure);
// 
//   /**
//    * Marks a test as having an assumption failure.
//    * @param failure failure information
//    */
//   void fireTestAssumptionFailed(final F failure);
// }


// Path: src/main/java/com/greghaskins/spectrum/internal/hooks/AbstractSupplyingHook.java
import com.greghaskins.spectrum.Block;
import com.greghaskins.spectrum.Variable;
import com.greghaskins.spectrum.internal.DeclarationState;
import com.greghaskins.spectrum.internal.RunReporting;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;

package com.greghaskins.spectrum.internal.hooks;



/**
 * A base class for {@link SupplyingHook hooks that supply a value}.
 *
 * <p>Override {@link #before} or {@link #after}. Return the singleton value from the before method.
 * You can use this to write any plugin which needs to make a value visible to the specs.
 * This is not the only way to achieve that - you can also build from {@link SupplyingHook}
 * but this captures the template for a complex hook.
 */
abstract class AbstractSupplyingHook<T> implements SupplyingHook<T> {

  private final Variable<T> value = new Variable<>();

  /**
   * Override this to supply behaviour for before the block is run.
   *
   * @return the value that the singleton will store to supply
   */
  protected abstract T before();

  /**
   * Override this to give a message for when the value from this hook gets used any time other than
   * while running a test.
   *
   * @return the IllegalStateException message to use
   */
  protected abstract String getExceptionMessageIfUsedAtDeclarationTime();

  /**
   * Override this to supply behaviour for after the block is run.
   */
  protected void after() {}

  /**
   * Template method for a hook which supplies.
   *
   * @param description description - unused here
   * @param reporting reporting - unused here
   * @param block       the inner block that will be run
   * @throws Throwable on error
   */
  @Override
  public void accept(final Description description, final RunReporting<Description, Failure> reporting,
      final Block block) throws Throwable {
    try {
      this.value.set(before());
      block.run();
    } finally {
      try {
        after();
      } finally {