Skip to content

Commit

Permalink
fix: In Document settings. (#1925)
Browse files Browse the repository at this point in the history
* fix: #1628

* fix: #1629

* Update InDocSettings.test.ts
  • Loading branch information
Jason3S committed Oct 30, 2021
1 parent 165410a commit 01c12ce
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 85 deletions.
155 changes: 86 additions & 69 deletions packages/cspell-lib/src/Settings/InDocSettings.test.ts
Expand Up @@ -2,6 +2,65 @@ import * as Text from '../util/text';
import * as TextRange from '../util/TextRange';
import * as InDoc from './InDocSettings';

const oc = expect.objectContaining;

// cSpell:ignore faullts straange
// cSpell:ignoreRegExp \w+s{4}\w+
// cSpell:ignoreRegExp /\/\/\/.*/
// cSpell:ignoreRegExp weird
const sampleCode = `
// cSpell:enableCompoundWords
// cSpell:disableCompoundWords
// cSpell: enableCOMPOUNDWords
// cSpell:words whiteberry, redberry, lightbrown
// cSpell: ignoreRegExp /\\/\\/\\/.*/
// cSpell:ignoreRegexp w\\w+berry
// cSpell::ignoreRegExp /
/* cSpell:ignoreRegExp \\w+s{4}\\w+ */
/* cSpell:ignoreRegExp /faullts[/]?/ */
const berries = ['whiteberry', 'redberry', 'blueberry'];
/* cSpell:ignore tripe, comment */
// cSpell:: ignoreWords tooo faullts
/// ignore triple comment, with misssspellings and faullts
/// mooree prooobleems onn thisss line tooo with wordberry
// misssspellings faullts
// weirdberry can be straange.
// cSpell:language en-US
// cspell:local
// cspell:locale es-ES
// cspell:local en, nl
// cspell:dictionaries lorem-ipsum
// LocalWords: one two three
// LocalWords:four five six
// localwords: seven eight nine
`;

// cspell:ignore againxx
const sampleText = `
# cSpell:disableCompoundWords
# cSpell:enableCOMPOUNDWords
# happydays arehere againxx
`;

// cspell:ignore popoutlist
const sampleTextWithIncompleteInDocSetting = `
// spell:dictionaries php
// spell:words const
// cspell:
// cspell:ignore popoutlist
const x = imp.popoutlist;
// cspell:ignore again
`;

// cspell:disable
const sampleTextWithBadRegexp = `
# cspell\x3AignoreRegExp "(foobar|foo_baz)"');
`;
// cspell:enable

describe('Validate InDocSettings', () => {
test('tests matching settings', () => {
const matches = InDoc.internal
Expand All @@ -11,48 +70,52 @@ describe('Validate InDocSettings', () => {
expect(matches.map((a) => a[0])).toEqual([
'enableCompoundWords',
'disableCompoundWords',
'enableCOMPOUNDWords',
' enableCOMPOUNDWords',
'words whiteberry, redberry, lightbrown',
'ignoreRegExp /\\/\\/\\/.*/',
' ignoreRegExp /\\/\\/\\/.*/',
'ignoreRegexp w\\w+berry',
'ignoreRegExp /',
'ignoreRegExp \\w+s{4}\\w+ */',
'ignoreRegExp /faullts[/]?/ */',
'ignore tripe, comment */',
'ignoreWords tooo faullts',
' ignoreWords tooo faullts',
'language en-US',
'local',
'locale es-ES',
'local en, nl',
'dictionaries lorem-ipsum',
'LocalWords: one two three',
'LocalWords:four five six',
]);
});

test('tests extracting in file settings for compound words', () => {
expect(InDoc.getInDocumentSettings('')).toEqual({ id: 'in-doc-settings' });
// 'cSpell:enableCompoundWords'
expect(InDoc.getInDocumentSettings('cSpell:enableCompoundWords').allowCompoundWords).toBe(true);
// 'cSpell:ENABLECompoundWords'
expect(InDoc.getInDocumentSettings('cSpell:ENABLECompoundWords').allowCompoundWords).toBe(true);
// 'cSpell:disableCompoundWords'
expect(InDoc.getInDocumentSettings('cSpell:disableCompoundWords').allowCompoundWords).toBe(false);
// 'cSpell:disableCompoundWORDS'
expect(InDoc.getInDocumentSettings('cSpell:disableCompoundWORDS').allowCompoundWords).toBe(false);
expect(
InDoc.getInDocumentSettings('cSpell:ENABLECompoundWords\ncSpell:disableCompoundWords').allowCompoundWords
).toBe(false);
expect(
InDoc.getInDocumentSettings('cSpell:disableCompoundWords\ncSpell:enableCompoundWords').allowCompoundWords
).toBe(true);
expect(InDoc.getInDocumentSettings(sampleText).allowCompoundWords).toBe(true);
expect(InDoc.getInDocumentSettings(sampleCode).allowCompoundWords).toBe(true);
test.each`
test | text | expected
${'Empty Doc'} | ${''} | ${{ id: 'in-doc-settings' }}
${'cSpell:enableCompoundWords'} | ${'cSpell:enableCompoundWords'} | ${oc({ allowCompoundWords: true })}
${'cSpell:ENABLECompoundWords'} | ${'cSpell:ENABLECompoundWords'} | ${oc({ allowCompoundWords: true })}
${'cSpell:disableCompoundWords'} | ${'cSpell:disableCompoundWords'} | ${oc({ allowCompoundWords: false })}
${'cSpell:disableCompoundWORDS'} | ${'cSpell:disableCompoundWORDS'} | ${oc({ allowCompoundWords: false })}
${'cSpell:ENABLECompoundWords\ncSpell:disableCompoundWords'} | ${'cSpell:ENABLECompoundWords\ncSpell:disableCompoundWords'} | ${oc({ allowCompoundWords: false })}
${'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);
});

test.each`
test | text | expected
${'Empty Doc'} | ${''} | ${{ id: 'in-doc-settings' }}
${'sampleTextWithIncompleteInDocSetting'} | ${sampleTextWithIncompleteInDocSetting} | ${oc({ words: ['const'], ignoreWords: ['popoutlist', 'again'], dictionaries: ['php'] })}
`('extract setting: $test', ({ text, expected }) => {
expect(InDoc.getInDocumentSettings(text)).toEqual(expected);
});

test('tests finding words to add to dictionary', () => {
const words = InDoc.internal.getWordsFromDocument(sampleCode);
// we match to the end of the line, so the */ is included.
expect(words).toEqual(['whiteberry', 'redberry', 'lightbrown', 'one', 'two', 'three']);
expect(words).toEqual(['whiteberry', 'redberry', 'lightbrown', 'one', 'two', 'three', 'four', 'five', 'six']);
expect(InDoc.getIgnoreWordsFromDocument('Hello')).toEqual([]);
});

Expand All @@ -74,7 +137,7 @@ describe('Validate InDocSettings', () => {

test('fetching the local for the text', () => {
const settings = InDoc.getInDocumentSettings(sampleCode);
expect(settings.language).toBe('en, nl');
expect(settings.language).toBe('en,nl');
});

test('setting dictionaries for file', () => {
Expand All @@ -91,52 +154,6 @@ describe('Validate InDocSettings', () => {
);
});
});
// cSpell:ignore faullts straange
// cSpell:ignoreRegExp \w+s{4}\w+
// cSpell:ignoreRegExp /\/\/\/.*/
// cSpell:ignoreRegExp weird
const sampleCode = `
// cSpell:enableCompoundWords
// cSpell:disableCompoundWords
// cSpell: enableCOMPOUNDWords
// cSpell:words whiteberry, redberry, lightbrown
// cSpell: ignoreRegExp /\\/\\/\\/.*/
// cSpell:ignoreRegexp w\\w+berry
// cSpell::ignoreRegExp /
/* cSpell:ignoreRegExp \\w+s{4}\\w+ */
/* cSpell:ignoreRegExp /faullts[/]?/ */
const berries = ['whiteberry', 'redberry', 'blueberry'];
/* cSpell:ignore tripe, comment */
// cSpell:: ignoreWords tooo faullts
/// ignore triple comment, with misssspellings and faullts
/// mooree prooobleems onn thisss line tooo with wordberry
// misssspellings faullts
// weirdberry can be straange.
// cSpell:language en-US
// cspell:local
// cspell:locale es-ES
// cspell:local en, nl
// cspell:dictionaries lorem-ipsum
// LocalWords: one two three
// LocalWords:four five six
// localwords: seven eight nine
`;

// cspell:ignore againxx
const sampleText = `
# cSpell:disableCompoundWords
# cSpell:enableCOMPOUNDWords
# happydays arehere againxx
`;

// cspell:disable
const sampleTextWithBadRegexp = `
# cspell\x3AignoreRegExp "(foobar|foo_baz)"');
`;
// cspell:enable

// cspell:disableCompoundWords
// cspell:ignore localwords happydays arehere
17 changes: 9 additions & 8 deletions packages/cspell-lib/src/Settings/InDocSettings.ts
Expand Up @@ -5,7 +5,7 @@ import { mergeInDocSettings } from './CSpellSettingsServer';

// cspell:ignore gimuy
const regExMatchRegEx = /\/.*\/[gimuy]*/;
const regExInFileSettings = [/(?:spell-?checker|cSpell)::?\s*(.*)/gi, /(LocalWords:?\s+.*)/g];
const regExInFileSettings = [/(?:spell-?checker|c?spell)::?(.*)/gi, /(LocalWords:?.*)/g];

export type CSpellUserSettingsKeys = keyof CSpellUserSettings;

Expand All @@ -22,17 +22,18 @@ export function getInDocumentSettings(text: string): CSpellUserSettings {
}

function parseSettingMatch(matchArray: RegExpMatchArray): CSpellUserSettings[] {
const [, possibleSetting = ''] = matchArray;
const [, match = ''] = matchArray;
const possibleSetting = match.trim();
const settingParsers: [RegExp, (m: string) => CSpellUserSettings][] = [
[/^(?:enable|disable)(?:allow)?CompoundWords/i, parseCompoundWords],
[/^words?\s/i, parseWords],
[/^ignore(?:words?)?\s/i, parseIgnoreWords],
[/^ignore_?Reg_?Exp\s+.+$/i, parseIgnoreRegExp],
[/^include_?Reg_?Exp\s+.+$/i, parseIncludeRegExp],
[/^locale?\s/i, parseLocal],
[/^language\s/i, parseLocal],
[/^locale?\s/i, parseLocale],
[/^language\s/i, parseLocale],
[/^dictionaries\s/i, parseDictionaries],
[/^LocalWords:/, parseWords],
[/^LocalWords:/, (w) => parseWords(w.replace(/LocalWords:?/gi, ' '))],
];

return settingParsers
Expand All @@ -51,9 +52,9 @@ function parseWords(match: string): CSpellUserSettings {
return { id: 'in-doc-words', words };
}

function parseLocal(match: string): CSpellUserSettings {
const parts = match.trim().split(/\s+/);
const language = parts.slice(1).join(' ');
function parseLocale(match: string): CSpellUserSettings {
const parts = match.trim().split(/[\s,]+/);
const language = parts.slice(1).join(',');
return language ? { id: 'in-doc-local', language } : {};
}

Expand Down
15 changes: 13 additions & 2 deletions packages/cspell-lib/src/Settings/LanguageSettings.test.ts
Expand Up @@ -114,8 +114,19 @@ describe('Validate LanguageSettings', () => {
expect(langSet).toContain('literate haskell');
});

test('tests locale matching', () => {
const localeSet = LS.normalizeLocale('en, en-GB, fr-fr, nl_NL');
// cspell:ignore engb frfr nlnl
test.each`
locales | expected
${''} | ${[]}
${'en, en-GB, fr-fr, nl_NL'} | ${['en', 'engb', 'frfr', 'nlnl']}
${['en, en-GB', 'fr-fr, nl_NL']} | ${['en', 'engb', 'frfr', 'nlnl']}
`('normalizeLocale $locales', ({ locales, expected }) => {
const localeSet = LS.normalizeLocale(locales);
expect([...localeSet]).toEqual(expected);
});

test('normalizeLocale $locales', () => {
const localeSet = LS.normalizeLocale('en, en-GB, fr-fr,nl_NL');
expect(localeSet.has('en')).toBe(true);
expect(LS.isLocaleInSet('nl-nl', localeSet)).toBe(true);
expect(LS.isLocaleInSet('nl_nl', localeSet)).toBe(true);
Expand Down
19 changes: 13 additions & 6 deletions packages/cspell-lib/src/Settings/LanguageSettings.ts
Expand Up @@ -13,13 +13,20 @@ export function getDefaultLanguageSettings(): LanguageSettings {
return defaultLanguageSettings;
}

function localesToList(locales: string | string[]): string[] {
locales = typeof locales !== 'string' ? locales.join(',') : locales;
return stringToList(locales.replace(/\s+/g, ','));
}

function stringToList(sList: string | string[]): string[] {
if (typeof sList === 'string') {
sList = sList
.replace(/[|;]/g, ',')
.split(',')
.map((s) => s.trim());
if (typeof sList !== 'string') {
sList = sList.join(',');
}
sList = sList
.replace(/[|;]/g, ',')
.split(',')
.map((s) => s.trim())
.filter((s) => !!s);
return sList;
}

Expand All @@ -33,7 +40,7 @@ function normalizeLanguageIdToString(langId: LanguageId | LanguageId[]): string
}

export function normalizeLocale(locale: LocaleId | LocaleId[]): Set<LocaleId> {
locale = stringToList(locale);
locale = localesToList(locale);
return new Set<LocaleId>(locale.map((locale) => locale.toLowerCase().replace(/[^a-z]/g, '')));
}

Expand Down

0 comments on commit 01c12ce

Please sign in to comment.