From 0f648cd7dbafdbbbefda0f23c61c6c48a8d77619 Mon Sep 17 00:00:00 2001 From: Johannes Date: Tue, 22 Mar 2022 16:02:11 +0100 Subject: [PATCH] add eslint rule to disallow look behind regex feature, ignore in git and markdown fyi @lszomoru, @mjbvz --- .eslintignore | 1 + .eslintrc.json | 1 + build/lib/eslint/code-no-look-behind-regex.js | 42 +++++++++++++++ build/lib/eslint/code-no-look-behind-regex.ts | 52 +++++++++++++++++++ extensions/git/src/git.ts | 1 + .../src/features/documentLinkProvider.ts | 1 + .../src/test/inMemoryDocument.ts | 1 + 7 files changed, 99 insertions(+) create mode 100644 build/lib/eslint/code-no-look-behind-regex.js create mode 100644 build/lib/eslint/code-no-look-behind-regex.ts diff --git a/.eslintignore b/.eslintignore index 27603af2b5b..1c49d5b8846 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,6 +9,7 @@ **/extensions/markdown-language-features/media/** **/extensions/markdown-language-features/notebook-out/** **/extensions/markdown-math/notebook-out/** +**/extensions/notebook-renderers/renderer-out/index.js **/extensions/simple-browser/media/index.js **/extensions/typescript-language-features/test-workspace/** **/extensions/vscode-api-tests/testWorkspace/** diff --git a/.eslintrc.json b/.eslintrc.json index 4f6bbe81b13..22157840d84 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -194,6 +194,7 @@ "src/**/*.ts" ], "rules": { + "code-no-look-behind-regex": "warn", "code-import-patterns": [ "warn", { diff --git a/build/lib/eslint/code-no-look-behind-regex.js b/build/lib/eslint/code-no-look-behind-regex.js new file mode 100644 index 00000000000..7c9c624a407 --- /dev/null +++ b/build/lib/eslint/code-no-look-behind-regex.js @@ -0,0 +1,42 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ +const _positiveLookBehind = /\(\?<=.+/; +const _negativeLookBehind = /\(\? { + const pattern = node.regex?.pattern; + if (_containsLookBehind(pattern)) { + context.report({ + node, + message: 'Look behind assertions are not yet supported in all browsers' + }); + } + }, + // new Regex("...") + ['NewExpression[callee.name="RegExp"] Literal']: (node) => { + if (_containsLookBehind(node.value)) { + context.report({ + node, + message: 'Look behind assertions are not yet supported in all browsers' + }); + } + } + }; + } +}; diff --git a/build/lib/eslint/code-no-look-behind-regex.ts b/build/lib/eslint/code-no-look-behind-regex.ts new file mode 100644 index 00000000000..ef3959e39c6 --- /dev/null +++ b/build/lib/eslint/code-no-look-behind-regex.ts @@ -0,0 +1,52 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as eslint from 'eslint'; +import { TSESTree } from '@typescript-eslint/experimental-utils'; +import * as ESTree from 'estree'; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +const _positiveLookBehind = /\(\?<=.+/; +const _negativeLookBehind = /\(\? { + type RegexLiteral = TSESTree.Literal & { regex: { pattern: string; flags: string } }; + const pattern = (node).regex?.pattern; + if (_containsLookBehind(pattern)) { + context.report({ + node, + message: 'Look behind assertions are not yet supported in all browsers' + }); + } + }, + // new Regex("...") + ['NewExpression[callee.name="RegExp"] Literal']: (node: ESTree.Literal) => { + if (_containsLookBehind(node.value)) { + context.report({ + node, + message: 'Look behind assertions are not yet supported in all browsers' + }); + } + } + }; + } +}; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 39ed6847423..f45a31d983d 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -480,6 +480,7 @@ export class Git { const repoUri = Uri.file(repoPath); const pathUri = Uri.file(repositoryPath); if (repoUri.authority.length !== 0 && pathUri.authority.length === 0) { + // eslint-disable-next-line code-no-look-behind-regex let match = /(?<=^\/?)([a-zA-Z])(?=:\/)/.exec(pathUri.path); if (match !== null) { const [, letter] = match; diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index 9c028de7d90..7e4f7cb397b 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -104,6 +104,7 @@ export function stripAngleBrackets(link: string) { } const linkPattern = /(\[((!\[[^\]]*?\]\(\s*)([^\s\(\)]+?)\s*\)\]|(?:\\\]|[^\]])*\])\(\s*)(([^\s\(\)]|\([^\s\(\)]*?\))+)\s*(".*?")?\)/g; +// eslint-disable-next-line code-no-look-behind-regex const referenceLinkPattern = /((?<=^|[^\]])\[((?:\\\]|[^\]])+)\])(?!:)(?:[^\[]|$|\[\s*?([^\s\]]*?)\])/g; const definitionPattern = /^([\t ]*\[(?!\^)((?:\\\]|[^\]])+)\]:\s*)([^<]\S*|<[^>]+>)/gm; const inlineCodePattern = /(?:^|[^`])(`+)(?:.+?|.*?(?:(?:\r?\n).+?)*?)(?:\r?\n)?\1(?:$|[^`])/gm; diff --git a/extensions/markdown-language-features/src/test/inMemoryDocument.ts b/extensions/markdown-language-features/src/test/inMemoryDocument.ts index dc82d2f7ec2..08f11c2952b 100644 --- a/extensions/markdown-language-features/src/test/inMemoryDocument.ts +++ b/extensions/markdown-language-features/src/test/inMemoryDocument.ts @@ -48,6 +48,7 @@ export class InMemoryDocument implements vscode.TextDocument { const before = this._contents.slice(0, offset); const newLines = before.match(/\r\n|\n/g); const line = newLines ? newLines.length : 0; + // eslint-disable-next-line code-no-look-behind-regex const preCharacters = before.match(/(?<=\r\n|\n|^).*$/g); return new vscode.Position(line, preCharacters ? preCharacters[0].length : 0); }