Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add directive flag-word #3472

Merged
merged 2 commits into from Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
36 changes: 26 additions & 10 deletions packages/cspell-lib/src/Settings/InDocSettings.test.ts
Expand Up @@ -5,6 +5,7 @@ import * as InDoc from './InDocSettings';

const oc = expect.objectContaining;
const ac = expect.arrayContaining;
const nac = expect.not.arrayContaining;

// cSpell:ignore faullts straange
// cSpell:ignoreRegExp \w+s{4}\w+
Expand Down Expand Up @@ -91,6 +92,8 @@ describe('Validate InDocSettings', () => {
]);
});

const USE_TEST = undefined;

test.each`
test | text | expected
${'Empty Doc'} | ${''} | ${{ id: 'in-doc-settings' }}
Expand All @@ -102,8 +105,16 @@ describe('Validate InDocSettings', () => {
${'cSpell:disableCompoundWords\ncSpell:enableCompoundWords'} | ${'cSpell:disableCompoundWords\ncSpell:enableCompoundWords'} | ${oc({ allowCompoundWords: true })}
${'sampleText'} | ${sampleText} | ${oc({ allowCompoundWords: true })}
${'sampleCode'} | ${sampleCode} | ${oc({ allowCompoundWords: true })}
`('detect compound words setting: $test', ({ text, expected }) => {
expect(InDoc.getInDocumentSettings(text)).toEqual(expected);
${'cSpell:word apple'} | ${USE_TEST} | ${oc({ words: ['apple'] })}
${'/*cSpell:word apple*/'} | ${USE_TEST} | ${oc({ words: ['apple*'] })}
${'<!--- cSpell:word apple -->'} | ${USE_TEST} | ${oc({ words: ['apple', '-->'] })}
${'<!--- cSpell:ignoreWords apple -->'} | ${USE_TEST} | ${oc({ ignoreWords: ['apple', '-->'] })}
${'<!--- cSpell:forbidWords apple -->'} | ${USE_TEST} | ${oc({ flagWords: ['apple', '-->'] })}
${'<!--- cSpell:flag-words apple -->'} | ${USE_TEST} | ${oc({ flagWords: ['apple', '-->'] })}
${'# cspell:ignore auto* *labeler'} | ${USE_TEST} | ${oc({ ignoreWords: ['auto*', '*labeler'] })}
`('detect compound words setting: $test', ({ test, text, expected }) => {
expect(InDoc.getInDocumentSettings(text == USE_TEST ? test : text)).toEqual(expected);
expect([...InDoc.validateInDocumentSettings(text, {})]).toEqual([]);
});

test.each`
Expand All @@ -126,7 +137,7 @@ describe('Validate InDocSettings', () => {
test('tests finding words to ignore', () => {
const words = InDoc.getIgnoreWordsFromDocument(sampleCode);
// we match to the end of the line, so the */ is included.
expect(words).toEqual(['tripe', 'comment', '*/', 'tooo', 'faullts']);
expect(words).toEqual(['tripe', 'comment', '*', 'tooo', 'faullts']);
expect(InDoc.getIgnoreWordsFromDocument('Hello')).toEqual([]);
});

Expand Down Expand Up @@ -158,14 +169,19 @@ describe('Validate InDocSettings', () => {
);
});

// cspell:ignore dictionar lokal

test.each`
text | settings | expected
${''} | ${{}} | ${[]}
${'cspell: */'} | ${{}} | ${[]}
${'cspell: ignore x */'} | ${{}} | ${[]}
${'cspell:dictionary dutch'} | ${{}} | ${[oc({ range: [7, 17], suggestions: ac(['dictionaries']), text: 'dictionary' })]}
${'cspell::dictionary dutch'} | ${{}} | ${[oc({ range: [8, 18], suggestions: ac(['dictionaries']), text: 'dictionary' })]}
${'cspell: ignored */'} | ${{}} | ${[oc({ range: [8, 15], suggestions: ac(['ignore', 'ignoreWord']), text: 'ignored' })]}
text | settings | expected
${''} | ${{}} | ${[]}
${'cspell: */'} | ${{}} | ${[]}
${'cspell: ignore x */'} | ${{}} | ${[]}
${'cspell: word*/'} | ${{}} | ${[]}
${'cspell:dictionar dutch'} | ${{}} | ${[oc({ range: [7, 16], suggestions: ac(['dictionary', 'dictionaries']), text: 'dictionar' })]}
${'cspell::dictionar dutch'} | ${{}} | ${[oc({ range: [8, 17], suggestions: ac(['dictionary', 'dictionaries']), text: 'dictionar' })]}
${'cspell: ignored */'} | ${{}} | ${[oc({ range: [8, 15], suggestions: ac(['ignore', 'ignoreWord']), text: 'ignored' })]}
${'cspell:lokal en'} | ${{}} | ${[oc({ suggestions: ac(['locale']) })]}
${'cspell:lokal en'} | ${{}} | ${[oc({ suggestions: nac(['local']) })]}
`('validateInDocumentSettings', ({ text, settings, expected }) => {
const result = [...InDoc.validateInDocumentSettings(text, settings)];
expect(result).toEqual(expected);
Expand Down
41 changes: 34 additions & 7 deletions packages/cspell-lib/src/Settings/InDocSettings.ts
Expand Up @@ -25,11 +25,21 @@ const officialDirectives = [
'ignore',
'ignoreWord',
'ignoreWords',
'ignore-word',
'ignore-words',
'includeRegExp',
'ignoreRegExp',
'local', // Do not suggest.
'locale',
'language',
'dictionaries',
'dictionary',
'forbid',
'forbidWord',
'forbid-word',
'flag',
'flagWord',
'flag-word',
'enableCompoundWords',
'enableAllowCompoundWords',
'disableCompoundWords',
Expand All @@ -38,14 +48,18 @@ const officialDirectives = [
'disableCaseSensitive',
];

const noSuggestDirectives = new Set(['local']);

const preferredDirectives = [
'enable',
'disable',
'disable-line',
'disable-next-line',
'words',
'ignore',
'forbid',
'locale',
'dictionary',
'dictionaries',
'enableCaseSensitive',
'disableCaseSensitive',
Expand Down Expand Up @@ -95,14 +109,15 @@ const settingParsers: readonly (readonly [RegExp, (m: string) => CSpellUserSetti
[/^(?:enable|disable)CaseSensitive\b/i, parseCaseSensitive],
[/^enable\b(?!-)/i, parseEnable],
[/^disable(-line|-next(-line)?)?\b(?!-)/i, parseDisable],
[/^words?\s/i, parseWords],
[/^ignore(?:words?)?\s/i, parseIgnoreWords],
[/^words?\b/i, parseWords],
[/^ignore(?:-?words?)?\b/i, parseIgnoreWords],
[/^(?:flag|forbid)(?:-?words?)?\b/i, parseFlagWords],
[/^ignore_?Reg_?Exp\s+.+$/i, parseIgnoreRegExp],
[/^include_?Reg_?Exp\s+.+$/i, parseIncludeRegExp],
[/^locale?\s/i, parseLocale],
[/^locale?\b/i, parseLocale],
[/^language\s/i, parseLocale],
[/^dictionaries\s/i, parseDictionaries],
[/^LocalWords:/, (w) => parseWords(w.replace(/LocalWords:?/gi, ' '))],
[/^dictionar(?:y|ies)\b/i, parseDictionaries], // cspell:disable-line
[/^LocalWords:/, (w) => parseWords(w.replace(/^LocalWords:?/gi, ' '))],
] as const;

export const regExSpellingGuardBlock =
Expand Down Expand Up @@ -134,7 +149,10 @@ function parseSettingMatchValidation(matchArray: RegExpMatchArray): DirectiveIss
if (matchingParsers.length > 0) return undefined;

// No matches were found, let make some suggestions.
const dictSugs = dictInDocSettings.suggest(text, { ignoreCase: false }).map((sug) => sug.word);
const dictSugs = dictInDocSettings
.suggest(text, { ignoreCase: false })
.map((sug) => sug.word)
.filter((a) => !noSuggestDirectives.has(a));
const sugs = new Set(pipeSync(dictSugs, opAppend(allDirectives)));
const suggestions = [...sugs].slice(0, 8);

Expand Down Expand Up @@ -169,7 +187,11 @@ function parseCaseSensitive(match: string): CSpellUserSettings {
}

function parseWords(match: string): CSpellUserSettings {
const words = match.split(/[,\s]+/g).slice(1);
const words = match
.replace(/[@#$%^&={}/"]/g, ' ')
.split(/[,\s;]+/g)
.slice(1)
.filter((a) => !!a);
return { id: 'in-doc-words', words };
}

Expand All @@ -184,6 +206,11 @@ function parseIgnoreWords(match: string): CSpellUserSettings {
return clean({ id: 'in-doc-ignore', ignoreWords: wordsSetting.words });
}

function parseFlagWords(match: string): CSpellUserSettings {
const wordsSetting = parseWords(match);
return clean({ id: 'in-doc-forbid', flagWords: wordsSetting.words });
}

function parseRegEx(match: string): string[] {
const patterns = [match.replace(/^[^\s]+\s+/, '')].map((a) => {
const m = a.match(regExMatchRegEx);
Expand Down
Expand Up @@ -101,7 +101,7 @@ describe('docValidator', () => {
${fix('sample-with-many-errors.ts')} | ${undefined} | ${['reciever', 'naame', 'naame', 'naame', 'reciever', 'Reciever', 'naame', 'Reciever', 'naame', 'kount', 'Reciever', 'kount', 'colector', 'recievers', 'Reciever', 'recievers', 'recievers']} | ${undefined}
${fix('sample-with-many-errors.ts')} | ${1} | ${['reciever', 'naame', 'Reciever', 'kount', 'colector', 'recievers']} | ${undefined}
${fix('parser/sample.ts')} | ${1} | ${['serrors']} | ${['\\x73errors']}
${fix('sample-with-directives-errors.ts')} | ${1} | ${['disable-prev', 'dictionary', 'ignored', 'world', 'enable-line']} | ${undefined}
${fix('sample-with-directives-errors.ts')} | ${1} | ${['disable-prev', 'ignored', 'world', 'enable-line']} | ${undefined}
`(
'checkDocument $filename $maxDuplicateProblems',
async ({ filename, maxDuplicateProblems, expectedIssues, expectedRawIssues }) => {
Expand Down