diff --git a/README.md b/README.md index 9954493..333a71b 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,24 @@ Add `plugin:relay/recommended` or `plugin:relay/strict` in `extends`: } ``` +### Suppressing rules within graphql tags + +The following rules support suppression within graphql tags: + +- relay/unused-fields +- relay/must-colocate-fragment-spreads + +Supported rules can be suppressed by adding `# eslint-disable-next-line relay/name-of-rule` to the preceding line: + +```js +graphql`fragment foo on Page { + # eslint-disable-next-line relay/must-colocate-fragment-spreads + ...unused1 +}` +``` + +Note that only the `eslint-disable-next-line` form of suppression works. `eslint-disable-line` doesn't currently work until graphql-js provides support for [parsing Comment nodes](https://github.com/graphql/graphql-js/issues/2241) in their AST. + ## Contribute We actively welcome pull requests, learn how to [contribute](./CONTRIBUTING.md). diff --git a/src/rule-must-colocate-fragment-spreads.js b/src/rule-must-colocate-fragment-spreads.js index 3bd21c3..6551b76 100644 --- a/src/rule-must-colocate-fragment-spreads.js +++ b/src/rule-must-colocate-fragment-spreads.js @@ -60,6 +60,9 @@ const {visit} = require('graphql'); const utils = require('./utils'); +const ESLINT_DISABLE_COMMENT = + ' eslint-disable-next-line relay/must-colocate-fragment-spreads'; + function getGraphQLFragmentSpreads(graphQLAst) { const fragmentSpreads = {}; visit(graphQLAst, { @@ -89,6 +92,11 @@ function getGraphQLFragmentSpreads(graphQLAst) { } } } + if ( + utils.hasPrecedingEslintDisableComment(node, ESLINT_DISABLE_COMMENT) + ) { + return; + } fragmentSpreads[node.name.value] = node; } }); diff --git a/src/rule-unused-fields.js b/src/rule-unused-fields.js index 71b0cc0..dfde701 100644 --- a/src/rule-unused-fields.js +++ b/src/rule-unused-fields.js @@ -7,20 +7,31 @@ 'use strict'; -const utils = require('./utils'); +const { + getGraphQLAST, + getLoc, + hasPrecedingEslintDisableComment +} = require('./utils'); -const getGraphQLAST = utils.getGraphQLAST; +const ESLINT_DISABLE_COMMENT = ' eslint-disable-next-line relay/unused-fields'; function getGraphQLFieldNames(graphQLAst) { const fieldNames = {}; function walkAST(node, ignoreLevel) { if (node.kind === 'Field' && !ignoreLevel) { + if (hasPrecedingEslintDisableComment(node, ESLINT_DISABLE_COMMENT)) { + return; + } const nameNode = node.alias || node.name; fieldNames[nameNode.value] = nameNode; } if (node.kind === 'OperationDefinition') { - if (node.operation === 'mutation' || node.operation === 'subscription') { + if ( + node.operation === 'mutation' || + node.operation === 'subscription' || + hasPrecedingEslintDisableComment(node, ESLINT_DISABLE_COMMENT) + ) { return; } // Ignore fields that are direct children of query as used in mutation @@ -142,7 +153,7 @@ function rule(context) { ) { context.report({ node: templateLiteral, - loc: utils.getLoc(context, templateLiteral, queriedFields[field]), + 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 ' + diff --git a/src/utils.js b/src/utils.js index 20d7977..205b31c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -112,6 +112,11 @@ function shouldLint(context) { return /graphql|relay/i.test(context.getSourceCode().text); } +function hasPrecedingEslintDisableComment(node, commentText) { + const prevNode = node.loc.startToken.prev; + return prevNode.kind === 'Comment' && prevNode.value.startsWith(commentText); +} + module.exports = { isGraphQLTemplate: isGraphQLTemplate, getGraphQLAST: getGraphQLAST, @@ -119,6 +124,7 @@ module.exports = { getLocFromIndex: getLocFromIndex, getModuleName: getModuleName, getRange: getRange, + hasPrecedingEslintDisableComment: hasPrecedingEslintDisableComment, isGraphQLTag: isGraphQLTag, isGraphQLDeprecatedTag: isGraphQLDeprecatedTag, shouldLint: shouldLint diff --git a/test/must-colocate-fragment-spreads.js b/test/must-colocate-fragment-spreads.js index 096a7a1..786d21b 100644 --- a/test/must-colocate-fragment-spreads.js +++ b/test/must-colocate-fragment-spreads.js @@ -100,7 +100,13 @@ ruleTester.run( const getOperation = (reference) => {\ return import(reference);\ };\ - ' + ', + ` + graphql\`fragment foo on Page { + # eslint-disable-next-line relay/must-colocate-fragment-spreads + ...unused1 + }\`; + ` ], invalid: [ { diff --git a/test/unused-fields.js b/test/unused-fields.js index e3d119c..c50d23a 100644 --- a/test/unused-fields.js +++ b/test/unused-fields.js @@ -83,6 +83,12 @@ ruleTester.run('unused-fields', rules['unused-fields'], { } } \`; + `, + ` + graphql\`fragment foo on Page { + # eslint-disable-next-line relay/unused-fields + name + }\`; ` ], invalid: [