function removeTag()

in src/rules/noRedundantJsdoc2Rule.ts [134:200]


function removeTag(tag: ts.JSDocTag, sourceFile: ts.SourceFile): Lint.Replacement | undefined {
    const { text } = sourceFile;
    const jsdoc = tag.parent;
    if (jsdoc.kind === ts.SyntaxKind.JSDocTypeLiteral) {
        return undefined;
    }

    if (jsdoc.comment === undefined && jsdoc.tags!.length === 1) {
        // This is the only tag -- remove the whole comment
        return Lint.Replacement.deleteFromTo(jsdoc.getStart(sourceFile), jsdoc.getEnd());
    }

    let start = tag.getStart(sourceFile);
    assert(text[start] === "@");
    start--;
    while (ts.isWhiteSpaceSingleLine(text.charCodeAt(start))) {
        start--;
    }
    if (text[start] !== "*") {
        return undefined;
    }

    let end = tag.getEnd();

    // For some tags, like `@param`, `end` will be the start of the next tag.
    // For some tags, like `@name`, `end` will be before the start of the comment.
    // And `@typedef` doesn't end until the last `@property` tag attached to it ends.
    switch (tag.tagName.text) {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore (fallthrough)
        case "param": {
            const { isBracketed, isNameFirst, typeExpression } = tag as ts.JSDocParameterTag;
            if (!isBracketed && !(isNameFirst && typeExpression !== undefined)) {
                break;
            }
            // falls through
        }
        // eslint-disable-next-line no-fallthrough
        case "name":
        case "return":
        case "returns":
        case "interface":
        case "default":
        case "memberof":
        case "memberOf":
        case "method":
        case "type":
        case "class":
        case "property":
        case "function":
            end--; // Might end with "\n" (test with just `@return` with no comment or type)
            // For some reason, for "@name", "end" is before the start of the comment part of the tag.
            // Also for "param" if the name is optional  as in `@param {number} [x]`
            while (!ts.isLineBreak(text.charCodeAt(end))) {
                end++;
            }
            end++;
    }
    while (ts.isWhiteSpaceSingleLine(text.charCodeAt(end))) {
        end++;
    }
    if (text[end] !== "*") {
        return undefined;
    }

    return Lint.Replacement.deleteFromTo(start, end);
}