From 5ea784bdb6e30df8bce91cd694f82d84ea663d4e Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sat, 16 May 2020 16:29:18 -0400 Subject: [PATCH 1/2] Add ignore fields option --- src/rule-unused-fields.js | 18 +++++++++++++++++- test/unused-fields.js | 15 ++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/rule-unused-fields.js b/src/rule-unused-fields.js index 71b0cc0..93440a6 100644 --- a/src/rule-unused-fields.js +++ b/src/rule-unused-fields.js @@ -11,6 +11,19 @@ const utils = require('./utils'); const getGraphQLAST = utils.getGraphQLAST; +const DEFAULT_OPTIONS = { + ignoreFields: [] +}; + +function getOptions(optionValue) { + if (optionValue) { + return { + ignoreFields: optionValue.ignoreFields || [] + }; + } + return DEFAULT_OPTIONS; +} + function getGraphQLFieldNames(graphQLAst) { const fieldNames = {}; @@ -82,6 +95,8 @@ function isPageInfoField(field) { } function rule(context) { + const options = getOptions(context.options[0]); + let currentMethod = []; let foundMemberAccesses = {}; let templateLiterals = []; @@ -138,7 +153,8 @@ function rule(context) { !isPageInfoField(field) && // Do not warn for unused __typename which can be a workaround // when only interested in existence of an object. - field !== '__typename' + field !== '__typename' && + !options.ignoreFields.includes(field) ) { context.report({ node: templateLiteral, diff --git a/test/unused-fields.js b/test/unused-fields.js index 23207f8..ba51b74 100644 --- a/test/unused-fields.js +++ b/test/unused-fields.js @@ -83,7 +83,13 @@ ruleTester.run('unused-fields', rules['unused-fields'], { } } \`; - ` + `, + { + code: ` + graphql\`fragment Test on Page { id }\`; + `, + options: [{ignoreFields: ['id']}] + } ], invalid: [ { @@ -109,6 +115,13 @@ ruleTester.run('unused-fields', rules['unused-fields'], { `, errors: [unusedFieldsWarning('unused1'), unusedFieldsWarning('unused2')] }, + { + code: ` + graphql\`fragment Test on Page { unused1, unused2 }\`; + `, + options: [{ignoreFields: ['unused1']}], + errors: [unusedFieldsWarning('unused2')] + }, { code: ` const getByPath = require('getByPath'); From 15abde5cdda1772bac61b03c0888b2eb11ddf33d Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Sat, 16 May 2020 16:56:25 -0400 Subject: [PATCH 2/2] Add option to check leave fields only --- src/rule-unused-fields.js | 19 ++++++++++++++----- test/unused-fields.js | 21 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/rule-unused-fields.js b/src/rule-unused-fields.js index 93440a6..83b81c2 100644 --- a/src/rule-unused-fields.js +++ b/src/rule-unused-fields.js @@ -12,23 +12,29 @@ const utils = require('./utils'); const getGraphQLAST = utils.getGraphQLAST; const DEFAULT_OPTIONS = { - ignoreFields: [] + ignoreFields: [], + leavesOnly: false }; function getOptions(optionValue) { if (optionValue) { return { - ignoreFields: optionValue.ignoreFields || [] + ignoreFields: optionValue.ignoreFields || DEFAULT_OPTIONS.ignoreFields, + leavesOnly: optionValue.leavesOnly || DEFAULT_OPTIONS.leavesOnly }; } return DEFAULT_OPTIONS; } -function getGraphQLFieldNames(graphQLAst) { +function getGraphQLFieldNames(graphQLAst, leavesOnly) { const fieldNames = {}; function walkAST(node, ignoreLevel) { - if (node.kind === 'Field' && !ignoreLevel) { + if ( + node.kind === 'Field' && + !ignoreLevel && + (!leavesOnly || node.selectionSet == null) + ) { const nameNode = node.alias || node.name; fieldNames[nameNode.value] = nameNode; } @@ -146,7 +152,10 @@ function rule(context) { return; } - const queriedFields = getGraphQLFieldNames(graphQLAst); + const queriedFields = getGraphQLFieldNames( + graphQLAst, + options.leavesOnly + ); for (const field in queriedFields) { if ( !foundMemberAccesses[field] && diff --git a/test/unused-fields.js b/test/unused-fields.js index ba51b74..48416af 100644 --- a/test/unused-fields.js +++ b/test/unused-fields.js @@ -89,6 +89,14 @@ ruleTester.run('unused-fields', rules['unused-fields'], { graphql\`fragment Test on Page { id }\`; `, options: [{ignoreFields: ['id']}] + }, + { + code: ` + graphql\`fragment Test on Page { connection { edges { node { id } } } }\`; + const nodes = useConnectionArray(props.connection); + node.id; + `, + options: [{leavesOnly: true}] } ], invalid: [ @@ -115,6 +123,19 @@ ruleTester.run('unused-fields', rules['unused-fields'], { `, errors: [unusedFieldsWarning('unused1'), unusedFieldsWarning('unused2')] }, + { + code: ` + graphql\`fragment Test on Page { unused1 { unused2 } }\`; + `, + errors: [unusedFieldsWarning('unused1'), unusedFieldsWarning('unused2')] + }, + { + code: ` + graphql\`fragment Test on Page { unused1 { unused2 } }\`; + `, + options: [{leavesOnly: true}], + errors: [unusedFieldsWarning('unused2')] + }, { code: ` graphql\`fragment Test on Page { unused1, unused2 }\`;