function main( context ) {
	var expressions;
	var prevAlias;

	expressions = [];

	/**
	* Extracts the alias value from a given node.
	*
	* @private
	* @param {ASTNode} node - node containing properties to search
	* @returns {string} alias value
	*/
	function getAlias( node ) {
		var props;
		var alias;
		var i;

		props = node.properties;
		for ( i = 0; i < props.length; i++ ) {
			if ( props[ i ].key.value === 'alias' ) {
				alias = props[ i ].value.value;
				if ( alias ) {
					return alias;
				}
			}
		}
	}

	/**
	* Compares two nodes and determines their order based on the alias property.
	*
	* @private
	* @param {ASTNode} a - first node
	* @param {ASTNode} b - second node
	* @returns {number} number indicating sort order
	*/
	function sortExpressions( a, b ) {
		var aliasA = getAlias( a.arguments[ 0 ] );
		var aliasB = getAlias( b.arguments[ 0 ] );
		return aliasA.localeCompare( aliasB, 'en', OPTS_COMPARE );
	}

	/**
	* Fixes the lint error by reordering the packages.
	*
	* @private
	* @param {Function} fixer - ESLint fixer
	* @returns {(Object|null)} fix or null
	*/
	function fix( fixer ) {
		var replacingText;
		var startRange;
		var endRange;
		var sorted;
		var source;
		var txt;
		var i;

		source = context.getSourceCode();
		replacingText = '';
		startRange = expressions[0].range[ 0 ];
		endRange = expressions[ expressions.length - 1 ].range[ 1 ];

		sorted = expressions.slice().sort( sortExpressions );

		for ( i = 0; i < sorted.length; i++ ) {
			txt = source.getText( sorted[ i ] );
			replacingText += txt;
			if ( i < sorted.length - 1 ) {
				replacingText += ';\n\n';
			}
		}
		return fixer.replaceTextRange( [ startRange, endRange ], replacingText ); // eslint-disable-line max-len
	}

	/**
	* Reports the error message.
	*
	* @private
	* @param {string} last - name of first package
	* @param {string} current - name of second package
	* @param {ASTNode} node - node to report
	*/
	function report( last, current, node ) {
		context.report({
			'node': node,
			'message': '"'+current+'" should come before "'+last+'"',
			'fix': fix
		});
	}

	/**
	* Checks whether the packages are added to a REPL namespace object in alphabetical order according to alias (namespace key).
	*
	* @private
	*/
	function validate() {
		var alias;
		var i;

		for ( i = 0; i < expressions.length; i++ ) {
			alias = getAlias( expressions[ i ].arguments[ 0 ] );
			if (
				prevAlias &&
				alias.localeCompare( prevAlias, 'en', OPTS_COMPARE ) < 0
			) {
				report( prevAlias, alias, expressions[ i ].arguments[ 0 ] );
			} else {
				prevAlias = alias;
			}
		}
	}

	/**
	* Collects all expressions which add a package to a REPL namespace.
	*
	* @private
	* @param {ASTNode} node - node to examine
	*/
	function collectExpressions( node ) {
		var object;
		var alias;

		if (
			node.callee.type === 'MemberExpression' &&
			node.callee.object.name === 'ns' &&
			node.callee.property.name === 'push'
		) {
			object = node.arguments[ 0 ];
			if ( object.type === 'ObjectExpression' ) {
				alias = getAlias( object );
				if ( alias ) {
					expressions.push( node );
				}
			}
		}
	}

	return {
		'CallExpression': collectExpressions,
		'Program:exit': validate
	};
}
Rule for validating that packages are added to a REPL namespace object in alphabetical order according to alias (namespace key).

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