function main( context ) {
	var options;
	var source;
	var order;

	options = context.options[ 0 ];
	order = DEFAULTS.order;
	if ( hasOwnProp( options, 'order' ) ) {
		order = options.order.slice();
	}
	source = context.getSourceCode();
	return {
		'FunctionExpression:exit': validate,
		'FunctionDeclaration:exit': validate,
		'VariableDeclaration:exit': validate,
		'ExpressionStatement:exit': validate
	};

	/**
	* Checks whether JSDoc tags follow a specified order.
	*
	* @private
	* @param {ASTNode} node - AST node
	*/
	function validate( node ) {
		var jsdoc;
		var curr;
		var prev;
		var tags;
		var ast;
		var i;

		jsdoc = findJSDoc( source, node );
		if ( isObject( jsdoc ) ) {
			ast = parseJSDoc( jsdoc.value, DOPTS );
			tags = ast.tags;
			if ( tags.length > 0 ) {
				prev = indexOf( order, tags[ 0 ].title );
				for ( i = 1; i < tags.length; i++ ) {
					curr = indexOf( order, tags[ i ].title );
					if ( curr !== -1 && prev !== -1 && curr < prev ) {
						report( order[ prev ], order[ curr ], jsdoc.loc );
					}
					prev = curr;
				}
			}
		}
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {string} last - name of last tag
	* @param {string} current - name of current tag
	* @param {Object} loc - lines of code (object with `start` and `end` properties)
	*/
	function report( last, current, loc ) {
		context.report({
			'node': null,
			'message': '"@'+current+'" tag should not follow "@'+last+'"',
			'loc': loc
		});
	}
}
Rule for validating that JSDoc tags follow a specified order.

@param {Object} context - ESLint context
@returns {Object} validators