import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";
import { arrayJoin, isDefined, keyIn } from "ts-extras";
/**
 * Whether an identifier belongs to an import/export specifier position.
 */
export const isImportOrExportSpecifier = (parent) => parent?.type === "ExportSpecifier" ||
    parent?.type === "ImportDefaultSpecifier" ||
    parent?.type === "ImportNamespaceSpecifier" ||
    parent?.type === "ImportSpecifier";
/**
 * Whether an identifier is the declaration identifier for supported node types.
 */
export const isDeclarationIdentifier = (node) => {
    const { parent } = node;
    if (parent === undefined) {
        return false;
    }
    if (parent.type === "TSInterfaceDeclaration" ||
        parent.type === "TSTypeAliasDeclaration") {
        return parent.id === node;
    }
    if (parent.type === "ClassDeclaration" ||
        parent.type === "FunctionDeclaration" ||
        parent.type === "TSDeclareFunction" ||
        parent.type === "TSEnumDeclaration") {
        return parent.id === node;
    }
    if (parent.type === "VariableDeclarator") {
        return parent.id === node;
    }
    return false;
};
const normalizeTagComment = (text) => {
    if (!isDefined(text)) {
        return undefined;
    }
    if (typeof text === "string") {
        const normalized = text.trim().replaceAll(/\s+/gu, " ");
        return normalized.length > 0 ? normalized : undefined;
    }
    const normalized = arrayJoin(text.map((part) => part.text), "")
        .replaceAll(/\s+/gu, " ")
        .trim();
    return normalized.length > 0 ? normalized : undefined;
};
const isUnknownRecord = (value) => typeof value === "object" && value !== null;
const isSymbolWithJsDocTags = (symbol) => {
    if (!isUnknownRecord(symbol)) {
        return false;
    }
    if (!keyIn(symbol, "getJsDocTags")) {
        return false;
    }
    return typeof symbol["getJsDocTags"] === "function";
};
/**
 * Collect normalized comment payloads for a specific JSDoc tag name.
 */
export const getJsDocTagComments = (symbol, checker, tagName) => {
    if (!isSymbolWithJsDocTags(symbol)) {
        return [];
    }
    const tags = symbol.getJsDocTags();
    const resolvedTags = tags.length > 0 ? tags : symbol.getJsDocTags(checker);
    return resolvedTags
        .filter((tag) => tag.name === tagName)
        .map((tag) => normalizeTagComment(tag.text));
};
/**
 * Return true when text matches any compiled regex pattern.
 */
export const matchesAnyPattern = (text, patterns) => patterns.some((pattern) => pattern.test(text));
/**
 * Resolve the symbol at identifier location, falling back to constrained type.
 */
export const getIdentifierSymbol = (parserServices, node) => {
    const symbolFromLocation = parserServices.getSymbolAtLocation(node);
    if (isDefined(symbolFromLocation)) {
        return symbolFromLocation;
    }
    return getConstrainedTypeAtLocation(parserServices, node).getSymbol();
};
//# sourceMappingURL=symbol-usage.js.map