Skip to content

Commit

Permalink
[Refactor] namespace, no-deprecated: extract a helper function
Browse files Browse the repository at this point in the history
  • Loading branch information
azyzz228 authored and ljharb committed Oct 31, 2022
1 parent 9288cf7 commit 516b80a
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 44 deletions.
45 changes: 45 additions & 0 deletions src/core/namespaceValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Exports from '../ExportMap';

export default function namespaceValidator(
node,
namespaces,
onComputed,
{
onNamespaceNotFound = undefined,
onDeprecation = undefined,
} = {},
) {
// go deep
let namespace = namespaces.get(node.object.name);
const namepath = [node.object.name];

const sentinel = { __proto__: null }; // callbacks return this value if they want THIS function to stop executing

// while property is namespace and parent is member expression, keep validating
while (namespace instanceof Exports && node.type === 'MemberExpression') {
if (node.computed) {
if (onComputed(node, sentinel) === sentinel) {
return;
}
}

if (onNamespaceNotFound) {
if (onNamespaceNotFound(node, namespace, namepath, sentinel) === sentinel) {
return;
}
}

const exported = namespace.get(node.property.name);
if (!exported) {
return;
}

if (onDeprecation) {
onDeprecation(node, exported);
}

namepath.push(node.property.name);
namespace = exported.namespace;
node = node.parent;
}
}
47 changes: 24 additions & 23 deletions src/rules/namespace.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import declaredScope from 'eslint-module-utils/declaredScope';
import Exports from '../ExportMap';
import importDeclaration from '../importDeclaration';
import docsUrl from '../docsUrl';
import namespaceValidator from '../core/namespaceValidator';

function processBodyStatement(context, namespaces, declaration) {
if (declaration.type !== 'ImportDeclaration') return;
Expand Down Expand Up @@ -118,37 +119,37 @@ module.exports = {
);
}

// go deep
let namespace = namespaces.get(dereference.object.name);
const namepath = [dereference.object.name];
// while property is namespace and parent is member expression, keep validating
while (namespace instanceof Exports && dereference.type === 'MemberExpression') {
if (dereference.computed) {
function onComputed(context, allowComputed){
return function innerOnComputed(node, returnChecker) {
if (!allowComputed) {
context.report(
dereference.property,
node.property,
`Unable to validate computed reference to imported namespace '${dereference.object.name}'.`,
);
}
return;
}
return returnChecker;
};
}

if (!namespace.has(dereference.property.name)) {
context.report(
dereference.property,
makeMessage(dereference.property, namepath),
);
break;
}
function onNamespaceNotFound(context) {
return function inner(node, namespace, namepath, returnChecker) {
if (!namespace.has(node.property.name)) {
context.report(
node.property,
makeMessage(node.property, namepath),
);
return returnChecker;
}
};
}

const exported = namespace.get(dereference.property.name);
if (exported == null) return;
namespaceValidator(
dereference,
namespaces,
onComputed(context, allowComputed),
{ onNamespaceNotFound: onNamespaceNotFound(context) },
);

// stash and pop
namepath.push(dereference.property.name);
namespace = exported.namespace;
dereference = dereference.parent;
}
},

VariableDeclarator({ id, init }) {
Expand Down
40 changes: 19 additions & 21 deletions src/rules/no-deprecated.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import declaredScope from 'eslint-module-utils/declaredScope';
import Exports from '../ExportMap';
import docsUrl from '../docsUrl';
import namespaceValidator from '../core/namespaceValidator';

function message(deprecation) {
return 'Deprecated' + (deprecation.description ? ': ' + deprecation.description : '.');
Expand Down Expand Up @@ -111,30 +112,27 @@ module.exports = {

if (declaredScope(context, dereference.object.name) !== 'module') return;

// go deep
let namespace = namespaces.get(dereference.object.name);
const namepath = [dereference.object.name];
// while property is namespace and parent is member expression, keep validating
while (namespace instanceof Exports &&
dereference.type === 'MemberExpression') {
function onDeprecation(context){
return function inner(node, exported) {
const deprecation = getDeprecation(exported);

// ignore computed parts for now
if (dereference.computed) return;

const metadata = namespace.get(dereference.property.name);

if (!metadata) break;
const deprecation = getDeprecation(metadata);

if (deprecation) {
context.report({ node: dereference.property, message: message(deprecation) });
}
if (deprecation) {
context.report({ node: node.property, message: message(deprecation) });
}
};
}

// stash and pop
namepath.push(dereference.property.name);
namespace = metadata.namespace;
dereference = dereference.parent;
function onComputed() {
// ignore computed parts for now
return arguments[2];
}

namespaceValidator(
dereference,
namespaces,
onComputed,
{ onDeprecation: onDeprecation(context) },
);
},
};
},
Expand Down

0 comments on commit 516b80a

Please sign in to comment.