/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
/**
 * An object which can enter a "broken" state where trying to use it is a UsageError.
 * @remarks
 * Use {@link WithBreakable} to apply this to another object.
 * @sealed
 */
export declare class Breakable {
    /**
     * A name for a given breakable scope.
     * @remarks
     * This is useful for documenting the semantics of a given Breakable and when inspecting things in the debugger, but is currently otherwise unused.
     */
    private readonly name;
    private brokenBy?;
    constructor(
    /**
     * A name for a given breakable scope.
     * @remarks
     * This is useful for documenting the semantics of a given Breakable and when inspecting things in the debugger, but is currently otherwise unused.
     */
    name: string);
    /**
     * Throws if this object is in the broken state.
     * @remarks
     * Can use {@link throwIfBroken} to apply this to a method.
     */
    use(message?: (brokenBy: Error) => string): void;
    /**
     * Puts this object into the broken state, and throws an error.
     *
     * @throws If already broken by a different error, throws a UsageError, otherwise throws `brokenBy`.
     */
    break(brokenBy: Error): never;
    /**
     * {@link Breakable.break}, except tolerates `unknown` to be more easily used by catch blocks.
     * @privateRemarks
     * If there is a use-case, this should be made public.
     */
    private rethrowCaught;
    /**
     * Runs code which should break the object if it throws.
     * @remarks
     * Like {@link Breakable.use}, this also throws if already broken.
     * Any exceptions this catches are re-thrown.
     * Can use {@link breakingMethod} to apply this to a method.
     *
     * If `breaker` returns a Promise, the breakable is also broken if that Promise rejects, and the broken state is rechecked when it resolves:
     * if the breakable was put into a broken state during the async operation (by some other code path), the resolved value is discarded and the returned Promise rejects with a {@link UsageError}.
     *
     * This does not serialize concurrent runs: a synchronous run invoked while an async run is in flight will execute immediately, and is only blocked if the breakable is already broken.
     * Detection of an async result uses `instanceof Promise`, so custom Promise-like objects and Promises from other realms will be treated as synchronous results.
     */
    run<TResult>(breaker: () => TResult): TResult;
    /**
     * Clears the existing broken state.
     * @remarks
     * This is rarely safe to to: it is only ok when all objects using this breaker are known to not have been left in an invalid state.
     * This is pretty much only safe in tests which just were checking a specific error was thrown, and which know that error closepath is actually exception safe.
     */
    clearError(): void;
}
/**
 * Marks an object as being able to be in a broken state (unknown/unspecified/broken state due to unhandled exception).
 * @remarks
 * See decorators {@link breakingMethod} and {@link throwIfBroken} for ease of use.
 */
export interface WithBreakable {
    /**
     * The breaker for this object.
     * @remarks
     * If this `breaker` is in the broken state, the `WithBreakable` should be considered in a broken state.
     */
    readonly breaker: Breakable;
}
/**
 * Decorator for methods which should break the object when they throw.
 * @remarks
 * This also throws if already broken like {@link throwIfBroken}.
 * See {@link Breakable.run} for details.
 *
 * This should be used on methods which modify data that could result in an unsupported/broken state if an exception is thrown while modifying.
 * It is ok for breakingMethods to call each-other.
 * @privateRemarks
 * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.
 */
export declare function breakingMethod<Target extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return), This extends WithBreakable, Args extends never[], Return>(target: Target, context?: ClassMethodDecoratorContext<This, Target>): Target;
/**
 * Decorator for methods which should throw if the object is in a broken state.
 * @remarks
 * This should be used on methods which read data that could be invalid when the object is broken.
 * @privateRemarks
 * Explicitly capturing the full `Target` type is necessary to make this work with generic methods with unknown numbers of type parameters.
 */
export declare function throwIfBroken<Target extends ((...args: any[]) => unknown) & ((this: This, ...args: Args) => Return), This extends WithBreakable, Args extends never[], Return>(target: Target, context: ClassMethodDecoratorContext<This, Target>): Target;
/**
 * Decorator for classes which should break when their methods throw.
 * @remarks
 * Applies {@link breakingMethod} to all methods declared directly by class or its base classes.
 * Does not include those on derived classes.
 * Does not include getters or setters, or value properties.
 * Methods already marked as {@link breakingMethod} or {@link throwIfBroken} are unaffected.
 */
export declare function breakingClass<Target extends abstract new (...args: any[]) => WithBreakable>(target: Target, context: ClassDecoratorContext<Target>): Target;
//# sourceMappingURL=breakable.d.ts.map