import { TransformError, MagicStringAST, SFC } from '@vue-macros/common';
export * from '@vue-macros/common';
export { SFC, parseSFC } from '@vue-macros/common';
import * as neverthrow from 'neverthrow';
import { ResultAsync as ResultAsync$1 } from 'neverthrow';
import { TypeScript, Declaration, TSModuleBlock, Statement, TSType, TSParenthesizedType, TSTypeAliasDeclaration, Node, Identifier, TSCallSignatureDeclaration, TSFunctionType, TSConstructSignatureDeclaration, TSMethodSignature, TSPropertySignature, TSMappedType, TSInterfaceDeclaration, TSInterfaceBody, TSTypeLiteral, TSIntersectionType, TemplateLiteral, StringLiteral, TSLiteralType, NumericLiteral, BooleanLiteral, BigIntLiteral, TSTypeElement, TSIndexedAccessType, TSUnionType, TSTypeOperator, LVal, VariableDeclaration, ExpressionStatement, CallExpression, TSTypeReference, ObjectMethod, ObjectProperty, Expression } from '@babel/types';
import { Plugin } from 'vite';

type ErrorVueSFC = "<script> is not supported, only <script setup>.";
type ErrorResolveTS = "Cannot resolve TS definition." | "Cannot resolve TS definition. Union type contains different types of results." | `Cannot resolve TS definition: ${string}` | `Cannot resolve TS type: ${string}`;
type ErrorWithDefaults = "withDefaults: first argument must be a defineProps call.";
type ErrorUnknownNode = `Unknown node: ${string}` | `Unknown ${"import" | "export"} type: ${string}`;
type Error = TransformError<ErrorVueSFC | ErrorResolveTS | ErrorWithDefaults | ErrorUnknownNode>;
type ResultAsync<T> = neverthrow.ResultAsync<T, Error>;

type TSDeclaration = TypeScript & Declaration;
declare function isTSDeclaration(node: any): node is TSDeclaration;

interface TSScopeBase {
	exports?: TSNamespace;
	declarations?: TSNamespace;
}
interface TSFile extends TSScopeBase {
	kind: "file";
	filePath: string;
	content: string;
	/** could be undefined if it's a JSON file */
	ast: Statement[] | undefined;
}
interface TSModule extends TSScopeBase {
	kind: "module";
	ast: TSModuleBlock;
	scope: TSScope;
}
type TSScope = TSFile | TSModule;
declare const tsFileCache: Record<string, TSFile>;
declare function getTSFile(filePath: string): Promise<TSFile>;
interface ResolvedTSScope {
	isFile: boolean;
	file: TSFile;
	body: Statement[] | undefined;
	exports?: TSNamespace;
	declarations?: TSNamespace;
}
declare function resolveTSScope(scope: TSScope): ResolvedTSScope;

interface TSResolvedType<T = Exclude<TSType, TSParenthesizedType> | Exclude<TSDeclaration, TSTypeAliasDeclaration>> {
	scope: TSScope;
	type: T;
}
type TSReferencedType = TSType | Identifier | TSDeclaration;
declare function isSupportedForTSReferencedType(node: Node): node is TSReferencedType;
/**
* Resolve a reference to a type.
*
* Supports `type` and `interface` only.
*
* @limitation don't support non-TS declaration (e.g. class, function...)
*/
declare function resolveTSReferencedType(ref: TSResolvedType<TSReferencedType>, stacks?: TSResolvedType<any>[]): ResultAsync$1<TSResolvedType | TSNamespace | undefined, TransformError<ErrorUnknownNode>>;

declare const namespaceSymbol: unique symbol;
type TSNamespace = { [K in string] : TSResolvedType | TSNamespace | undefined } & {
	[namespaceSymbol]: true
};
declare function isTSNamespace(val: unknown): val is TSNamespace;
/**
* Get exports of the TS file.
*
* @limitation don't support non-TS declaration (e.g. class, function...)
*/
declare function resolveTSNamespace(scope: TSScope): ResultAsync$1<void, TransformError<ErrorUnknownNode>>;

interface TSProperties {
	callSignatures: Array<TSResolvedType<TSCallSignatureDeclaration | TSFunctionType>>;
	constructSignatures: Array<TSResolvedType<TSConstructSignatureDeclaration>>;
	methods: Record<string | number, Array<TSResolvedType<TSMethodSignature>>>;
	properties: Record<string | number, {
		value: TSResolvedType<TSType> | null
		optional: boolean
		signature: TSResolvedType<TSPropertySignature | TSMappedType>
	}>;
}
declare function mergeTSProperties(a: TSProperties, b: TSProperties): TSProperties;
declare function checkForTSProperties(node?: Node): node is TSInterfaceDeclaration | TSInterfaceBody | TSTypeLiteral | TSIntersectionType | TSMappedType | TSFunctionType;
/**
* get properties of `interface` or `type` declaration
*
* @limitation don't support index signature
*/
declare function resolveTSProperties({ type, scope }: TSResolvedType<TSInterfaceDeclaration | TSInterfaceBody | TSTypeLiteral | TSIntersectionType | TSMappedType | TSFunctionType>): ResultAsync$1<TSProperties, TransformError<ErrorUnknownNode>>;
declare function getTSPropertiesKeys(properties: TSProperties): string[];

declare function resolveDts(id: string, importer: string): Promise<string | undefined>;
declare const resolveDtsHMR: NonNullable<Plugin["handleHotUpdate"]>;

declare function resolveTSTemplateLiteral({ type, scope }: TSResolvedType<TemplateLiteral>): ResultAsync$1<StringLiteral[], TransformError<ErrorUnknownNode>>;
declare function resolveTSLiteralType({ type, scope }: TSResolvedType<TSLiteralType>): ResultAsync$1<StringLiteral[] | NumericLiteral | StringLiteral | BooleanLiteral | BigIntLiteral | undefined, TransformError<ErrorUnknownNode>>;
/**
* @limitation don't support index signature
*/
declare function resolveTypeElements(scope: TSScope, elements: Array<TSTypeElement>): TSProperties;
declare function resolveTSIndexedAccessType({ scope, type }: TSResolvedType<TSIndexedAccessType>, stacks?: TSResolvedType<any>[]): ResultAsync$1<{
	type: TSUnionType
	scope: TSScope
} | void, TransformError<ErrorUnknownNode>>;
declare function resolveTSTypeOperator({ scope, type }: TSResolvedType<TSTypeOperator>, stacks?: TSResolvedType<any>[]): ResultAsync$1<StringLiteral[] | void, TransformError<ErrorUnknownNode>>;
declare function resolveMaybeTSUnion<T extends Node>(node: T | T[]): T[];
declare function resolveMaybeTSUnion<T extends Node>(node: T): (T | TSType)[];

declare enum DefinitionKind {
	/**
	* Definition is a referenced variable.
	*
	* @example defineSomething(foo)
	*/
	Reference = "Reference",
	/**
	* Definition is a `ObjectExpression`.
	*
	* @example defineSomething({ ... })
	*/
	Object = "Object",
	/**
	* Definition is TypeScript interface.
	*
	* @example defineSomething<{ ... }>()
	*/
	TS = "TS"
}
interface ASTDefinition<T extends Node> {
	code: string;
	scope: TSFile | TSModule | undefined;
	ast: T;
}

declare function handleTSEmitsDefinition({ s, file, offset, defineEmitsAst, typeDeclRaw, declId, statement }: {
	s: MagicStringAST
	file: TSFile
	sfc: SFC
	offset: number
	defineEmitsAst: CallExpression
	typeDeclRaw: TSType
	statement: DefineEmitsStatement
	declId?: LVal
}): ResultAsync$1<TSEmits, TransformError<ErrorResolveTS | ErrorUnknownNode>>;
type Emits = TSEmits | undefined;
type DefineEmitsStatement = VariableDeclaration | ExpressionStatement;
interface EmitsBase {
	declId?: LVal;
	statementAst: DefineEmitsStatement;
	defineEmitsAst: CallExpression;
}
interface TSEmits extends EmitsBase {
	kind: DefinitionKind.TS;
	definitions: Record<string, ASTDefinition<TSCallSignatureDeclaration | TSFunctionType | TSPropertySignature | TSMappedType>[]>;
	definitionsAst: ASTDefinition<TSTypeLiteral | TSIntersectionType | TSInterfaceDeclaration | TSFunctionType>;
	/**
	* Adds a new emit to the definitions. `definitions` will updated after this call.
	*
	* Added definition cannot be set and removed again.
	*
	* @example add('change', '(evt: "change", value: string): void')
	*/
	addEmit: (name: string | StringLiteral, signature: string) => void;
	/**
	* Modify a definition of a emit. `definitions` will updated after this call.
	*
	* @limitation Cannot set the emit added by `addEmit`.
	*
	* @example setEmit('foo', 0, '(evt: "change", value: string): void')
	*
	* @returns false if the definition does not exist.
	*/
	setEmit: (name: string | StringLiteral, index: number, signature: string) => boolean;
	/**
	* Removes specified emit from TS interface. `definitions` will updated after this call.
	*
	* @limitation Cannot remove emit added by `addEmit`. (it will be removed in definitions though)
	*
	* @returns `true` if emit was removed, `false` if emit was not found.
	*/
	removeEmit: (name: string | StringLiteral, index: number) => boolean;
}

declare function handleTSPropsDefinition({ s, file, offset, definePropsAst, typeDeclRaw, withDefaultsAst, defaultsDeclRaw, statement, declId }: {
	s: MagicStringAST
	file: TSFile
	sfc: SFC
	offset: number
	definePropsAst: CallExpression
	typeDeclRaw: TSType
	withDefaultsAst?: CallExpression
	defaultsDeclRaw?: DefaultsASTRaw
	statement: DefinePropsStatement
	declId?: LVal
}): ResultAsync$1<TSProps, TransformError<ErrorResolveTS | ErrorUnknownNode>>;
type Props = TSProps | undefined;
type DefinePropsStatement = VariableDeclaration | ExpressionStatement;
type DefaultsASTRaw = CallExpression["arguments"][number];
interface PropsBase {
	declId?: LVal;
	statementAst: DefinePropsStatement;
	definePropsAst: CallExpression;
	withDefaultsAst?: CallExpression;
}
interface TSPropsMethod {
	type: "method";
	methods: ASTDefinition<TSMethodSignature>[];
	optional: boolean;
}
interface TSPropsProperty {
	type: "property";
	value: ASTDefinition<TSResolvedType["type"]> | undefined;
	optional: boolean;
	signature: ASTDefinition<TSPropertySignature | TSMappedType>;
	/** Whether added by `addProp` API */
	addByAPI: boolean;
}
interface RuntimePropDefinition {
	type: string[];
	required: boolean;
	default?: (key?: string) => string;
}
interface TSProps extends PropsBase {
	kind: DefinitionKind.TS;
	definitions: Record<string | number, TSPropsMethod | TSPropsProperty>;
	definitionsAst: ASTDefinition<TSInterfaceDeclaration | TSTypeLiteral | TSIntersectionType | TSUnionType | TSMappedType | TSTypeReference>;
	/**
	* Default value of props.
	*
	* `undefined` if not defined or it's not a static expression that cannot be analyzed statically.
	*/
	defaults?: Record<string, ObjectMethod | ObjectProperty>;
	/**
	* `undefined` if not defined.
	*/
	defaultsAst?: Expression;
	/**
	* Adds a new prop to the definitions. `definitions` will updated after this call.
	*
	* Added definition cannot be set and removed again.
	*
	* @example addProp('foo', 'string ｜ boolean')
	*
	* @returns false if the definition already exists.
	*/
	addProp: (name: string | StringLiteral, type: string, optional?: boolean) => boolean;
	/**
	* Modify a definition of a prop. `definitions` will updated after this call.
	*
	* @limitation Cannot set the prop added by `addProp`.
	*
	* @example setProp('foo', 'string ｜ boolean')
	*
	* @returns false if the definition does not exist.
	*/
	setProp: (name: string | StringLiteral, type: string, optional?: boolean) => boolean;
	/**
	* Removes specified prop from TS interface. `definitions` will updated after this call.
	*
	* @limitation Cannot remove prop added by `addProp`. (it will be removed in definitions though)
	*
	* @returns `true` if prop was removed, `false` if prop was not found.
	*/
	removeProp: (name: string | StringLiteral) => boolean;
	/**
	* get runtime definitions.
	*/
	getRuntimeDefinitions: () => ResultAsync$1<Record<string, RuntimePropDefinition>, TransformError<ErrorUnknownNode>>;
}

interface AnalyzeResult {
	props: Props;
	emits: Emits;
}
declare function analyzeSFC(s: MagicStringAST, sfc: SFC): ResultAsync$1<AnalyzeResult, Error>;

declare const UNKNOWN_TYPE = "Unknown";
declare function inferRuntimeType(node: TSResolvedType | TSNamespace): ResultAsync$1<string[], TransformError<ErrorUnknownNode>>;
declare function attachNodeLoc(node: Node, newNode: Node): void;
declare function genRuntimePropDefinition(types: string[] | undefined, isProduction: boolean, properties: string[]): string;

export { DefinitionKind, UNKNOWN_TYPE, analyzeSFC, attachNodeLoc, checkForTSProperties, genRuntimePropDefinition, getTSFile, getTSPropertiesKeys, handleTSEmitsDefinition, handleTSPropsDefinition, inferRuntimeType, isSupportedForTSReferencedType, isTSDeclaration, isTSNamespace, mergeTSProperties, namespaceSymbol, resolveDts, resolveDtsHMR, resolveMaybeTSUnion, resolveTSIndexedAccessType, resolveTSLiteralType, resolveTSNamespace, resolveTSProperties, resolveTSReferencedType, resolveTSScope, resolveTSTemplateLiteral, resolveTSTypeOperator, resolveTypeElements, tsFileCache };
export type { ASTDefinition, AnalyzeResult, DefaultsASTRaw, DefineEmitsStatement, DefinePropsStatement, Emits, EmitsBase, Error, ErrorResolveTS, ErrorUnknownNode, ErrorVueSFC, ErrorWithDefaults, Props, PropsBase, ResultAsync, RuntimePropDefinition, TSDeclaration, TSEmits, TSFile, TSModule, TSNamespace, TSProperties, TSProps, TSPropsMethod, TSPropsProperty, TSResolvedType, TSScope, TSScopeBase };
