"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.InheritDocPlugin = void 0;
const models_1 = require("../../models");
const components_1 = require("../components");
const converter_1 = require("../converter");
const reflections_1 = require("../utils/reflections");
const abstract_1 = require("../../models/reflections/abstract");
/**
 * A plugin that handles `inheritDoc` by copying documentation from another API item.
 *
 * What gets copied:
 * - short text
 * - text
 * - `@remarks` block
 * - `@params` block
 * - `@typeParam` block
 * - `@return` block
 */
let InheritDocPlugin = class InheritDocPlugin extends components_1.ConverterComponent {
    /**
     * Create a new InheritDocPlugin instance.
     */
    initialize() {
        this.listenTo(this.owner, {
            [converter_1.Converter.EVENT_RESOLVE]: this.onResolve,
        }, undefined, -200);
    }
    /**
     * Triggered when the converter resolves a reflection.
     *
     * Traverse through reflection descendant to check for `inheritDoc` tag.
     * If encountered, the parameter of the tag iss used to determine a source reflection
     * that will provide actual comment.
     *
     * @param context  The context object describing the current state the converter is in.
     * @param reflection  The reflection that is currently resolved.
     */
    onResolve(_context, reflection) {
        if (reflection instanceof models_1.ContainerReflection) {
            const descendantsCallback = (item) => {
                var _a, _b, _c, _d, _e;
                item.traverse(descendantsCallback);
                const inheritDoc = (_b = (_a = item.comment) === null || _a === void 0 ? void 0 : _a.getTag("inheritdoc")) === null || _b === void 0 ? void 0 : _b.paramName;
                const source = inheritDoc && reflection.findReflectionByName(inheritDoc);
                let referencedReflection = source;
                if (source instanceof models_1.DeclarationReflection &&
                    item instanceof models_1.SignatureReflection) {
                    const isFunction = source.kindOf(models_1.ReflectionKind.FunctionOrMethod);
                    if (isFunction) {
                        // Assumes that if there are overloads, they are declared in the same order as the parent.
                        // TS doesn't check this, but if a user messes this up then they are almost
                        // guaranteed to run into bugs where they can't call a method on a child class
                        // but if they assign (without a type assertion) that child to a variable of the parent class
                        // then they can call the method.
                        const itemIndex = (_d = (_c = item.parent.signatures) === null || _c === void 0 ? void 0 : _c.indexOf(item)) !== null && _d !== void 0 ? _d : 0;
                        referencedReflection = (_e = source.signatures) === null || _e === void 0 ? void 0 : _e[itemIndex];
                    }
                }
                if (referencedReflection instanceof abstract_1.Reflection) {
                    (0, reflections_1.copyComment)(item, referencedReflection);
                }
                return true;
            };
            reflection.traverse(descendantsCallback);
        }
    }
};
InheritDocPlugin = __decorate([
    (0, components_1.Component)({ name: "inheritDoc" })
], InheritDocPlugin);
exports.InheritDocPlugin = InheritDocPlugin;
