import { Imm } from 'ts-imm';
import { CodeWriter } from './CodeWriter';
import { FunctionSpec } from './FunctionSpec';
import { SymbolSpec } from './SymbolSpecs';
export interface Dictionary<T> {
    [key: string]: T;
}
/**
 * A fragment of a .ts file, potentially containing declarations, statements, and documentation.
 * Code blocks are not necessarily well-formed TypeScript code, and are not validated. This class
 * assumes tsc will check correctness later!
 *
 * Code blocks support placeholders like [java.text.Format]. This class uses a percent sign
 * `%` but has its own set of permitted placeholders:
 *
 *  * `%L` emits a *literal* value with no escaping. Arguments for literals may be strings,
 *    primitives, [type declarations][ClassSpec], [decorators][DecoratorSpec] and even other code
 *    blocks.
 *  * `%N` emits a *name*, using name collision avoidance where necessary. Arguments for names may
 *    be strings (actually any [character sequence][CharSequence]), [parameters][ParameterSpec],
 *    [properties][PropertySpec], [functions][FunSpec], and [types][ClassSpec].
 *  * `%S` escapes the value as a *string*, wraps it with double quotes, and emits that. For
 *    example, `6" sandwich` is emitted `"6\" sandwich"`.
 *  * `%T` emits a *type* reference. Types will be imported if possible. Arguments for types may be
 *    [classes][Class], [type mirrors][javax.lang.model.type.TypeMirror], and
 *    [elements][javax.lang.model.element.Element].
 *  * `%%` emits a percent sign.
 *  * `%W` emits a space or a newline, depending on its position on the line. This prefers to wrap
 *    lines before 100 columns.
 *  * `%>` increases the indentation level.
 *  * `%<` decreases the indentation level.
 *  * `%[` begins a statement.
 *  * `%]` ends a statement.
 */
export declare class CodeBlock extends Imm<CodeBlock> {
    static of(format: string, ...args: any[]): CodeBlock;
    static empty(): CodeBlock;
    static hash(contents: object): CodeBlock;
    /** Returns a code block for doing multiline lambdas. */
    static lambda(...parameterNames: string[]): CodeBlock;
    static asyncLambda(...parameterNames: string[]): CodeBlock;
    static joinToCode(blocks: CodeBlock[], separator?: string, prefix?: string, suffix?: string): CodeBlock;
    /** A heterogeneous list containing string literals and value placeholders.  */
    readonly formatParts: ReadonlyArray<string>;
    readonly args: ReadonlyArray<unknown>;
    readonly referencedSymbols: Set<SymbolSpec>;
    readonly trailer?: CodeBlock;
    indent(): this;
    unindent(): this;
    /**
     * @param controlFlow the control flow construct and its code, such as "if (foo == 5)".
     *     Shouldn't contain braces or newline characters.
     */
    beginControlFlow(controlFlow: string, ...args: any[]): this;
    /**
     * @param controlFlow the control flow construct and its code, such as "else if (foo == 10)".
     *     Shouldn't contain braces or newline characters.
     */
    nextControlFlow(controlFlow: string, ...args: any[]): this;
    endControlFlow(): this;
    beginLambda(controlFlow: string, ...args: any[]): this;
    endLambda(closing: string, ...args: any[]): this;
    beginHash(): this;
    endHash(): this;
    addHashEntry(value: FunctionSpec): this;
    addHashEntry(key: string, value: CodeBlock | any): this;
    newLine(): this;
    addStatement(format: string, ...args: any[]): this;
    addFunction(fn: FunctionSpec): this;
    addCode(codeBlock: CodeBlock): this;
    addTrailer(codeBlock: CodeBlock): this;
    /**
     * Add code with positional or relative arguments.
     *
     * Relative arguments map 1:1 with the placeholders in the format string.
     *
     * Positional arguments use an index after the placeholder to identify which argument index
     * to use. For example, for a literal to reference the 3rd argument: "%3L" (1 based index)
     *
     * Mixing relative and positional arguments in a call to add is invalid and will result in an
     * error.
     */
    add(format: string, ...args: any[]): this;
    /**
     * Adds code using named arguments.
     *
     * Named arguments specify their name after the '%' followed by : and the corresponding type
     * character. Argument names consist of characters in `a-z, A-Z, 0-9, and _` and must start
     * with a lowercase character.
     *
     * For example, to refer to the type [java.lang.Integer] with the argument name `clazz` use a
     * format string containing `%clazz:T` and include the key `clazz` with value
     * `java.lang.Integer.class` in the argument map.
     */
    addNamed(format: string, args: Dictionary<unknown>): this;
    remove(matching: RegExp): this;
    isEmpty(): boolean;
    isNotEmpty(): boolean;
    emit(codeWriter: CodeWriter): void;
    toString(): string;
    /**
     * Returns a code block with `prefix` stripped off, or null if this code block doesn't start with
     * `prefix`.
     *
     * This is a pretty anyType implementation that might not cover cases like mismatched whitespace. We
     * could offer something more lenient if necessary.
     */
    private withoutPrefix;
    /**
     * Returns a copy of the code block without leading and trailing no-arg placeholders
     * (`%W`, `%<`, `%>`, `%[`, `%]`).
     */
    private trim;
}
