"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _iterateJsdoc = _interopRequireDefault(require("../iterateJsdoc.cjs"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var _default = exports.default = (0, _iterateJsdoc.default)(({
  context,
  jsdoc,
  utils
}) => {
  const {
    allowMultipleTags = true,
    minimumLengthForMultiline = Number.POSITIVE_INFINITY,
    multilineTags = ['*'],
    noFinalLineText = true,
    noMultilineBlocks = false,
    noSingleLineBlocks = false,
    noZeroLineText = true,
    singleLineTags = ['lends', 'type']
  } = context.options[0] || {};
  const {
    source: [{
      tokens
    }]
  } = jsdoc;
  const {
    description,
    tag
  } = tokens;
  const sourceLength = jsdoc.source.length;

  /**
   * @param {string} tagName
   * @returns {boolean}
   */
  const isInvalidSingleLine = tagName => {
    return noSingleLineBlocks && (!tagName || !singleLineTags.includes(tagName) && !singleLineTags.includes('*'));
  };
  if (sourceLength === 1) {
    if (!isInvalidSingleLine(tag.slice(1))) {
      return;
    }
    const fixer = () => {
      utils.makeMultiline();
    };
    utils.reportJSDoc('Single line blocks are not permitted by your configuration.', null, fixer, true);
    return;
  }
  const lineChecks = () => {
    if (noZeroLineText && (tag || description)) {
      const fixer = () => {
        const line = {
          ...tokens
        };
        utils.emptyTokens(tokens);
        const {
          tokens: {
            delimiter,
            start
          }
        } = jsdoc.source[1];
        utils.addLine(1, {
          ...line,
          delimiter,
          start
        });
      };
      utils.reportJSDoc('Should have no text on the "0th" line (after the `/**`).', null, fixer);
      return;
    }
    const finalLine = jsdoc.source[jsdoc.source.length - 1];
    const finalLineTokens = finalLine.tokens;
    if (noFinalLineText && finalLineTokens.description.trim()) {
      const fixer = () => {
        const line = {
          ...finalLineTokens
        };
        line.description = line.description.trimEnd();
        const {
          delimiter
        } = line;
        for (const prop of ['delimiter', 'postDelimiter', 'tag', 'type', 'lineEnd', 'postType', 'postTag', 'name', 'postName', 'description']) {
          finalLineTokens[(
          /**
           * @type {"delimiter"|"postDelimiter"|"tag"|"type"|
           *   "lineEnd"|"postType"|"postTag"|"name"|
           *   "postName"|"description"}
           */
          prop)] = '';
        }
        utils.addLine(jsdoc.source.length - 1, {
          ...line,
          delimiter,
          end: ''
        });
      };
      utils.reportJSDoc('Should have no text on the final line (before the `*/`).', null, fixer);
    }
  };
  if (noMultilineBlocks) {
    if (jsdoc.tags.length && (multilineTags.includes('*') || utils.hasATag(multilineTags))) {
      lineChecks();
      return;
    }
    if (jsdoc.description.length >= minimumLengthForMultiline) {
      lineChecks();
      return;
    }
    if (noSingleLineBlocks && (!jsdoc.tags.length || !utils.filterTags(({
      tag: tg
    }) => {
      return !isInvalidSingleLine(tg);
    }).length)) {
      utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but fixing would result in a single ' + 'line block which you have prohibited with `noSingleLineBlocks`.');
      return;
    }
    if (jsdoc.tags.length > 1) {
      if (!allowMultipleTags) {
        utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has multiple tags.');
        return;
      }
    } else if (jsdoc.tags.length === 1 && jsdoc.description.trim()) {
      if (!allowMultipleTags) {
        utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration but the block has a description with a tag.');
        return;
      }
    } else {
      const fixer = () => {
        jsdoc.source = [{
          number: 1,
          source: '',
          tokens: jsdoc.source.reduce((obj, {
            tokens: {
              description: desc,
              lineEnd,
              name: nme,
              postName,
              postTag,
              postType,
              tag: tg,
              type: typ
            }
          }) => {
            if (typ) {
              obj.type = typ;
            }
            if (tg && typ && nme) {
              obj.postType = postType;
            }
            if (nme) {
              obj.name += nme;
            }
            if (nme && desc) {
              obj.postName = postName;
            }
            obj.description += desc;
            const nameOrDescription = obj.description || obj.name;
            if (nameOrDescription && nameOrDescription.slice(-1) !== ' ') {
              obj.description += ' ';
            }
            obj.lineEnd = lineEnd;

            // Already filtered for multiple tags
            obj.tag += tg;
            if (tg) {
              obj.postTag = postTag || ' ';
            }
            return obj;
          }, utils.seedTokens({
            delimiter: '/**',
            end: '*/',
            postDelimiter: ' '
          }))
        }];
      };
      utils.reportJSDoc('Multiline jsdoc blocks are prohibited by ' + 'your configuration.', null, fixer);
      return;
    }
  }
  lineChecks();
}, {
  iterateAllJsdocs: true,
  meta: {
    docs: {
      description: 'Controls how and whether jsdoc blocks can be expressed as single or multiple line blocks.',
      url: 'https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/multiline-blocks.md#repos-sticky-header'
    },
    fixable: 'code',
    schema: [{
      additionalProperties: false,
      properties: {
        allowMultipleTags: {
          type: 'boolean'
        },
        minimumLengthForMultiline: {
          type: 'integer'
        },
        multilineTags: {
          anyOf: [{
            enum: ['*'],
            type: 'string'
          }, {
            items: {
              type: 'string'
            },
            type: 'array'
          }]
        },
        noFinalLineText: {
          type: 'boolean'
        },
        noMultilineBlocks: {
          type: 'boolean'
        },
        noSingleLineBlocks: {
          type: 'boolean'
        },
        noZeroLineText: {
          type: 'boolean'
        },
        singleLineTags: {
          items: {
            type: 'string'
          },
          type: 'array'
        }
      },
      type: 'object'
    }],
    type: 'suggestion'
  }
});
module.exports = exports.default;
//# sourceMappingURL=multilineBlocks.cjs.map