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.

177 lines
22 KiB

2 years ago
'use strict';
var _minimatch = require('minimatch');var _minimatch2 = _interopRequireDefault(_minimatch);
var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}} /**
* @fileoverview Rule to disallow namespace import
* @author Radek Benkel
*/ //------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
module.exports = {
meta: {
type: 'suggestion',
docs: {
url: (0, _docsUrl2['default'])('no-namespace') },
fixable: 'code',
schema: [{
type: 'object',
properties: {
ignore: {
type: 'array',
items: {
type: 'string' },
uniqueItems: true } } }] },
create: function () {function create(context) {
var firstOption = context.options[0] || {};
var ignoreGlobs = firstOption.ignore;
return {
ImportNamespaceSpecifier: function () {function ImportNamespaceSpecifier(node) {
if (ignoreGlobs && ignoreGlobs.find(function (glob) {return (0, _minimatch2['default'])(node.parent.source.value, glob, { matchBase: true });})) {
return;
}
var scopeVariables = context.getScope().variables;
var namespaceVariable = scopeVariables.find(function (variable) {return variable.defs[0].node === node;});
var namespaceReferences = namespaceVariable.references;
var namespaceIdentifiers = namespaceReferences.map(function (reference) {return reference.identifier;});
var canFix = namespaceIdentifiers.length > 0 && !usesNamespaceAsObject(namespaceIdentifiers);
context.report({
node: node,
message: 'Unexpected namespace import.',
fix: canFix && function (fixer) {
var scopeManager = context.getSourceCode().scopeManager;
var fixes = [];
// Pass 1: Collect variable names that are already in scope for each reference we want
// to transform, so that we can be sure that we choose non-conflicting import names
var importNameConflicts = {};
namespaceIdentifiers.forEach(function (identifier) {
var parent = identifier.parent;
if (parent && parent.type === 'MemberExpression') {
var importName = getMemberPropertyName(parent);
var localConflicts = getVariableNamesInScope(scopeManager, parent);
if (!importNameConflicts[importName]) {
importNameConflicts[importName] = localConflicts;
} else {
localConflicts.forEach(function (c) {return importNameConflicts[importName].add(c);});
}
}
});
// Choose new names for each import
var importNames = Object.keys(importNameConflicts);
var importLocalNames = generateLocalNames(
importNames,
importNameConflicts,
namespaceVariable.name);
// Replace the ImportNamespaceSpecifier with a list of ImportSpecifiers
var namedImportSpecifiers = importNames.map(function (importName) {return (
importName === importLocalNames[importName] ?
importName : String(
importName) + ' as ' + String(importLocalNames[importName]));});
fixes.push(fixer.replaceText(node, '{ ' + String(namedImportSpecifiers.join(', ')) + ' }'));
// Pass 2: Replace references to the namespace with references to the named imports
namespaceIdentifiers.forEach(function (identifier) {
var parent = identifier.parent;
if (parent && parent.type === 'MemberExpression') {
var importName = getMemberPropertyName(parent);
fixes.push(fixer.replaceText(parent, importLocalNames[importName]));
}
});
return fixes;
} });
}return ImportNamespaceSpecifier;}() };
}return create;}() };
/**
* @param {Identifier[]} namespaceIdentifiers
* @returns {boolean} `true` if the namespace variable is more than just a glorified constant
*/
function usesNamespaceAsObject(namespaceIdentifiers) {
return !namespaceIdentifiers.every(function (identifier) {
var parent = identifier.parent;
// `namespace.x` or `namespace['x']`
return (
parent && parent.type === 'MemberExpression' && (
parent.property.type === 'Identifier' || parent.property.type === 'Literal'));
});
}
/**
* @param {MemberExpression} memberExpression
* @returns {string} the name of the member in the object expression, e.g. the `x` in `namespace.x`
*/
function getMemberPropertyName(memberExpression) {
return memberExpression.property.type === 'Identifier' ?
memberExpression.property.name :
memberExpression.property.value;
}
/**
* @param {ScopeManager} scopeManager
* @param {ASTNode} node
* @return {Set<string>}
*/
function getVariableNamesInScope(scopeManager, node) {
var currentNode = node;
var scope = scopeManager.acquire(currentNode);
while (scope == null) {
currentNode = currentNode.parent;
scope = scopeManager.acquire(currentNode, true);
}
return new Set([].concat(_toConsumableArray(
scope.variables.map(function (variable) {return variable.name;})), _toConsumableArray(
scope.upper.variables.map(function (variable) {return variable.name;}))));
}
/**
*
* @param {*} names
* @param {*} nameConflicts
* @param {*} namespaceName
*/
function generateLocalNames(names, nameConflicts, namespaceName) {
var localNames = {};
names.forEach(function (name) {
var localName = void 0;
if (!nameConflicts[name].has(name)) {
localName = name;
} else if (!nameConflicts[name].has(String(namespaceName) + '_' + String(name))) {
localName = String(namespaceName) + '_' + String(name);
} else {
for (var i = 1; i < Infinity; i++) {
if (!nameConflicts[name].has(String(namespaceName) + '_' + String(name) + '_' + String(i))) {
localName = String(namespaceName) + '_' + String(name) + '_' + String(i);
break;
}
}
}
localNames[name] = localName;
});
return localNames;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby1uYW1lc3BhY2UuanMiXSwibmFtZXMiOlsibW9kdWxlIiwiZXhwb3J0cyIsIm1ldGEiLCJ0eXBlIiwiZG9jcyIsInVybCIsImZpeGFibGUiLCJzY2hlbWEiLCJwcm9wZXJ0aWVzIiwiaWdub3JlIiwiaXRlbXMiLCJ1bmlxdWVJdGVtcyIsImNyZWF0ZSIsImNvbnRleHQiLCJmaXJzdE9wdGlvbiIsIm9wdGlvbnMiLCJpZ25vcmVHbG9icyIsIkltcG9ydE5hbWVzcGFjZVNwZWNpZmllciIsIm5vZGUiLCJmaW5kIiwicGFyZW50Iiwic291cmNlIiwidmFsdWUiLCJnbG9iIiwibWF0Y2hCYXNlIiwic2NvcGVWYXJpYWJsZXMiLCJnZXRTY29wZSIsInZhcmlhYmxlcyIsIm5hbWVzcGFjZVZhcmlhYmxlIiwidmFyaWFibGUiLCJkZWZzIiwibmFtZXNwYWNlUmVmZXJlbmNlcyIsInJlZmVyZW5jZXMiLCJuYW1lc3BhY2VJZGVudGlmaWVycyIsIm1hcCIsInJlZmVyZW5jZSIsImlkZW50aWZpZXIiLCJjYW5GaXgiLCJsZW5ndGgiLCJ1c2VzTmFtZXNwYWNlQXNPYmplY3QiLCJyZXBvcnQiLCJtZXNzYWdlIiwiZml4Iiwic2NvcGVNYW5hZ2VyIiwiZ2V0U291cmNlQ29kZSIsImZpeGVzIiwiaW1wb3J0TmFtZUNvbmZsaWN0cyIsImZvckVhY2giLCJpbXBvcnROYW1lIiwiZ2V0TWVtYmVyUHJvcGVydHlOYW1lIiwibG9jYWxDb25mbGljdHMiLCJnZXRWYXJpYWJsZU5hbWVzSW5TY29wZSIsImMiLCJhZGQiLCJpbXBvcnROYW1lcyIsIk9iamVjdCIsImtleXMiLCJpbXBvcnRMb2NhbE5hbWVzIiwiZ2VuZXJhdGVMb2NhbE5hbWVzIiwibmFtZSIsIm5hbWVkSW1wb3J0U3BlY2lmaWVycyIsInB1c2giLCJmaXhlciIsInJlcGxhY2VUZXh0Iiwiam9pbiIsImV2ZXJ5IiwicHJvcGVydHkiLCJtZW1iZXJFeHByZXNzaW9uIiwiY3VycmVudE5vZGUiLCJzY29wZSIsImFjcXVpcmUiLCJTZXQiLCJ1cHBlciIsIm5hbWVzIiwibmFtZUNvbmZsaWN0cyIsIm5hbWVzcGFjZU5hbWUiLCJsb2NhbE5hbWVzIiwibG9jYWxOYW1lIiwiaGFzIiwiaSIsIkluZmluaXR5Il0sIm1hcHBpbmdzIjoiOzs7OztBQUtBLHNDO0FBQ0EscUMsMlVBTkE7OztvWEFRQTtBQUNBO0FBQ0E7O0FBR0FBLE9BQU9DLE9BQVAsR0FBaUI7QUFDZkMsUUFBTTtBQUNKQyxVQUFNLFlBREY7QUFFSkMsVUFBTTtBQUNKQyxXQUFLLDBCQUFRLGNBQVIsQ0FERCxFQUZGOztBQUtKQyxhQUFTLE1BTEw7QUFNSkMsWUFBUSxDQUFDO0FBQ1BKLFlBQU0sUUFEQztBQUVQSyxrQkFBWTtBQUNWQyxnQkFBUTtBQUNOTixnQkFBTSxPQURBO0FBRU5PLGlCQUFPO0FBQ0xQLGtCQUFNLFFBREQsRUFGRDs7QUFLTlEsdUJBQWEsSUFMUCxFQURFLEVBRkwsRUFBRCxDQU5KLEVBRFM7Ozs7OztBQXFCZkMsUUFyQmUsK0JBcUJSQyxPQXJCUSxFQXFCQztBQUNkLFVBQU1DLGNBQWNELFFBQVFFLE9BQVIsQ0FBZ0IsQ0FBaEIsS0FBc0IsRUFBMUM7QUFDQSxVQUFNQyxjQUFjRixZQUFZTCxNQUFoQzs7QUFFQSxhQUFPO0FBQ0xRLGdDQURLLGlEQUNvQkMsSUFEcEIsRUFDMEI7QUFDN0IsZ0JBQUlGLGVBQWVBLFlBQVlHLElBQVosQ0FBaUIsd0JBQVEsNEJBQVVELEtBQUtFLE1BQUwsQ0FBWUMsTUFBWixDQUFtQkMsS0FBN0IsRUFBb0NDLElBQXBDLEVBQTBDLEVBQUVDLFdBQVcsSUFBYixFQUExQyxDQUFSLEVBQWpCLENBQW5CLEVBQTZHO0FBQzNHO0FBQ0Q7O0FBRUQsZ0JBQU1DLGlCQUFpQlosUUFBUWEsUUFBUixHQUFtQkMsU0FBMUM7QUFDQSxnQkFBTUMsb0JBQW9CSCxlQUFlTixJQUFmLENBQW9CLFVBQUNVLFFBQUQsVUFBY0EsU0FBU0MsSUFBVCxDQUFjLENBQWQsRUFBaUJaLElBQWpCLEtBQTBCQSxJQUF4QyxFQUFwQixDQUExQjtBQUNBLGdCQUFNYSxzQkFBc0JILGtCQUFrQkksVUFBOUM7QUFDQSxnQkFBTUMsdUJBQXVCRixvQkFBb0JHLEdBQXBCLENBQXdCLDZCQUFhQyxVQUFVQyxVQUF2QixFQUF4QixDQUE3QjtBQUNBLGdCQUFNQyxTQUFTSixxQkFBcUJLLE1BQXJCLEdBQThCLENBQTlCLElBQW1DLENBQUNDLHNCQUFzQk4sb0JBQXRCLENBQW5EOztBQUVBcEIsb0JBQVEyQixNQUFSLENBQWU7QUFDYnRCLHdCQURhO0FBRWJ1QixxREFGYTtBQUdiQyxtQkFBS0wsVUFBVyxpQkFBUztBQUN2QixvQkFBTU0sZUFBZTlCLFFBQVErQixhQUFSLEdBQXdCRCxZQUE3QztBQUNBLG9CQUFNRSxRQUFRLEVBQWQ7O0FBRUE7QUFDQTtBQUNBLG9CQUFNQyxzQkFBc0IsRUFBNUI7QUFDQWIscUNBQXFCYyxPQUFyQixDQUE2QixVQUFDWCxVQUFELEVBQWdCO0FBQzNDLHNCQUFNaEIsU0FBU2dCLFdBQVdoQixNQUExQjtBQUNBLHNCQUFJQSxVQUFVQSxPQUFPakIsSUFBUCxLQUFnQixrQkFBOUIsRUFBa0Q7QUFDaEQsd0JBQU02QyxhQUFhQyxzQkFBc0I3QixNQUF0QixDQUFuQjtBQUNBLHdCQUFNOEIsaUJBQWlCQyx3QkFBd0JSLFlBQXhCLEVBQXNDdkIsTUFBdEMsQ0FBdkI7QUFDQSx3QkFBSSxDQUFDMEIsb0JBQW9CRSxVQUFwQixDQUFMLEVBQXNDO0FBQ3BDRiwwQ0FBb0JFLFVBQXBCLElBQWtDRSxjQUFsQztBQUNELHFCQUZELE1BRU87QUFDTEEscUNBQWVILE9BQWYsQ0FBdUIsVUFBQ0ssQ0FBRCxVQUFPTixvQkFBb0JFLFVBQXBCLEVBQWdDSyxHQUFoQyxDQUFvQ0QsQ0FBcEMsQ0FBUCxFQUF2QjtBQUNEO0FBQ0Y7QUFDRixpQkFYRDs7QUFhQTtBQUNBLG9CQUFNRSxjQUFjQyxPQUFPQyxJQUFQLENBQVlWLG1CQUFaLENBQXBCO0FBQ0Esb0JBQU1XLG1CQUFtQkM7QUFDdkJKLDJCQUR1QjtBQUV2QlIsbUNBRnVCO0FBR3ZCbEIsa0NBQWtCK0IsSUFISyxDQUF6Qjs7O0FBTUE7QUFDQSxvQkFBTUMsd0JBQXdCTixZQUFZcEIsR0FBWixDQUFnQixVQUFDYyxVQUFEO0FBQzVDQSxtQ0FBZVMsaUJBQWlCVCxVQUFqQixDQUFmO0FBQ0lBLDhCQURKO0FBRU9BLDhCQUZQLG9CQUV3QlMsaUJBQWlCVCxVQUFqQixDQUZ4QixDQUQ0QyxHQUFoQixDQUE5Qjs7QUFLQUgsc0JBQU1nQixJQUFOLENBQVdDLE1BQU1DLFdBQU4sQ0FBa0I3QyxJQUFsQixnQkFBNkIwQyxzQkFBc0JJLElBQXRCLENBQTJCLElBQTNCLENBQTdCLFNBQVg7O0FBRUE7QUFDQS9CLHFDQUFxQmMsT0FBckIsQ0F