'use strict';

/* eslint "complexity": [ "error", 5 ] */

const createAstUtils = require('../util/ast');

module.exports = {
    meta: {
        type: 'problem',
        docs: {
            description: 'Disallow tests to be nested within other tests '
        }
    },
    create(context) {
        const astUtils = createAstUtils(context.settings);
        let testNestingLevel = 0;
        let hookCallNestingLevel = 0;

        function report(callExpression, message) {
            context.report({
                message,
                node: callExpression.callee
            });
        }

        function isNestedTest(isTestCase, isDescribe, nestingLevel) {
            const isNested = nestingLevel > 0;
            const isTest = isTestCase || isDescribe;

            return isNested && isTest;
        }

        function checkForAndReportErrors(
            node,
            isTestCase,
            isDescribe,
            isHookCall
        ) {
            if (isNestedTest(isTestCase, isDescribe, testNestingLevel)) {
                const message = isDescribe ?
                    'Unexpected suite nested within a test.' :
                    'Unexpected test nested within another test.';
                report(node, message);
            } else if (
                isNestedTest(isTestCase, isHookCall, hookCallNestingLevel)
            ) {
                const message = isHookCall ?
                    'Unexpected test hook nested within a test hook.' :
                    'Unexpected test nested within a test hook.';
                report(node, message);
            }
        }

        return {
            CallExpression(node) {
                const isTestCase = astUtils.isTestCase(node);
                const isHookCall = astUtils.isHookCall(node);
                const isDescribe = astUtils.isDescribe(node);

                checkForAndReportErrors(
                    node,
                    isTestCase,
                    isDescribe,
                    isHookCall
                );

                if (isTestCase) {
                    testNestingLevel += 1;
                } else if (isHookCall) {
                    hookCallNestingLevel += 1;
                }
            },

            'CallExpression:exit'(node) {
                if (astUtils.isTestCase(node)) {
                    testNestingLevel -= 1;
                } else if (astUtils.isHookCall(node)) {
                    hookCallNestingLevel -= 1;
                }
            }
        };
    }
};

@@ -415,16 +415,142 @@
 vel = 0;
+%0A        const isTestCase = astUtils.buildIsTestCaseAnswerer();%0A        const isDescribe = astUtils.buildIsDescribeAnswerer();
 %0A%0A      
@@ -741,32 +741,33 @@
 on isNestedTest(
+_
 isTestCase, isDe
@@ -754,32 +754,33 @@
 st(_isTestCase, 
+_
 isDescribe, nest
@@ -865,16 +865,17 @@
 sTest = 
+_
 isTestCa
@@ -880,16 +880,17 @@
 Case %7C%7C 
+_
 isDescri
@@ -1008,32 +1008,33 @@
 de,%0A            
+_
 isTestCase,%0A    
@@ -1033,32 +1033,33 @@
 se,%0A            
+_
 isDescribe,%0A    
@@ -1110,32 +1110,33 @@
 f (isNestedTest(
+_
 isTestCase, isDe
@@ -1131,16 +1131,17 @@
 stCase, 
+_
 isDescri
@@ -1197,16 +1197,17 @@
 ssage = 
+_
 isDescri
@@ -1433,16 +1433,17 @@
 tedTest(
+_
 isTestCa
@@ -1809,32 +1809,33 @@
           const 
+_
 isTestCase = ast
@@ -1831,25 +1831,16 @@
 tCase = 
-astUtils.
 isTestCa
@@ -1925,32 +1925,33 @@
           const 
+_
 isDescribe = ast
@@ -1947,25 +1947,16 @@
 cribe = 
-astUtils.
 isDescri
@@ -2053,16 +2053,17 @@
         
+_
 isTestCa
@@ -2086,16 +2086,17 @@
         
+_
 isDescri
@@ -2170,16 +2170,17 @@
     if (
+_
 isTestCa
@@ -2412,25 +2412,16 @@
     if (
-astUtils.
 isTestCa

Improve no-nested-tests performance