You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							151 lines
						
					
					
						
							4.9 KiB
						
					
					
				
			
		
		
	
	
							151 lines
						
					
					
						
							4.9 KiB
						
					
					
				/** | 
						|
 * @fileoverview Rule to enforce consistent naming of "this" context variables | 
						|
 * @author Raphael Pigulla | 
						|
 */ | 
						|
"use strict"; | 
						|
 | 
						|
//------------------------------------------------------------------------------ | 
						|
// Rule Definition | 
						|
//------------------------------------------------------------------------------ | 
						|
 | 
						|
module.exports = { | 
						|
    meta: { | 
						|
        type: "suggestion", | 
						|
 | 
						|
        docs: { | 
						|
            description: "enforce consistent naming when capturing the current execution context", | 
						|
            category: "Stylistic Issues", | 
						|
            recommended: false, | 
						|
            url: "https://eslint.org/docs/rules/consistent-this" | 
						|
        }, | 
						|
 | 
						|
        schema: { | 
						|
            type: "array", | 
						|
            items: { | 
						|
                type: "string", | 
						|
                minLength: 1 | 
						|
            }, | 
						|
            uniqueItems: true | 
						|
        }, | 
						|
 | 
						|
        messages: { | 
						|
            aliasNotAssignedToThis: "Designated alias '{{name}}' is not assigned to 'this'.", | 
						|
            unexpectedAlias: "Unexpected alias '{{name}}' for 'this'." | 
						|
        } | 
						|
    }, | 
						|
 | 
						|
    create(context) { | 
						|
        let aliases = []; | 
						|
 | 
						|
        if (context.options.length === 0) { | 
						|
            aliases.push("that"); | 
						|
        } else { | 
						|
            aliases = context.options; | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Reports that a variable declarator or assignment expression is assigning | 
						|
         * a non-'this' value to the specified alias. | 
						|
         * @param {ASTNode} node The assigning node. | 
						|
         * @param {string}  name the name of the alias that was incorrectly used. | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function reportBadAssignment(node, name) { | 
						|
            context.report({ node, messageId: "aliasNotAssignedToThis", data: { name } }); | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Checks that an assignment to an identifier only assigns 'this' to the | 
						|
         * appropriate alias, and the alias is only assigned to 'this'. | 
						|
         * @param {ASTNode} node The assigning node. | 
						|
         * @param {Identifier} name The name of the variable assigned to. | 
						|
         * @param {Expression} value The value of the assignment. | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkAssignment(node, name, value) { | 
						|
            const isThis = value.type === "ThisExpression"; | 
						|
 | 
						|
            if (aliases.indexOf(name) !== -1) { | 
						|
                if (!isThis || node.operator && node.operator !== "=") { | 
						|
                    reportBadAssignment(node, name); | 
						|
                } | 
						|
            } else if (isThis) { | 
						|
                context.report({ node, messageId: "unexpectedAlias", data: { name } }); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Ensures that a variable declaration of the alias in a program or function | 
						|
         * is assigned to the correct value. | 
						|
         * @param {string} alias alias the check the assignment of. | 
						|
         * @param {Object} scope scope of the current code we are checking. | 
						|
         * @private | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function checkWasAssigned(alias, scope) { | 
						|
            const variable = scope.set.get(alias); | 
						|
 | 
						|
            if (!variable) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            if (variable.defs.some(def => def.node.type === "VariableDeclarator" && | 
						|
                def.node.init !== null)) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            /* | 
						|
             * The alias has been declared and not assigned: check it was | 
						|
             * assigned later in the same scope. | 
						|
             */ | 
						|
            if (!variable.references.some(reference => { | 
						|
                const write = reference.writeExpr; | 
						|
 | 
						|
                return ( | 
						|
                    reference.from === scope && | 
						|
                    write && write.type === "ThisExpression" && | 
						|
                    write.parent.operator === "=" | 
						|
                ); | 
						|
            })) { | 
						|
                variable.defs.map(def => def.node).forEach(node => { | 
						|
                    reportBadAssignment(node, alias); | 
						|
                }); | 
						|
            } | 
						|
        } | 
						|
 | 
						|
        /** | 
						|
         * Check each alias to ensure that is was assinged to the correct value. | 
						|
         * @returns {void} | 
						|
         */ | 
						|
        function ensureWasAssigned() { | 
						|
            const scope = context.getScope(); | 
						|
 | 
						|
            aliases.forEach(alias => { | 
						|
                checkWasAssigned(alias, scope); | 
						|
            }); | 
						|
        } | 
						|
 | 
						|
        return { | 
						|
            "Program:exit": ensureWasAssigned, | 
						|
            "FunctionExpression:exit": ensureWasAssigned, | 
						|
            "FunctionDeclaration:exit": ensureWasAssigned, | 
						|
 | 
						|
            VariableDeclarator(node) { | 
						|
                const id = node.id; | 
						|
                const isDestructuring = | 
						|
                    id.type === "ArrayPattern" || id.type === "ObjectPattern"; | 
						|
 | 
						|
                if (node.init !== null && !isDestructuring) { | 
						|
                    checkAssignment(node, id.name, node.init); | 
						|
                } | 
						|
            }, | 
						|
 | 
						|
            AssignmentExpression(node) { | 
						|
                if (node.left.type === "Identifier") { | 
						|
                    checkAssignment(node, node.left.name, node.right); | 
						|
                } | 
						|
            } | 
						|
        }; | 
						|
 | 
						|
    } | 
						|
};
 | 
						|
 |