219 lines
26 KiB
JavaScript
219 lines
26 KiB
JavaScript
|
'use strict';var _declaredScope = require('eslint-module-utils/declaredScope');var _declaredScope2 = _interopRequireDefault(_declaredScope);
|
||
|
var _builder = require('../exportMap/builder');var _builder2 = _interopRequireDefault(_builder);
|
||
|
var _exportMap = require('../exportMap');var _exportMap2 = _interopRequireDefault(_exportMap);
|
||
|
var _importDeclaration = require('../importDeclaration');var _importDeclaration2 = _interopRequireDefault(_importDeclaration);
|
||
|
var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}
|
||
|
|
||
|
function processBodyStatement(context, namespaces, declaration) {
|
||
|
if (declaration.type !== 'ImportDeclaration') {return;}
|
||
|
|
||
|
if (declaration.specifiers.length === 0) {return;}
|
||
|
|
||
|
var imports = _builder2['default'].get(declaration.source.value, context);
|
||
|
if (imports == null) {return null;}
|
||
|
|
||
|
if (imports.errors.length > 0) {
|
||
|
imports.reportErrors(context, declaration);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
declaration.specifiers.forEach(function (specifier) {
|
||
|
switch (specifier.type) {
|
||
|
case 'ImportNamespaceSpecifier':
|
||
|
if (!imports.size) {
|
||
|
context.report(
|
||
|
specifier, 'No exported names found in module \'' + String(
|
||
|
declaration.source.value) + '\'.');
|
||
|
|
||
|
}
|
||
|
namespaces.set(specifier.local.name, imports);
|
||
|
break;
|
||
|
case 'ImportDefaultSpecifier':
|
||
|
case 'ImportSpecifier':{
|
||
|
var meta = imports.get(
|
||
|
// default to 'default' for default https://i.imgur.com/nj6qAWy.jpg
|
||
|
specifier.imported ? specifier.imported.name || specifier.imported.value : 'default');
|
||
|
|
||
|
if (!meta || !meta.namespace) {break;}
|
||
|
namespaces.set(specifier.local.name, meta.namespace);
|
||
|
break;
|
||
|
}
|
||
|
default:}
|
||
|
|
||
|
});
|
||
|
}
|
||
|
|
||
|
module.exports = {
|
||
|
meta: {
|
||
|
type: 'problem',
|
||
|
docs: {
|
||
|
category: 'Static analysis',
|
||
|
description: 'Ensure imported namespaces contain dereferenced properties as they are dereferenced.',
|
||
|
url: (0, _docsUrl2['default'])('namespace') },
|
||
|
|
||
|
|
||
|
schema: [
|
||
|
{
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
allowComputed: {
|
||
|
description: 'If `false`, will report computed (and thus, un-lintable) references to namespace members.',
|
||
|
type: 'boolean',
|
||
|
'default': false } },
|
||
|
|
||
|
|
||
|
additionalProperties: false }] },
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
create: function () {function namespaceRule(context) {
|
||
|
// read options
|
||
|
var _ref =
|
||
|
|
||
|
context.options[0] || {},_ref$allowComputed = _ref.allowComputed,allowComputed = _ref$allowComputed === undefined ? false : _ref$allowComputed;
|
||
|
|
||
|
var namespaces = new Map();
|
||
|
|
||
|
function makeMessage(last, namepath) {
|
||
|
return '\'' + String(last.name) + '\' not found in ' + (namepath.length > 1 ? 'deeply ' : '') + 'imported namespace \'' + String(namepath.join('.')) + '\'.';
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
// pick up all imports at body entry time, to properly respect hoisting
|
||
|
Program: function () {function Program(_ref2) {var body = _ref2.body;
|
||
|
body.forEach(function (x) {processBodyStatement(context, namespaces, x);});
|
||
|
}return Program;}(),
|
||
|
|
||
|
// same as above, but does not add names to local map
|
||
|
ExportNamespaceSpecifier: function () {function ExportNamespaceSpecifier(namespace) {
|
||
|
var declaration = (0, _importDeclaration2['default'])(context);
|
||
|
|
||
|
var imports = _builder2['default'].get(declaration.source.value, context);
|
||
|
if (imports == null) {return null;}
|
||
|
|
||
|
if (imports.errors.length) {
|
||
|
imports.reportErrors(context, declaration);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!imports.size) {
|
||
|
context.report(
|
||
|
namespace, 'No exported names found in module \'' + String(
|
||
|
declaration.source.value) + '\'.');
|
||
|
|
||
|
}
|
||
|
}return ExportNamespaceSpecifier;}(),
|
||
|
|
||
|
// todo: check for possible redefinition
|
||
|
|
||
|
MemberExpression: function () {function MemberExpression(dereference) {
|
||
|
if (dereference.object.type !== 'Identifier') {return;}
|
||
|
if (!namespaces.has(dereference.object.name)) {return;}
|
||
|
if ((0, _declaredScope2['default'])(context, dereference.object.name) !== 'module') {return;}
|
||
|
|
||
|
if (dereference.parent.type === 'AssignmentExpression' && dereference.parent.left === dereference) {
|
||
|
context.report(
|
||
|
dereference.parent, 'Assignment to member of namespace \'' + String(
|
||
|
dereference.object.name) + '\'.');
|
||
|
|
||
|
}
|
||
|
|
||
|
// go deep
|
||
|
var namespace = namespaces.get(dereference.object.name);
|
||
|
var namepath = [dereference.object.name];
|
||
|
// while property is namespace and parent is member expression, keep validating
|
||
|
while (namespace instanceof _exportMap2['default'] && dereference.type === 'MemberExpression') {
|
||
|
if (dereference.computed) {
|
||
|
if (!allowComputed) {
|
||
|
context.report(
|
||
|
dereference.property, 'Unable to validate computed reference to imported namespace \'' + String(
|
||
|
dereference.object.name) + '\'.');
|
||
|
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!namespace.has(dereference.property.name)) {
|
||
|
context.report(
|
||
|
dereference.property,
|
||
|
makeMessage(dereference.property, namepath));
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
var exported = namespace.get(dereference.property.name);
|
||
|
if (exported == null) {return;}
|
||
|
|
||
|
// stash and pop
|
||
|
namepath.push(dereference.property.name);
|
||
|
namespace = exported.namespace;
|
||
|
dereference = dereference.parent;
|
||
|
}
|
||
|
}return MemberExpression;}(),
|
||
|
|
||
|
VariableDeclarator: function () {function VariableDeclarator(_ref3) {var id = _ref3.id,init = _ref3.init;
|
||
|
if (init == null) {return;}
|
||
|
if (init.type !== 'Identifier') {return;}
|
||
|
if (!namespaces.has(init.name)) {return;}
|
||
|
|
||
|
// check for redefinition in intermediate scopes
|
||
|
if ((0, _declaredScope2['default'])(context, init.name) !== 'module') {return;}
|
||
|
|
||
|
// DFS traverse child namespaces
|
||
|
function testKey(pattern, namespace) {var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [init.name];
|
||
|
if (!(namespace instanceof _exportMap2['default'])) {return;}
|
||
|
|
||
|
if (pattern.type !== 'ObjectPattern') {return;}var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
|
||
|
|
||
|
for (var _iterator = pattern.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var property = _step.value;
|
||
|
if (
|
||
|
property.type === 'ExperimentalRestProperty' ||
|
||
|
property.type === 'RestElement' ||
|
||
|
!property.key)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (property.key.type !== 'Identifier') {
|
||
|
context.report({
|
||
|
node: property,
|
||
|
message: 'Only destructure top-level names.' });
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!namespace.has(property.key.name)) {
|
||
|
context.report({
|
||
|
node: property,
|
||
|
message: makeMessage(property.key, path) });
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
path.push(property.key.name);
|
||
|
var dependencyExportMap = namespace.get(property.key.name);
|
||
|
// could be null when ignored or ambiguous
|
||
|
if (dependencyExportMap !== null) {
|
||
|
testKey(property.value, dependencyExportMap.namespace, path);
|
||
|
}
|
||
|
path.pop();
|
||
|
}} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator['return']) {_iterator['return']();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
|
||
|
}
|
||
|
|
||
|
testKey(id, namespaces.get(init.name));
|
||
|
}return VariableDeclarator;}(),
|
||
|
|
||
|
JSXMemberExpression: function () {function JSXMemberExpression(_ref4) {var object = _ref4.object,property = _ref4.property;
|
||
|
if (!namespaces.has(object.name)) {return;}
|
||
|
var namespace = namespaces.get(object.name);
|
||
|
if (!namespace.has(property.name)) {
|
||
|
context.report({
|
||
|
node: property,
|
||
|
message: makeMessage(property, [object.name]) });
|
||
|
|
||
|
}
|
||
|
}return JSXMemberExpression;}() };
|
||
|
|
||
|
}return namespaceRule;}() };
|
||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uYW1lc3BhY2UuanMiXSwibmFtZXMiOlsicHJvY2Vzc0JvZHlTdGF0ZW1lbnQiLCJjb250ZXh0IiwibmFtZXNwYWNlcyIsImRlY2xhcmF0aW9uIiwidHlwZSIsInNwZWNpZmllcnMiLCJsZW5ndGgiLCJpbXBvcnRzIiwiRXhwb3J0TWFwQnVpbGRlciIsImdldCIsInNvdXJjZSIsInZhbHVlIiwiZXJyb3JzIiwicmVwb3J0RXJyb3JzIiwiZm9yRWFjaCIsInNwZWNpZmllciIsInNpemUiLCJyZXBvcnQiLCJzZXQiLCJsb2NhbCIsIm5hbWUiLCJtZXRhIiwiaW1wb3J0ZWQiLCJuYW1lc3BhY2UiLCJtb2R1bGUiLCJleHBvcnRzIiwiZG9jcyIsImNhdGVnb3J5IiwiZGVzY3JpcHRpb24iLCJ1cmwiLCJzY2hlbWEiLCJwcm9wZXJ0aWVzIiwiYWxsb3dDb21wdXRlZCIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiY3JlYXRlIiwibmFtZXNwYWNlUnVsZSIsIm9wdGlvbnMiLCJNYXAiLCJtYWtlTWVzc2FnZSIsImxhc3QiLCJuYW1lcGF0aCIsImpvaW4iLCJQcm9ncmFtIiwiYm9keSIsIngiLCJFeHBvcnROYW1lc3BhY2VTcGVjaWZpZXIiLCJNZW1iZXJFeHByZXNzaW9uIiwiZGVyZWZlcmVuY2UiLCJvYmplY3QiLCJoYXMiLCJwYXJlbnQiLCJsZWZ0IiwiRXhwb3J0TWFwIiwiY29tcHV0ZWQiLCJwcm9wZXJ0eSIsImV4cG9ydGVkIiwicHVzaCIsIlZhcmlhYmxlRGVjbGFyYXRvciIsImlkIiwiaW5pdCIsInRlc3RLZXkiLCJwYXR0ZXJuIiwicGF0aCIsImtleSIsIm5vZGUiLCJtZXNzYWdlIiwiZGVwZW5kZW5jeUV4cG9ydE1hcCIsInBvcCIsIkpTWE1lbWJlckV4cHJlc3Npb24iXSwibWFwcGluZ3MiOiJhQUFBLGtFO0FBQ0EsK0M7QUFDQSx5QztBQUNBLHlEO0FBQ0EscUM7O0FBRUEsU0FBU0Esb0JBQVQsQ0FBOEJDLE9BQTlCLEVB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
|