Skip to content

Commit

Permalink
fix: Try to detect some common bad regex patterns and fix them.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Feb 18, 2020
1 parent ff86c53 commit 822da97
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 9 deletions.
66 changes: 65 additions & 1 deletion packages/_server/src/documentSettings.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { DocumentSettings, isUriAllowed, isUriBlackListed } from './documentSettings';
import { DocumentSettings, isUriAllowed, isUriBlackListed, debugExports, correctBadSettings } from './documentSettings';
import { Connection, WorkspaceFolder } from 'vscode-languageserver';
import { getWorkspaceFolders, getConfiguration } from './vscode.config';
import * as Path from 'path';
import { URI as Uri } from 'vscode-uri';
import * as cspell from 'cspell-lib';
import { Pattern, CSpellUserSettings } from 'cspell-lib';
import * as os from 'os';

jest.mock('vscode-languageserver');
jest.mock('./vscode.config');
Expand Down Expand Up @@ -89,7 +92,68 @@ describe('Validate DocumentSettings', () => {
expect(result).toBe(false);
});

test('resolvePath', () => {
expect(debugExports.resolvePath(__dirname)).toBe(__dirname);
expect(debugExports.resolvePath('~')).toBe(os.homedir());
});

function newDocumentSettings() {
return new DocumentSettings({} as Connection, {});
}
});

describe('Validate RegExp corrections', () => {
test('fixRegEx', () => {
const defaultSettings = cspell.getDefaultSettings();
// Make sure it doesn't change the defaults.
expect(defaultSettings.patterns?.map(p => p.pattern).map(debugExports.fixRegEx))
.toEqual(defaultSettings.patterns?.map(p => p.pattern));
const sampleRegEx: Pattern[] = [
'/#.*/',
'/"""(.*?\\n?)+?"""/g',
'/\'\'\'(.*?\\n?)+?\'\'\'/g',
'strings',
];
const expectedRegEx: Pattern[] = [
'/#.*/',
'/(""")[^\\1]*?\\1/g',
"/(''')[^\\1]*?\\1/g",
'strings',
];
expect(sampleRegEx.map(debugExports.fixRegEx)).toEqual(expectedRegEx);
});

test('fixPattern', () => {
const defaultSettings = cspell.getDefaultSettings();
// Make sure it doesn't change the defaults.
expect(defaultSettings.patterns?.map(debugExports.fixPattern))
.toEqual(defaultSettings.patterns);

});

test('fixPattern', () => {
const defaultSettings = cspell.getDefaultSettings();
// Make sure it doesn't change the defaults.
expect(correctBadSettings(defaultSettings))
.toEqual(defaultSettings);

const settings: CSpellUserSettings = {
patterns: [
{
name: 'strings',
pattern: '/"""(.*?\\n?)+?"""/g',
}
]
};
const expectedSettings: CSpellUserSettings = {
patterns: [
{
name: 'strings',
pattern: '/(""")[^\\1]*?\\1/g',
}
]
};
expect(correctBadSettings(settings)).toEqual(expectedSettings);
expect(correctBadSettings(settings)).not.toEqual(settings);
});
});
50 changes: 44 additions & 6 deletions packages/_server/src/documentSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { Connection, TextDocumentUri, getWorkspaceFolders, getConfiguration } fr
import * as vscode from 'vscode-languageserver';
import {
ExcludeFilesGlobMap,
Glob
Glob,
RegExpPatternDefinition,
Pattern
} from 'cspell-lib';
import * as path from 'path';
import * as fs from 'fs-extra';
Expand Down Expand Up @@ -86,7 +88,7 @@ export class DocumentSettings {
}

resetSettings() {
log(`resetSettings`);
log('resetSettings');
CSpell.clearCachedSettings();
this.cachedValues.forEach(cache => cache.clear());
this._version += 1;
Expand All @@ -97,7 +99,7 @@ export class DocumentSettings {
}

private _importSettings() {
log(`importSettings`);
log('importSettings');
const importPaths = [...this.configsToImport.keys()].sort();
return readSettingsFiles(importPaths);
}
Expand Down Expand Up @@ -212,7 +214,7 @@ function configPathsForRoot(workspaceRootUri?: string) {
}

function resolveConfigImports(config: CSpellUserSettings, folderUri: string): CSpellUserSettings {
log(`resolveConfigImports:`, folderUri);
log('resolveConfigImports:', folderUri);
const uriFsPath = Uri.parse(folderUri).fsPath;
const imports = typeof config.import === 'string' ? [config.import] : config.import || [];
const importAbsPath = imports.map(file => resolvePath(uriFsPath, file));
Expand All @@ -229,9 +231,9 @@ function _readSettingsForFolderUri(folderUri: string): CSpellUserSettings {
}

function readSettingsFiles(paths: string[]) {
log(`readSettingsFiles:`, paths);
log('readSettingsFiles:', paths);
const existingPaths = paths.filter(filename => exists(filename));
log(`readSettingsFiles actual:`, existingPaths);
log('readSettingsFiles actual:', existingPaths);
return existingPaths.length ? CSpell.readSettingsFiles(existingPaths) : {};
}

Expand Down Expand Up @@ -261,3 +263,39 @@ export function doesUriMatchAnyScheme(uri: string, schemes: string[]): boolean {
const schema = Uri.parse(uri).scheme;
return schemes.findIndex(v => v === schema) >= 0;
}

const correctRegExMap = new Map([
['/"""(.*?\\n?)+?"""/g', '/(""")[^\\1]*?\\1/g'],
["/'''(.*?\\n?)+?'''/g", "/(''')[^\\1]*?\\1/g"],
]);

function fixRegEx(pat: Pattern): Pattern {
if (typeof pat != 'string') {
return pat;
}
return correctRegExMap.get(pat) || pat;
}

function fixPattern(pat: RegExpPatternDefinition): RegExpPatternDefinition {
const pattern = fixRegEx(pat.pattern);
if (pattern === pat.pattern) {
return pat;
}
return {...pat, pattern};
}

export function correctBadSettings(settings: CSpellUserSettings): CSpellUserSettings {
const newSettings = {...settings};

// Fix patterns
newSettings.patterns = newSettings?.patterns?.map(fixPattern);
newSettings.ignoreRegExpList = newSettings?.ignoreRegExpList?.map(fixRegEx);
newSettings.includeRegExpList = newSettings?.includeRegExpList?.map(fixRegEx);
return newSettings;
}

export const debugExports = {
fixRegEx,
fixPattern,
resolvePath,
};
5 changes: 3 additions & 2 deletions packages/_server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import * as CSpell from 'cspell-lib';
import { CSpellUserSettings } from './cspellConfig';
import { getDefaultSettings } from 'cspell-lib';
import * as Api from './api';
import { DocumentSettings, SettingsCspell, isUriAllowed, isUriBlackListed } from './documentSettings';
import { DocumentSettings, SettingsCspell, isUriAllowed, isUriBlackListed, correctBadSettings } from './documentSettings';
import {
log,
logError,
Expand Down Expand Up @@ -290,7 +290,8 @@ function run() {
if (settingsToUse.enabled) {
logInfo('Validate File', uri);
log(`validateTextDocument start: v${doc.version}`, uri);
const diagnostics = await Validator.validateTextDocument(doc, settingsToUse);
const settings = correctBadSettings(settingsToUse);
const diagnostics = await Validator.validateTextDocument(doc, settings);
log(`validateTextDocument done: v${doc.version}`, uri);
return { uri, diagnostics };
}
Expand Down

0 comments on commit 822da97

Please sign in to comment.