in src/rule-unused-fields.js [95:206]
function rule(context) {
let currentMethod = [];
let foundMemberAccesses = {};
let templateLiterals = [];
function visitGetByPathCall(node) {
// The `getByPath` utility accesses nested fields in the form
// `getByPath(thing, ['field', 'nestedField'])`.
const pathArg = node.arguments[1];
if (!pathArg || pathArg.type !== 'ArrayExpression') {
return;
}
pathArg.elements.forEach(element => {
if (isStringNode(element)) {
foundMemberAccesses[element.value] = true;
}
});
}
function visitDotAccessCall(node) {
// The `dotAccess` utility accesses nested fields in the form
// `dotAccess(thing, 'field.nestedField')`.
const pathArg = node.arguments[1];
if (isStringNode(pathArg)) {
pathArg.value.split('.').forEach(element => {
foundMemberAccesses[element] = true;
});
}
}
function visitMemberExpression(node) {
if (node.property.type === 'Identifier') {
foundMemberAccesses[node.property.name] = true;
}
}
return {
Program(_node) {
currentMethod = [];
foundMemberAccesses = {};
templateLiterals = [];
},
'Program:exit'(_node) {
templateLiterals.forEach(templateLiteral => {
const graphQLAst = getGraphQLAST(templateLiteral);
if (!graphQLAst) {
// ignore nodes with syntax errors, they're handled by rule-graphql-syntax
return;
}
const queriedFields = getGraphQLFieldNames(graphQLAst);
for (const field in queriedFields) {
if (
!foundMemberAccesses[field] &&
!isPageInfoField(field) &&
// Do not warn for unused __typename which can be a workaround
// when only interested in existence of an object.
field !== '__typename'
) {
context.report({
node: templateLiteral,
loc: getLoc(context, templateLiteral, queriedFields[field]),
message:
`This queries for the field \`${field}\` but this file does ` +
'not seem to use it directly. If a different file needs this ' +
'information that file should export a fragment and colocate ' +
'the query for the data with the usage.\n' +
'If only interested in the existence of a record, __typename ' +
'can be used without this warning.'
});
}
}
});
},
CallExpression(node) {
if (node.callee.type !== 'Identifier') {
return;
}
switch (node.callee.name) {
case 'getByPath':
visitGetByPathCall(node);
break;
case 'dotAccess':
visitDotAccessCall(node);
break;
}
},
TaggedTemplateExpression(node) {
if (currentMethod[0] === 'getConfigs') {
return;
}
if (isGraphQLTemplate(node)) {
templateLiterals.push(node);
}
},
MemberExpression: visitMemberExpression,
OptionalMemberExpression: visitMemberExpression,
ObjectPattern(node) {
node.properties.forEach(node => {
if (node.type === 'Property' && !node.computed) {
foundMemberAccesses[node.key.name] = true;
}
});
},
MethodDefinition(node) {
currentMethod.unshift(node.key.name);
},
'MethodDefinition:exit'(_node) {
currentMethod.shift();
}
};
}