From 1aad60ba8384ba4e4ee7adc20c98ba3a7fd620ab Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 13 Mar 2022 08:23:01 +0100 Subject: [PATCH 1/5] test: move the test fixture files. --- .../.eslintrc.debug.js | 8 ++++++++ .../test-cspell-eslint-plugin/.eslintrc.js | 3 +-- .../fixtures/creepyData.ts | 19 +++++++++++++++++++ .../{src => fixtures}/file.js | 0 .../{src => fixtures}/index.ts | 5 +++++ .../{src => fixtures}/myReader.ts | 0 .../{src => fixtures}/reader.ts | 0 .../test-cspell-eslint-plugin/package.json | 5 +---- .../test-cspell-eslint-plugin/tsconfig.json | 2 +- 9 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test-packages/test-cspell-eslint-plugin/.eslintrc.debug.js create mode 100644 test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts rename test-packages/test-cspell-eslint-plugin/{src => fixtures}/file.js (100%) rename test-packages/test-cspell-eslint-plugin/{src => fixtures}/index.ts (70%) rename test-packages/test-cspell-eslint-plugin/{src => fixtures}/myReader.ts (100%) rename test-packages/test-cspell-eslint-plugin/{src => fixtures}/reader.ts (100%) diff --git a/test-packages/test-cspell-eslint-plugin/.eslintrc.debug.js b/test-packages/test-cspell-eslint-plugin/.eslintrc.debug.js new file mode 100644 index 00000000000..8f23a1a2956 --- /dev/null +++ b/test-packages/test-cspell-eslint-plugin/.eslintrc.debug.js @@ -0,0 +1,8 @@ +/** + * @type { import("eslint").Linter.Config } + */ +const config = { + extends: ['./.eslintrc.js', 'plugin:@cspell/debug'], +}; + +module.exports = config; diff --git a/test-packages/test-cspell-eslint-plugin/.eslintrc.js b/test-packages/test-cspell-eslint-plugin/.eslintrc.js index 10398dfb527..22b3b067ab7 100644 --- a/test-packages/test-cspell-eslint-plugin/.eslintrc.js +++ b/test-packages/test-cspell-eslint-plugin/.eslintrc.js @@ -13,8 +13,7 @@ const config = { 'plugin:import/warnings', 'plugin:promise/recommended', 'plugin:prettier/recommended', - // 'plugin:@cspell/recommended', - 'plugin:@cspell/debug', + 'plugin:@cspell/recommended', ], ignorePatterns: ['**/*.d.ts', '**/*.map', '**/coverage/**', '**/dist/**', '**/node_modules/**'], parserOptions: { diff --git a/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts b/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts new file mode 100644 index 00000000000..e0606369a59 --- /dev/null +++ b/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts @@ -0,0 +1,19 @@ +export interface CreepyExpressions { + muawhahaha: string; + grrrrr: string; + uuuug: string; +} + +export const expressions: CreepyExpressions = { + muawhahaha: 'muawhahaha', + grrrrr: 'grrrrr', + uuuug: 'uuuug', +}; + +export const muawhahaha = expressions.muawhahaha; + +export enum ExpressionCategory { + MUAWHAHAHA = 0, + GRRRRRR, + UUUUUG, +} diff --git a/test-packages/test-cspell-eslint-plugin/src/file.js b/test-packages/test-cspell-eslint-plugin/fixtures/file.js similarity index 100% rename from test-packages/test-cspell-eslint-plugin/src/file.js rename to test-packages/test-cspell-eslint-plugin/fixtures/file.js diff --git a/test-packages/test-cspell-eslint-plugin/src/index.ts b/test-packages/test-cspell-eslint-plugin/fixtures/index.ts similarity index 70% rename from test-packages/test-cspell-eslint-plugin/src/index.ts rename to test-packages/test-cspell-eslint-plugin/fixtures/index.ts index f41d4ef2ec1..858b325855a 100644 --- a/test-packages/test-cspell-eslint-plugin/src/index.ts +++ b/test-packages/test-cspell-eslint-plugin/fixtures/index.ts @@ -1,4 +1,5 @@ import { reader as myreader, reeder } from './reader'; +import { expressions, muawhahaha } from './creepyData'; /** * This is some sample code to test cspell's eslint-plugin. @@ -16,6 +17,10 @@ function main() { console.log(myreader === reeder ? 'Match' : 'miss'); console.log(myreader(__filename)); + + console.log(expressions.grrrrr); + console.log(expressions['uuuug']); + console.log(muawhahaha); } main(); diff --git a/test-packages/test-cspell-eslint-plugin/src/myReader.ts b/test-packages/test-cspell-eslint-plugin/fixtures/myReader.ts similarity index 100% rename from test-packages/test-cspell-eslint-plugin/src/myReader.ts rename to test-packages/test-cspell-eslint-plugin/fixtures/myReader.ts diff --git a/test-packages/test-cspell-eslint-plugin/src/reader.ts b/test-packages/test-cspell-eslint-plugin/fixtures/reader.ts similarity index 100% rename from test-packages/test-cspell-eslint-plugin/src/reader.ts rename to test-packages/test-cspell-eslint-plugin/fixtures/reader.ts diff --git a/test-packages/test-cspell-eslint-plugin/package.json b/test-packages/test-cspell-eslint-plugin/package.json index 17a3750770e..d9a5cbcbccb 100644 --- a/test-packages/test-cspell-eslint-plugin/package.json +++ b/test-packages/test-cspell-eslint-plugin/package.json @@ -4,10 +4,7 @@ "description": "Pure testing package for @cspell/eslint-plugin-cspell.", "private": true, "scripts": { - "clean": "rimraf dist .tsbuildinfo", - "build": "tsc -p .", - "eslint": "eslint -c .eslintrc.js", - "clean-build": "npm run clean && npm run build", + "eslint": "eslint -c .eslintrc.js .", "test": "npm run eslint" }, "engines": { diff --git a/test-packages/test-cspell-eslint-plugin/tsconfig.json b/test-packages/test-cspell-eslint-plugin/tsconfig.json index d11ecf39ed1..447234decf1 100644 --- a/test-packages/test-cspell-eslint-plugin/tsconfig.json +++ b/test-packages/test-cspell-eslint-plugin/tsconfig.json @@ -4,6 +4,6 @@ "outDir": "dist" }, "include": [ - "src" + "fixtures" ] } From 009a2887f12c084b0a2ad18ecb68999ea975aecf Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 13 Mar 2022 08:55:07 +0100 Subject: [PATCH 2/5] fix: do not spell check imported properties --- .../fixtures/with-errors/creepyData.ts | 19 +++++++ .../fixtures/with-errors/imports.ts | 7 +++ .../src/cspell-eslint-plugin.ts | 50 ++++++++++++++++--- .../cspell-eslint-plugin/src/index.test.ts | 14 ++++++ .../fixtures/index.ts | 2 + 5 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts create mode 100644 packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts diff --git a/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts b/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts new file mode 100644 index 00000000000..e0606369a59 --- /dev/null +++ b/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts @@ -0,0 +1,19 @@ +export interface CreepyExpressions { + muawhahaha: string; + grrrrr: string; + uuuug: string; +} + +export const expressions: CreepyExpressions = { + muawhahaha: 'muawhahaha', + grrrrr: 'grrrrr', + uuuug: 'uuuug', +}; + +export const muawhahaha = expressions.muawhahaha; + +export enum ExpressionCategory { + MUAWHAHAHA = 0, + GRRRRRR, + UUUUUG, +} diff --git a/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts b/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts new file mode 100644 index 00000000000..cd0bf93ebc8 --- /dev/null +++ b/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts @@ -0,0 +1,7 @@ +import { muawhahaha as m, expressions } from './creepyData'; +import * as creepy from './creepyData'; + +console.log(creepy.expressions.grrrrr); +console.log(creepy.muawhahaha); +console.log(m); +console.log(expressions.uuuug); diff --git a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts index be67c4cf278..9980f0b725d 100644 --- a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts +++ b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts @@ -56,6 +56,7 @@ function log(...args: Parameters) { function create(context: Rule.RuleContext): Rule.RuleListener { const options = normalizeOptions(context.options[0]); + const toIgnore = new Set(); const importedIdentifiers = new Set(); isDebugMode = options.debugMode || false; isDebugMode && logContext(context); @@ -66,8 +67,9 @@ function create(context: Rule.RuleContext): Rule.RuleListener { function checkLiteral(node: Literal & Rule.NodeParentExtension) { if (!options.checkStrings) return; if (typeof node.value === 'string') { - if (options.ignoreImports && isImportOrRequired(node)) return; debugNode(node, node.value); + if (options.ignoreImports && isImportOrRequired(node)) return; + if (isImportedProperty(node)) return; checkNodeText(node, node.value); } } @@ -80,13 +82,20 @@ function create(context: Rule.RuleContext): Rule.RuleListener { } function checkIdentifier(node: Identifier & Rule.NodeParentExtension) { - if (options.ignoreImports && isImportIdentifier(node)) { - importedIdentifiers.add(node.name); - return; + debugNode(node, node.name); + if (options.ignoreImports) { + if (isRawImportIdentifier(node)) { + toIgnore.add(node.name); + return; + } + if (isImportIdentifier(node)) { + importedIdentifiers.add(node.name); + } else if (isImportedProperty(node)) { + return; + } } if (!options.checkIdentifiers) return; - if (importedIdentifiers.has(node.name)) return; - debugNode(node, node.name); + if (toIgnore.has(node.name)) return; checkNodeText(node, node.name); } @@ -113,6 +122,17 @@ function create(context: Rule.RuleContext): Rule.RuleListener { } function isImportIdentifier(node: ASTNode): boolean { + const parent = node.parent; + if (node.type !== 'Identifier' || !parent) return false; + return ( + (parent.type === 'ImportSpecifier' || + parent.type === 'ImportNamespaceSpecifier' || + parent.type === 'ImportDefaultSpecifier') && + parent.local === node + ); + } + + function isRawImportIdentifier(node: ASTNode): boolean { const parent = node.parent; if (node.type !== 'Identifier' || !parent) return false; return ( @@ -121,6 +141,11 @@ function create(context: Rule.RuleContext): Rule.RuleListener { ); } + function isImportedProperty(node: ASTNode): boolean { + const obj = findOriginObject(node); + return !!obj && obj.type === 'Identifier' && importedIdentifiers.has(obj.name); + } + function reportIssue(issue: ValidationIssue) { const messageId: MessageIds = issue.isFlagged ? 'wordForbidden' : 'wordUnknown'; const data = { @@ -236,6 +261,19 @@ function create(context: Rule.RuleContext): Rule.RuleListener { return inheritance(node).join(' '); } + /** + * find the origin of a member expression + */ + function findOriginObject(node: ASTNode): ASTNode | undefined { + const parent = node.parent; + if (parent?.type !== 'MemberExpression' || parent.property !== node) return undefined; + let obj = parent.object; + while (obj.type === 'MemberExpression') { + obj = obj.object; + } + return obj; + } + function isFunctionCall(node: ASTNode | undefined, name: string): boolean { return node?.type === 'CallExpression' && node.callee.type === 'Identifier' && node.callee.name === name; } diff --git a/packages/cspell-eslint-plugin/src/index.test.ts b/packages/cspell-eslint-plugin/src/index.test.ts index 0c3ad47dc24..d6d885899f8 100644 --- a/packages/cspell-eslint-plugin/src/index.test.ts +++ b/packages/cspell-eslint-plugin/src/index.test.ts @@ -42,6 +42,7 @@ ruleTester.run('cspell', Rule.rules.spellchecker, { readSample('sample.ts'), readSample('sampleESM.mjs'), readFix('with-errors/strings.ts', { checkStrings: false, checkStringTemplates: false }), + readFix('with-errors/imports.ts'), ], invalid: [ // cspell:ignore Guuide Gallaxy BADD functionn coool @@ -86,6 +87,19 @@ ruleTester.run('cspell', Rule.rules.spellchecker, { readInvalid('with-errors/strings.ts', ['Unknown word: "naaame"', 'Unknown word: "doen\'t"'], { checkStringTemplates: false, }), + // cspell:ignore muawhahaha grrrrr uuuug + readInvalid( + 'with-errors/imports.ts', + [ + 'Unknown word: "muawhahaha"', + 'Unknown word: "grrrrr"', + 'Unknown word: "muawhahaha"', + 'Unknown word: "uuuug"', + ], + { + ignoreImports: false, + } + ), ], }); diff --git a/test-packages/test-cspell-eslint-plugin/fixtures/index.ts b/test-packages/test-cspell-eslint-plugin/fixtures/index.ts index 858b325855a..c204478808d 100644 --- a/test-packages/test-cspell-eslint-plugin/fixtures/index.ts +++ b/test-packages/test-cspell-eslint-plugin/fixtures/index.ts @@ -1,5 +1,6 @@ import { reader as myreader, reeder } from './reader'; import { expressions, muawhahaha } from './creepyData'; +import * as creepy from './creepyData'; /** * This is some sample code to test cspell's eslint-plugin. @@ -21,6 +22,7 @@ function main() { console.log(expressions.grrrrr); console.log(expressions['uuuug']); console.log(muawhahaha); + console.log(creepy.expressions.grrrrr); } main(); From 25c2aa2c9c79d6daaf4d2ca8a489fb73544b1f95 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 13 Mar 2022 09:42:32 +0100 Subject: [PATCH 3/5] fix: support ignoring imported properties. --- packages/cspell-eslint-plugin/README.md | 29 +++++++++++++------ .../fixtures/with-errors/imports.ts | 4 +-- .../src/_auto_generated_/options.schema.json | 7 ++++- .../src/cspell-eslint-plugin.ts | 18 ++++++++++-- .../cspell-eslint-plugin/src/index.test.ts | 8 +++++ packages/cspell-eslint-plugin/src/options.ts | 24 +++++++++++---- 6 files changed, 70 insertions(+), 20 deletions(-) diff --git a/packages/cspell-eslint-plugin/README.md b/packages/cspell-eslint-plugin/README.md index e0476a22018..fd6ed3a8638 100644 --- a/packages/cspell-eslint-plugin/README.md +++ b/packages/cspell-eslint-plugin/README.md @@ -21,30 +21,36 @@ This plugin is still in active development. Due to the nature of how files are p ## Options -```ts +````ts interface Options { /** * Number of spelling suggestions to make. * @default 8 */ numSuggestions: number; - /** * Generate suggestions * @default true */ generateSuggestions: boolean; - - /** - * Output debug logs - * @default false - */ - debugMode?: boolean; /** * Ignore import and require names * @default true */ ignoreImports?: boolean; + /** + * Ignore the properties of imported variables, structures, and types. + * + * Example: + * ``` + * import { example } from 'third-party'; + * + * const msg = example.property; // `property` is not spell checked. + * ``` + * + * @default true + */ + ignoreImportProperties?: boolean; /** * Spell check identifiers (variables names, function names, and class names) * @default true @@ -65,8 +71,13 @@ interface Options { * @default true */ checkComments?: boolean; + /** + * Output debug logs + * @default false + */ + debugMode?: boolean; } -``` +```` Example: diff --git a/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts b/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts index cd0bf93ebc8..7e6ec087647 100644 --- a/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts +++ b/packages/cspell-eslint-plugin/fixtures/with-errors/imports.ts @@ -1,7 +1,7 @@ -import { muawhahaha as m, expressions } from './creepyData'; +import { muawhahaha, expressions } from './creepyData'; import * as creepy from './creepyData'; console.log(creepy.expressions.grrrrr); console.log(creepy.muawhahaha); -console.log(m); +console.log(muawhahaha); console.log(expressions.uuuug); diff --git a/packages/cspell-eslint-plugin/src/_auto_generated_/options.schema.json b/packages/cspell-eslint-plugin/src/_auto_generated_/options.schema.json index 05644e321bd..eab433afa72 100644 --- a/packages/cspell-eslint-plugin/src/_auto_generated_/options.schema.json +++ b/packages/cspell-eslint-plugin/src/_auto_generated_/options.schema.json @@ -10,7 +10,7 @@ }, "checkIdentifiers": { "default": true, - "description": "Spell check identifiers (variables names, function names, and class names)", + "description": "Spell check identifiers (variables names, function names, class names, etc.)", "type": "boolean" }, "checkStringTemplates": { @@ -33,6 +33,11 @@ "description": "Generate suggestions", "type": "boolean" }, + "ignoreImportProperties": { + "default": true, + "description": "Ignore the properties of imported variables, structures, and types.\n\nExample: ``` import { example } from 'third-party';\n\nconst msg = example.property; // `property` is not spell checked. ```", + "type": "boolean" + }, "ignoreImports": { "default": true, "description": "Ignore import and require names", diff --git a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts index 9980f0b725d..d2c1bc0dd24 100644 --- a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts +++ b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts @@ -69,7 +69,7 @@ function create(context: Rule.RuleContext): Rule.RuleListener { if (typeof node.value === 'string') { debugNode(node, node.value); if (options.ignoreImports && isImportOrRequired(node)) return; - if (isImportedProperty(node)) return; + if (options.ignoreImportProperties && isImportedProperty(node)) return; checkNodeText(node, node.value); } } @@ -90,12 +90,13 @@ function create(context: Rule.RuleContext): Rule.RuleListener { } if (isImportIdentifier(node)) { importedIdentifiers.add(node.name); - } else if (isImportedProperty(node)) { + } else if (options.ignoreImportProperties && isImportedProperty(node)) { return; } } if (!options.checkIdentifiers) return; - if (toIgnore.has(node.name)) return; + if (toIgnore.has(node.name) && !isObjectProperty(node)) return; + if (skipCheckForRawImportIdentifiers(node)) return; checkNodeText(node, node.name); } @@ -141,11 +142,22 @@ function create(context: Rule.RuleContext): Rule.RuleListener { ); } + function skipCheckForRawImportIdentifiers(node: ASTNode): boolean { + if (options.ignoreImports) return false; + const parent = node.parent; + if (parent?.type !== 'ImportSpecifier') return false; + return parent.imported === node && parent.imported.name === parent.local.name; + } + function isImportedProperty(node: ASTNode): boolean { const obj = findOriginObject(node); return !!obj && obj.type === 'Identifier' && importedIdentifiers.has(obj.name); } + function isObjectProperty(node: ASTNode): boolean { + return node.parent?.type === 'MemberExpression'; + } + function reportIssue(issue: ValidationIssue) { const messageId: MessageIds = issue.isFlagged ? 'wordForbidden' : 'wordUnknown'; const data = { diff --git a/packages/cspell-eslint-plugin/src/index.test.ts b/packages/cspell-eslint-plugin/src/index.test.ts index d6d885899f8..c2691ad341a 100644 --- a/packages/cspell-eslint-plugin/src/index.test.ts +++ b/packages/cspell-eslint-plugin/src/index.test.ts @@ -94,12 +94,20 @@ ruleTester.run('cspell', Rule.rules.spellchecker, { 'Unknown word: "muawhahaha"', 'Unknown word: "grrrrr"', 'Unknown word: "muawhahaha"', + 'Unknown word: "muawhahaha"', 'Unknown word: "uuuug"', ], { ignoreImports: false, } ), + readInvalid( + 'with-errors/imports.ts', + ['Unknown word: "grrrrr"', 'Unknown word: "muawhahaha"', 'Unknown word: "uuuug"'], + { + ignoreImportProperties: false, + } + ), ], }); diff --git a/packages/cspell-eslint-plugin/src/options.ts b/packages/cspell-eslint-plugin/src/options.ts index 2c83da39047..2f0161a1ddf 100644 --- a/packages/cspell-eslint-plugin/src/options.ts +++ b/packages/cspell-eslint-plugin/src/options.ts @@ -25,7 +25,20 @@ export interface Check { */ ignoreImports?: boolean; /** - * Spell check identifiers (variables names, function names, and class names) + * Ignore the properties of imported variables, structures, and types. + * + * Example: + * ``` + * import { example } from 'third-party'; + * + * const msg = example.property; // `property` is not spell checked. + * ``` + * + * @default true + */ + ignoreImportProperties?: boolean; + /** + * Spell check identifiers (variables names, function names, class names, etc.) * @default true */ checkIdentifiers?: boolean; @@ -46,22 +59,23 @@ export interface Check { checkComments?: boolean; } -export const defaultCheckOptions: Check = { +export const defaultCheckOptions: Required = { checkComments: true, checkIdentifiers: true, checkStrings: true, checkStringTemplates: true, ignoreImports: true, + ignoreImportProperties: true, }; -export const defaultOptions: Options = { +export const defaultOptions: Required = { ...defaultCheckOptions, numSuggestions: 8, generateSuggestions: true, debugMode: false, }; -export function normalizeOptions(opts: Options | undefined): Options { - const options: Options = Object.assign({}, defaultOptions, opts || {}); +export function normalizeOptions(opts: Options | undefined): Required { + const options: Required = Object.assign({}, defaultOptions, opts || {}); return options; } From d1ee63b104e47e8c4616c3bfa0bf49099e7d37a2 Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 13 Mar 2022 10:37:41 +0100 Subject: [PATCH 4/5] fix: Make sure import aliases are checked. --- .../fixtures/with-errors/creepyData.ts | 2 ++ .../fixtures/with-errors/importAlias.ts | 5 ++++ .../src/cspell-eslint-plugin.ts | 24 +++++++++++++++---- .../cspell-eslint-plugin/src/index.test.ts | 23 +++++++++++++----- .../fixtures/creepyData.ts | 2 ++ .../fixtures/importAlias.ts | 5 ++++ 6 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 packages/cspell-eslint-plugin/fixtures/with-errors/importAlias.ts create mode 100644 test-packages/test-cspell-eslint-plugin/fixtures/importAlias.ts diff --git a/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts b/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts index e0606369a59..fd1da2db515 100644 --- a/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts +++ b/packages/cspell-eslint-plugin/fixtures/with-errors/creepyData.ts @@ -11,6 +11,8 @@ export const expressions: CreepyExpressions = { }; export const muawhahaha = expressions.muawhahaha; +export const uuug = expressions.uuuug; +export const grrr = expressions.grrrrr; export enum ExpressionCategory { MUAWHAHAHA = 0, diff --git a/packages/cspell-eslint-plugin/fixtures/with-errors/importAlias.ts b/packages/cspell-eslint-plugin/fixtures/with-errors/importAlias.ts new file mode 100644 index 00000000000..3f20efaa0db --- /dev/null +++ b/packages/cspell-eslint-plugin/fixtures/with-errors/importAlias.ts @@ -0,0 +1,5 @@ +import { uuug as uuug, muawhahaha as evilLaugh, grrr } from './creepyData'; + +console.log(uuug); +console.log(evilLaugh); +console.log(grrr); diff --git a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts index d2c1bc0dd24..08fe58935d0 100644 --- a/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts +++ b/packages/cspell-eslint-plugin/src/cspell-eslint-plugin.ts @@ -4,7 +4,7 @@ import assert from 'assert'; import { createTextDocument, CSpellSettings, DocumentValidator, ValidationIssue } from 'cspell-lib'; import type { Rule } from 'eslint'; // eslint-disable-next-line node/no-missing-import -import type { Comment, Identifier, Literal, Node, TemplateElement } from 'estree'; +import type { Comment, Identifier, Literal, Node, TemplateElement, ImportSpecifier } from 'estree'; import { format } from 'util'; import { normalizeOptions } from './options'; import optionsSchema from './_auto_generated_/options.schema.json'; @@ -90,6 +90,10 @@ function create(context: Rule.RuleContext): Rule.RuleListener { } if (isImportIdentifier(node)) { importedIdentifiers.add(node.name); + if (isLocalImportIdentifierUnique(node)) { + checkNodeText(node, node.name); + } + return; } else if (options.ignoreImportProperties && isImportedProperty(node)) { return; } @@ -142,11 +146,23 @@ function create(context: Rule.RuleContext): Rule.RuleListener { ); } + function isLocalImportIdentifierUnique(node: ASTNode): boolean { + const parent = getImportParent(node); + if (!parent) return true; + const { imported, local } = parent; + if (imported.name !== local.name) return true; + return imported.range?.[0] !== local.range?.[0] && imported.range?.[1] !== local.range?.[1]; + } + + function getImportParent(node: ASTNode): ImportSpecifier | undefined { + const parent = node.parent; + return parent?.type === 'ImportSpecifier' ? parent : undefined; + } + function skipCheckForRawImportIdentifiers(node: ASTNode): boolean { if (options.ignoreImports) return false; - const parent = node.parent; - if (parent?.type !== 'ImportSpecifier') return false; - return parent.imported === node && parent.imported.name === parent.local.name; + const parent = getImportParent(node); + return !!parent && parent.imported === node && !isLocalImportIdentifierUnique(node); } function isImportedProperty(node: ASTNode): boolean { diff --git a/packages/cspell-eslint-plugin/src/index.test.ts b/packages/cspell-eslint-plugin/src/index.test.ts index c2691ad341a..f1119011560 100644 --- a/packages/cspell-eslint-plugin/src/index.test.ts +++ b/packages/cspell-eslint-plugin/src/index.test.ts @@ -97,16 +97,27 @@ ruleTester.run('cspell', Rule.rules.spellchecker, { 'Unknown word: "muawhahaha"', 'Unknown word: "uuuug"', ], - { - ignoreImports: false, - } + { ignoreImports: false } ), readInvalid( 'with-errors/imports.ts', ['Unknown word: "grrrrr"', 'Unknown word: "muawhahaha"', 'Unknown word: "uuuug"'], - { - ignoreImportProperties: false, - } + { ignoreImportProperties: false } + ), + // cspell:ignore uuug + readInvalid('with-errors/importAlias.ts', ['Unknown word: "uuug"']), + readInvalid('with-errors/importAlias.ts', ['Unknown word: "uuug"'], { ignoreImportProperties: false }), + readInvalid( + 'with-errors/importAlias.ts', + [ + 'Unknown word: "uuug"', + 'Unknown word: "uuug"', + 'Unknown word: "muawhahaha"', + 'Unknown word: "grrr"', + 'Unknown word: "uuug"', + 'Unknown word: "grrr"', + ], + { ignoreImports: false } ), ], }); diff --git a/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts b/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts index e0606369a59..fd1da2db515 100644 --- a/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts +++ b/test-packages/test-cspell-eslint-plugin/fixtures/creepyData.ts @@ -11,6 +11,8 @@ export const expressions: CreepyExpressions = { }; export const muawhahaha = expressions.muawhahaha; +export const uuug = expressions.uuuug; +export const grrr = expressions.grrrrr; export enum ExpressionCategory { MUAWHAHAHA = 0, diff --git a/test-packages/test-cspell-eslint-plugin/fixtures/importAlias.ts b/test-packages/test-cspell-eslint-plugin/fixtures/importAlias.ts new file mode 100644 index 00000000000..3f20efaa0db --- /dev/null +++ b/test-packages/test-cspell-eslint-plugin/fixtures/importAlias.ts @@ -0,0 +1,5 @@ +import { uuug as uuug, muawhahaha as evilLaugh, grrr } from './creepyData'; + +console.log(uuug); +console.log(evilLaugh); +console.log(grrr); From fc994b4fd1441dccd8cfd60f595fd01785c0e16c Mon Sep 17 00:00:00 2001 From: Jason Dent Date: Sun, 13 Mar 2022 10:39:56 +0100 Subject: [PATCH 5/5] Update index.test.ts --- packages/cspell-eslint-plugin/src/index.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cspell-eslint-plugin/src/index.test.ts b/packages/cspell-eslint-plugin/src/index.test.ts index f1119011560..4afaebf2341 100644 --- a/packages/cspell-eslint-plugin/src/index.test.ts +++ b/packages/cspell-eslint-plugin/src/index.test.ts @@ -104,7 +104,7 @@ ruleTester.run('cspell', Rule.rules.spellchecker, { ['Unknown word: "grrrrr"', 'Unknown word: "muawhahaha"', 'Unknown word: "uuuug"'], { ignoreImportProperties: false } ), - // cspell:ignore uuug + // cspell:ignore uuug grrr readInvalid('with-errors/importAlias.ts', ['Unknown word: "uuug"']), readInvalid('with-errors/importAlias.ts', ['Unknown word: "uuug"'], { ignoreImportProperties: false }), readInvalid(