"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const common_utils_1 = require("../utils/common/common.utils");
const formatting_utils_1 = require("../utils/formatting/formatting.utils");
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
const MAX_CONTENT_WIDTH = 70;
const MAX_PROPERTIES_IN_SINGLE_LINE = 3;
const MAX_ARRAY_PROPERTIES_IN_SINGLE_LINE = 1;
const MAX_CHILD_OBJECT_PROPERTIES_IN_SINGLE_LINE = 0;
const MAX_CHILD_CALL_EXPRESSION_LENGTH = 20;
const MAX_COUNT_CALL_EXPRESSION_IN_SINGLE_LINE = 1;
var ERROR_TYPE;
(function (ERROR_TYPE) {
    ERROR_TYPE["CONTENT_WIDTH"] = "content-width";
    ERROR_TYPE["COUNT_PROPERTIES"] = "count-properties";
    ERROR_TYPE["COUNT_CALL_EXPRESSIONS"] = "count-call-expressions";
    ERROR_TYPE["FUNCTION_LENGTH"] = "function-length";
    ERROR_TYPE["COUNT_NESTED_OBJECT_PROPERTIES"] = "count-nested-object-properties";
    ERROR_TYPE["COUNT_NESTED_ARRAY_ELEMENTS"] = "count-nested-array-properties";
    ERROR_TYPE["NO_MULTILINE"] = "no-multiline";
})(ERROR_TYPE = exports.ERROR_TYPE || (exports.ERROR_TYPE = {}));
const SINGLE_LINE_ERRORS = {
    [ERROR_TYPE.CONTENT_WIDTH]: `content width of object is more than ${MAX_CONTENT_WIDTH}.`,
    [ERROR_TYPE.COUNT_PROPERTIES]: `an object in single line must contain not more than\
     ${MAX_PROPERTIES_IN_SINGLE_LINE} properties.`,
    [ERROR_TYPE.COUNT_CALL_EXPRESSIONS]: `an object in single line must contain not more than\
     ${MAX_COUNT_CALL_EXPRESSION_IN_SINGLE_LINE} call expressions.`,
    [ERROR_TYPE.FUNCTION_LENGTH]: `an object in single line can contain a function no longer than\
     ${MAX_CHILD_CALL_EXPRESSION_LENGTH} characters.`,
    [ERROR_TYPE.COUNT_NESTED_OBJECT_PROPERTIES]: `an object in single line can contain an object with the number of\
     properties not more than ${MAX_CHILD_OBJECT_PROPERTIES_IN_SINGLE_LINE}.`,
    [ERROR_TYPE.COUNT_NESTED_ARRAY_ELEMENTS]: `an object in single line can contain an array with the number of\
     properties not more than ${MAX_ARRAY_PROPERTIES_IN_SINGLE_LINE}.`
};
const MULTI_LINE_ERRORS = {
    [ERROR_TYPE.NO_MULTILINE]: 'the object can be written in one line.'
};
exports.default = {
    meta: {
        type: 'layout',
        docs: {
            description: 'object literal property carrying rules',
            category: 'Stylistic Issues',
            recommended: 'error'
        },
        messages: {
            [ERROR_TYPE.CONTENT_WIDTH]: SINGLE_LINE_ERRORS[ERROR_TYPE.CONTENT_WIDTH],
            [ERROR_TYPE.COUNT_PROPERTIES]: SINGLE_LINE_ERRORS[ERROR_TYPE.COUNT_PROPERTIES],
            [ERROR_TYPE.COUNT_CALL_EXPRESSIONS]: SINGLE_LINE_ERRORS[ERROR_TYPE.COUNT_CALL_EXPRESSIONS],
            [ERROR_TYPE.FUNCTION_LENGTH]: SINGLE_LINE_ERRORS[ERROR_TYPE.FUNCTION_LENGTH],
            [ERROR_TYPE.COUNT_NESTED_OBJECT_PROPERTIES]: SINGLE_LINE_ERRORS[ERROR_TYPE.COUNT_NESTED_OBJECT_PROPERTIES],
            [ERROR_TYPE.COUNT_NESTED_ARRAY_ELEMENTS]: SINGLE_LINE_ERRORS[ERROR_TYPE.COUNT_NESTED_ARRAY_ELEMENTS],
            [ERROR_TYPE.NO_MULTILINE]: MULTI_LINE_ERRORS[ERROR_TYPE.NO_MULTILINE]
        }
    },
    create(context) {
        return {
            ObjectExpression(node) {
                if (!isDesiredObject(context)) {
                    return;
                }
                const isSingleLine = common_utils_1.CommonUtils.isSingleLine(node);
                let messages = checkLiteralAsSingleLine(context, node);
                if (!isSingleLine) {
                    messages = !messages.length ? [ERROR_TYPE.NO_MULTILINE] : [];
                }
                report(context, node, messages);
            }
        };
    }
};
// Not a part of call expression
function isDesiredObject(context) {
    const ignoredParentTypes = [experimental_utils_1.AST_NODE_TYPES.CallExpression];
    const approvedParentTypes = [experimental_utils_1.AST_NODE_TYPES.AssignmentExpression, experimental_utils_1.AST_NODE_TYPES.VariableDeclarator];
    const approvedParentIndex = getClosestByTypes(context, approvedParentTypes);
    const ignoredParentIndex = getClosestByTypes(context, ignoredParentTypes);
    return approvedParentIndex < ignoredParentIndex;
}
function getClosestByTypes(context, types) {
    const NOT_FOUND_INDEX = -1;
    const parentPositions = types.map(type => common_utils_1.CommonUtils.findIndexParentByType(context, type))
        .filter(index => NOT_FOUND_INDEX < index);
    return Math.min(...parentPositions);
}
function checkLiteralAsSingleLine(context, node) {
    const messages = [];
    messages.push(...checkCommonRules(context, node));
    const nestedNodes = node.properties.map(prop => {
        return prop.type !== experimental_utils_1.AST_NODE_TYPES.SpreadElement ? prop.value : undefined;
    })
        .filter(nestedNode => Boolean(nestedNode));
    messages.push(checkArrayExpressionInObject(nestedNodes));
    messages.push(...checkFunctionsInObject(nestedNodes));
    messages.push(checkObjectInObject(nestedNodes));
    return messages.filter(message => Boolean(message));
}
function checkCommonRules(context, node) {
    const messages = [];
    if (MAX_CONTENT_WIDTH < formatting_utils_1.FormattingUtils.nodeToSingleLineText(context, node).length) {
        messages.push(ERROR_TYPE.CONTENT_WIDTH);
    }
    if (MAX_PROPERTIES_IN_SINGLE_LINE < node.properties.length) {
        messages.push(ERROR_TYPE.COUNT_PROPERTIES);
    }
    return messages;
}
function checkArrayExpressionInObject(nodes) {
    const arrayExpressions = nodes.filter(nestedNode => {
        return nestedNode.type === experimental_utils_1.AST_NODE_TYPES.ArrayExpression;
    });
    if (arrayExpressions.some(array => MAX_ARRAY_PROPERTIES_IN_SINGLE_LINE < array.elements.length)) {
        return ERROR_TYPE.COUNT_NESTED_ARRAY_ELEMENTS;
    }
}
function checkFunctionsInObject(nodes) {
    const functionExpressions = [experimental_utils_1.AST_NODE_TYPES.ArrowFunctionExpression, experimental_utils_1.AST_NODE_TYPES.CallExpression];
    const callExpressions = nodes.filter(nestedNode => functionExpressions.includes(nestedNode.type));
    const messages = [];
    if (MAX_COUNT_CALL_EXPRESSION_IN_SINGLE_LINE < callExpressions.length) {
        messages.push(ERROR_TYPE.COUNT_CALL_EXPRESSIONS);
    }
    const functionLengths = callExpressions.map(expressionNode => common_utils_1.CommonUtils.getContentLength(expressionNode));
    if (functionLengths.some(length => MAX_CHILD_CALL_EXPRESSION_LENGTH < length)) {
        messages.push(ERROR_TYPE.FUNCTION_LENGTH);
    }
    return messages;
}
function checkObjectInObject(nodes) {
    const objectExpressions = nodes.filter(nestedNode => {
        return nestedNode.type === experimental_utils_1.AST_NODE_TYPES.ObjectExpression;
    });
    if (objectExpressions.some(objectNode => Boolean(objectNode.properties.length))) {
        return ERROR_TYPE.COUNT_NESTED_OBJECT_PROPERTIES;
    }
}
function report(context, node, messages) {
    messages.forEach(message => context.report({ messageId: message, node }));
}
//# sourceMappingURL=object-properties-carrying.js.map