mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add regex eslint plugin, fix lints (#59371)
This commit is contained in:
@@ -10678,7 +10678,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
else if (localName === InternalSymbolName.ExportEquals) {
|
||||
localName = "_exports";
|
||||
}
|
||||
localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-zA-Z0-9]/g, "_");
|
||||
localName = isIdentifierText(localName, languageVersion) && !isStringANonContextualKeyword(localName) ? localName : "_" + localName.replace(/[^a-z0-9]/gi, "_");
|
||||
return localName;
|
||||
}
|
||||
|
||||
@@ -34355,7 +34355,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function containerSeemsToBeEmptyDomElement(containingType: Type) {
|
||||
return (compilerOptions.lib && !compilerOptions.lib.includes("dom")) &&
|
||||
everyContainedType(containingType, type => type.symbol && /^(EventTarget|Node|((HTML[a-zA-Z]*)?Element))$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) &&
|
||||
everyContainedType(containingType, type => type.symbol && /^(?:EventTarget|Node|(?:HTML[a-zA-Z]*)?Element)$/.test(unescapeLeadingUnderscores(type.symbol.escapedName))) &&
|
||||
isEmptyObjectType(containingType);
|
||||
}
|
||||
|
||||
|
||||
@@ -3762,7 +3762,7 @@ function convertJsonOptionOfListType(
|
||||
* \*\* # matches the recursive directory wildcard "**".
|
||||
* \/?$ # matches an optional trailing directory separator at the end of the string.
|
||||
*/
|
||||
const invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/;
|
||||
const invalidTrailingRecursionPattern = /(?:^|\/)\*\*\/?$/;
|
||||
|
||||
/**
|
||||
* Matches the portion of a wildcard path that does not contain wildcards.
|
||||
|
||||
@@ -581,7 +581,7 @@ export namespace Debug {
|
||||
// This regex can trigger slow backtracking because of overlapping potential captures.
|
||||
// We don't care, this is debug code that's only enabled with a debugger attached -
|
||||
// we're just taking note of it for anyone checking regex performance in the future.
|
||||
defaultValue = String(defaultValue).replace(/(?:,[\s\w\d_]+:[^,]+)+\]$/, "]");
|
||||
defaultValue = String(defaultValue).replace(/(?:,[\s\w]+:[^,]+)+\]$/, "]");
|
||||
return `NodeArray ${defaultValue}`;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4005,7 +4005,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
if (node.comment) {
|
||||
const text = getTextOfJSDocComment(node.comment);
|
||||
if (text) {
|
||||
const lines = text.split(/\r\n?|\n/g);
|
||||
const lines = text.split(/\r\n?|\n/);
|
||||
for (const line of lines) {
|
||||
writeLine();
|
||||
writeSpace();
|
||||
@@ -4880,7 +4880,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
|
||||
}
|
||||
|
||||
function writeLines(text: string): void {
|
||||
const lines = text.split(/\r\n?|\n/g);
|
||||
const lines = text.split(/\r\n?|\n/);
|
||||
const indentation = guessIndentation(lines);
|
||||
for (const lineText of lines) {
|
||||
const line = indentation ? lineText.slice(indentation) : lineText;
|
||||
|
||||
@@ -10653,8 +10653,8 @@ function getNamedArgRegEx(name: string): RegExp {
|
||||
return result;
|
||||
}
|
||||
|
||||
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
|
||||
const singleLinePragmaRegEx = /^\/\/\/?\s*@([^\s:]+)(.*)\s*$/im;
|
||||
const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/m;
|
||||
const singleLinePragmaRegEx = /^\/\/\/?\s*@([^\s:]+)((?:[^\S\r\n]|:).*)?$/m;
|
||||
function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) {
|
||||
const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
|
||||
if (tripleSlash) {
|
||||
@@ -10700,7 +10700,7 @@ function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, te
|
||||
}
|
||||
|
||||
if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
|
||||
const multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
|
||||
const multiLinePragmaRegEx = /@(\S+)(\s+(?:\S.*)?)?$/gm; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
|
||||
let multiLineMatch: RegExpExecArray | null; // eslint-disable-line no-restricted-syntax
|
||||
while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
|
||||
addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
|
||||
|
||||
@@ -98,7 +98,7 @@ export function pathIsAbsolute(path: string): boolean {
|
||||
* @internal
|
||||
*/
|
||||
export function pathIsRelative(path: string): boolean {
|
||||
return /^\.\.?($|[\\/])/.test(path);
|
||||
return /^\.\.?(?:$|[\\/])/.test(path);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,7 +779,7 @@ export function changeFullExtension(path: string, newExtension: string) {
|
||||
//// Path Comparisons
|
||||
|
||||
// check path for these segments: '', '.'. '..'
|
||||
const relativePathSegmentRegExp = /(?:\/\/)|(?:^|\/)\.\.?(?:$|\/)/;
|
||||
const relativePathSegmentRegExp = /\/\/|(?:^|\/)\.\.?(?:$|\/)/;
|
||||
|
||||
function comparePathsWorker(a: string, b: string, componentComparer: (a: string, b: string) => Comparison) {
|
||||
if (a === b) return Comparison.EqualTo;
|
||||
|
||||
@@ -3109,7 +3109,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
|
||||
|
||||
// Stop searching if the line is not empty and not a comment
|
||||
const lineText = file.text.slice(lineStarts[line], lineStarts[line + 1]).trim();
|
||||
if (lineText !== "" && !/^(\s*)\/\/(.*)$/.test(lineText)) {
|
||||
if (lineText !== "" && !/^\s*\/\/.*$/.test(lineText)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -267,11 +267,11 @@ function perceivedOsRootLengthForWatching(pathComponents: Readonly<PathPathCompo
|
||||
// Ignore "/", "c:/"
|
||||
if (length <= 1) return 1;
|
||||
let indexAfterOsRoot = 1;
|
||||
let isDosStyle = pathComponents[0].search(/[a-zA-Z]:/) === 0;
|
||||
let isDosStyle = pathComponents[0].search(/[a-z]:/i) === 0;
|
||||
if (
|
||||
pathComponents[0] !== directorySeparator &&
|
||||
!isDosStyle && // Non dos style paths
|
||||
pathComponents[1].search(/[a-zA-Z]\$$/) === 0 // Dos style nextPart
|
||||
pathComponents[1].search(/[a-z]\$$/i) === 0 // Dos style nextPart
|
||||
) {
|
||||
// ignore "//vda1cs4850/c$/folderAtRoot"
|
||||
if (length === 2) return 2;
|
||||
|
||||
@@ -36,7 +36,7 @@ const buildPartRegExp = /^[a-z0-9-]+$/i;
|
||||
|
||||
// https://semver.org/#spec-item-9
|
||||
// > Numeric identifiers MUST NOT include leading zeroes.
|
||||
const numericIdentifierRegExp = /^(0|[1-9]\d*)$/;
|
||||
const numericIdentifierRegExp = /^(?:0|[1-9]\d*)$/;
|
||||
|
||||
/**
|
||||
* Describes a precise semantic version number, https://semver.org
|
||||
@@ -244,8 +244,8 @@ interface Comparator {
|
||||
// range-set ::= range ( logical-or range ) *
|
||||
// range ::= hyphen | simple ( ' ' simple ) * | ''
|
||||
// logical-or ::= ( ' ' ) * '||' ( ' ' ) *
|
||||
const logicalOrRegExp = /\|\|/g;
|
||||
const whitespaceRegExp = /\s+/g;
|
||||
const logicalOrRegExp = /\|\|/;
|
||||
const whitespaceRegExp = /\s+/;
|
||||
|
||||
// https://github.com/npm/node-semver#range-grammar
|
||||
//
|
||||
@@ -257,7 +257,7 @@ const whitespaceRegExp = /\s+/g;
|
||||
// build ::= parts
|
||||
// parts ::= part ( '.' part ) *
|
||||
// part ::= nr | [-0-9A-Za-z]+
|
||||
const partialRegExp = /^([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i;
|
||||
const partialRegExp = /^([x*0]|[1-9]\d*)(?:\.([x*0]|[1-9]\d*)(?:\.([x*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i;
|
||||
|
||||
// https://github.com/npm/node-semver#range-grammar
|
||||
//
|
||||
@@ -270,7 +270,7 @@ const hyphenRegExp = /^\s*([a-z0-9-+.*]+)\s+-\s+([a-z0-9-+.*]+)\s*$/i;
|
||||
// primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial
|
||||
// tilde ::= '~' partial
|
||||
// caret ::= '^' partial
|
||||
const rangeRegExp = /^(~|\^|<|<=|>|>=|=)?\s*([a-z0-9-+.*]+)$/i;
|
||||
const rangeRegExp = /^([~^<>=]|<=|>=)?\s*([a-z0-9-+.*]+)$/i;
|
||||
|
||||
function parseRange(text: string) {
|
||||
const alternatives: Comparator[][] = [];
|
||||
|
||||
@@ -360,9 +360,9 @@ export function createSourceMapGenerator(host: EmitHost, file: string, sourceRoo
|
||||
|
||||
// Sometimes tools can see the following line as a source mapping url comment, so we mangle it a bit (the [M])
|
||||
/** @internal */
|
||||
export const sourceMapCommentRegExpDontCareLineStart = /\/\/[@#] source[M]appingURL=(.+)\r?\n?$/;
|
||||
export const sourceMapCommentRegExpDontCareLineStart = /\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; // eslint-disable-line regexp/no-useless-character-class
|
||||
/** @internal */
|
||||
export const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/;
|
||||
export const sourceMapCommentRegExp = /^\/\/[@#] source[M]appingURL=(.+)\r?\n?$/; // eslint-disable-line regexp/no-useless-character-class
|
||||
|
||||
/** @internal */
|
||||
export const whitespaceOrMapCommentRegExp = /^\s*(\/\/[@#] .*)?$/;
|
||||
|
||||
+2
-2
@@ -1466,7 +1466,7 @@ export let sys: System = (() => {
|
||||
const byteOrderMarkIndicator = "\uFEFF";
|
||||
|
||||
function getNodeSystem(): System {
|
||||
const nativePattern = /^native |^\([^)]+\)$|^(internal[\\/]|[a-zA-Z0-9_\s]+(\.js)?$)/;
|
||||
const nativePattern = /^native |^\([^)]+\)$|^(?:internal[\\/]|[\w\s]+(?:\.js)?$)/;
|
||||
const _fs: typeof import("fs") = require("fs");
|
||||
const _path: typeof import("path") = require("path");
|
||||
const _os = require("os");
|
||||
@@ -1592,7 +1592,7 @@ export let sys: System = (() => {
|
||||
disableCPUProfiler,
|
||||
cpuProfilingEnabled: () => !!activeSession || contains(process.execArgv, "--cpu-prof") || contains(process.execArgv, "--prof"),
|
||||
realpath,
|
||||
debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv, arg => /^--(inspect|debug)(-brk)?(=\d+)?$/i.test(arg)) || !!(process as any).recordreplay,
|
||||
debugMode: !!process.env.NODE_INSPECTOR_IPC || !!process.env.VSCODE_INSPECTOR_OPTIONS || some(process.execArgv, arg => /^--(?:inspect|debug)(?:-brk)?(?:=\d+)?$/i.test(arg)) || !!(process as any).recordreplay,
|
||||
tryEnableSourceMapsForHost() {
|
||||
try {
|
||||
(require("source-map-support") as typeof import("source-map-support")).install();
|
||||
|
||||
@@ -667,7 +667,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B
|
||||
const name = node.name;
|
||||
if (isIdentifier(name)) {
|
||||
const text = idText(name);
|
||||
return (/^[A-Za-z_]\w*$/.test(text)) ? name : factory.createStringLiteral(text);
|
||||
return (/^[A-Z_]\w*$/i.test(text)) ? name : factory.createStringLiteral(text);
|
||||
}
|
||||
return factory.createStringLiteral(idText(name.namespace) + ":" + idText(name.name));
|
||||
}
|
||||
|
||||
+11
-11
@@ -2622,12 +2622,12 @@ export function getJSDocCommentRanges(node: Node, text: string) {
|
||||
text.charCodeAt(comment.pos + 3) !== CharacterCodes.slash);
|
||||
}
|
||||
|
||||
const fullTripleSlashReferencePathRegEx = /^(\/\/\/\s*<reference\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^(\/\/\/\s*<reference\s+types\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashLibReferenceRegEx = /^(\/\/\/\s*<reference\s+lib\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashAMDReferencePathRegEx = /^(\/\/\/\s*<amd-dependency\s+path\s*=\s*)(('[^']*')|("[^"]*")).*?\/>/;
|
||||
const fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*<amd-module\s+.*?\/>/;
|
||||
const defaultLibReferenceRegEx = /^(\/\/\/\s*<reference\s+no-default-lib\s*=\s*)(('[^']*')|("[^"]*"))\s*\/>/;
|
||||
const fullTripleSlashReferencePathRegEx = /^\/\/\/\s*<reference\s+path\s*=\s*(?:'[^']*'|"[^"]*").*?\/>/;
|
||||
const fullTripleSlashReferenceTypeReferenceDirectiveRegEx = /^\/\/\/\s*<reference\s+types\s*=\s*(?:'[^']*'|"[^"]*").*?\/>/;
|
||||
const fullTripleSlashLibReferenceRegEx = /^\/\/\/\s*<reference\s+lib\s*=\s*(?:'[^']*'|"[^"]*").*?\/>/;
|
||||
const fullTripleSlashAMDReferencePathRegEx = /^\/\/\/\s*<amd-dependency\s+path\s*=\s*(?:'[^']*'|"[^"]*").*?\/>/;
|
||||
const fullTripleSlashAMDModuleRegEx = /^\/\/\/\s*<amd-module\s+(?:\S.*?)??\/>/;
|
||||
const defaultLibReferenceRegEx = /^\/\/\/\s*<reference\s+no-default-lib\s*=\s*(?:'[^']*'|"[^"]*")\s*\/>/;
|
||||
|
||||
export function isPartOfTypeNode(node: Node): boolean {
|
||||
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
|
||||
@@ -5988,10 +5988,10 @@ export function hasInvalidEscape(template: TemplateLiteral): boolean {
|
||||
// the language service. These characters should be escaped when printing, and if any characters are added,
|
||||
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
|
||||
// There is no reason for this other than that JSON.stringify does not handle it either.
|
||||
const doubleQuoteEscapedCharsRegExp = /[\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const singleQuoteEscapedCharsRegExp = /[\\'\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
|
||||
const doubleQuoteEscapedCharsRegExp = /[\\"\u0000-\u001f\u2028\u2029\u0085]/g;
|
||||
const singleQuoteEscapedCharsRegExp = /[\\'\u0000-\u001f\u2028\u2029\u0085]/g;
|
||||
// Template strings preserve simple LF newlines, still encode CRLF (or CR)
|
||||
const backtickQuoteEscapedCharsRegExp = /\r\n|[\\`\u0000-\u001f\t\v\f\b\r\u2028\u2029\u0085]/g;
|
||||
const backtickQuoteEscapedCharsRegExp = /\r\n|[\\`\u0000-\u001f\u2028\u2029\u0085]/g;
|
||||
const escapedCharsMap = new Map(Object.entries({
|
||||
"\t": "\\t",
|
||||
"\v": "\\v",
|
||||
@@ -8365,7 +8365,7 @@ export function setObjectAllocator(alloc: ObjectAllocator) {
|
||||
|
||||
/** @internal */
|
||||
export function formatStringFromArgs(text: string, args: DiagnosticArguments): string {
|
||||
return text.replace(/{(\d+)}/g, (_match, index: string) => "" + Debug.checkDefined(args[+index]));
|
||||
return text.replace(/\{(\d+)\}/g, (_match, index: string) => "" + Debug.checkDefined(args[+index]));
|
||||
}
|
||||
|
||||
let localizedDiagnosticMessages: MapLike<string> | undefined;
|
||||
@@ -10623,7 +10623,7 @@ export function isFunctionExpressionOrArrowFunction(node: Node): node is Functio
|
||||
|
||||
/** @internal */
|
||||
export function escapeSnippetText(text: string): string {
|
||||
return text.replace(/\$/gm, () => "\\$");
|
||||
return text.replace(/\$/g, () => "\\$");
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
||||
@@ -681,7 +681,7 @@ export function validateLocaleAndSetLanguage(
|
||||
errors?: Diagnostic[],
|
||||
) {
|
||||
const lowerCaseLocale = locale.toLowerCase();
|
||||
const matchResult = /^([a-z]+)([_-]([a-z]+))?$/.exec(lowerCaseLocale);
|
||||
const matchResult = /^([a-z]+)(?:[_-]([a-z]+))?$/.exec(lowerCaseLocale);
|
||||
|
||||
if (!matchResult) {
|
||||
if (errors) {
|
||||
@@ -691,7 +691,7 @@ export function validateLocaleAndSetLanguage(
|
||||
}
|
||||
|
||||
const language = matchResult[1];
|
||||
const territory = matchResult[3];
|
||||
const territory = matchResult[2];
|
||||
|
||||
// First try the entire locale, then fall back to just language if that's all we have.
|
||||
// Either ways do not fail, and fallback to the English diagnostic strings.
|
||||
|
||||
@@ -72,8 +72,8 @@ export class SourceMap {
|
||||
public readonly mappings: readonly Mapping[] = [];
|
||||
public readonly names: readonly string[] | undefined;
|
||||
|
||||
private static readonly _mappingRegExp = /([A-Za-z0-9+/]+),?|(;)|./g;
|
||||
private static readonly _sourceMappingURLRegExp = /^\/\/[#@]\s*sourceMappingURL\s*=\s*(.*?)\s*$/mig;
|
||||
private static readonly _mappingRegExp = /([A-Z0-9+/]+),?|(;)|./gi;
|
||||
private static readonly _sourceMappingURLRegExp = /^\/\/[#@]\s*sourceMappingURL\s*=\s*(.*?)\s*$/gim;
|
||||
private static readonly _dataURLRegExp = /^data:application\/json;base64,([a-z0-9+/=]+)$/i;
|
||||
private static readonly _base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
@@ -966,7 +966,7 @@ export class TestState {
|
||||
const annotations = ts.map(hints.sort(sortHints), hint => {
|
||||
if (hint.displayParts) {
|
||||
hint.displayParts = ts.map(hint.displayParts, part => {
|
||||
if (part.file && /lib(?:.*)\.d\.ts$/.test(part.file)) {
|
||||
if (part.file && /lib.*\.d\.ts$/.test(part.file)) {
|
||||
part.span!.start = -1;
|
||||
}
|
||||
return part;
|
||||
@@ -1547,7 +1547,7 @@ export class TestState {
|
||||
}: BaselineDocumentSpansWithFileContentsOptions<T>,
|
||||
spanToContextId: Map<T, number>,
|
||||
) {
|
||||
const isLibFile = /lib(?:.*)\.d\.ts$/.test(fileName);
|
||||
const isLibFile = /lib.*\.d\.ts$/.test(fileName);
|
||||
let readableContents = `// === ${fileName} ===`;
|
||||
let newContent = "";
|
||||
interface Detail {
|
||||
@@ -2514,7 +2514,7 @@ export class TestState {
|
||||
for (const part of tag.text ?? ts.emptyArray) {
|
||||
if (part.kind === "linkName") {
|
||||
const link = part as ts.JSDocLinkDisplayPart;
|
||||
if (/lib(?:.*)\.d\.ts$/.test(link.target.fileName)) {
|
||||
if (/lib.*\.d\.ts$/.test(link.target.fileName)) {
|
||||
// The object literal isn't a complete TextSpan, but we're only going to
|
||||
// use these results in the baseline for diffing, so just overwrite.
|
||||
(link.target.textSpan as any) = { start: "--", length: "--" };
|
||||
|
||||
@@ -582,7 +582,7 @@ export namespace Compiler {
|
||||
let location = info.file ? " " + ts.formatLocation(info.file, info.start!, formatDiagnsoticHost, ts.identity) : "";
|
||||
location = Utils.removeTestPathPrefixes(location);
|
||||
if (location && isDefaultLibraryFile(info.file!.fileName)) {
|
||||
location = location.replace(/(lib(?:.*)\.d\.ts):\d+:\d+/i, "$1:--:--");
|
||||
location = location.replace(/(lib.*\.d\.ts):\d+:\d+/i, "$1:--:--");
|
||||
}
|
||||
errLines.push(`!!! related TS${info.code}${location}: ${ts.flattenDiagnosticMessageText(info.messageText, IO.newLine())}`);
|
||||
}
|
||||
@@ -603,7 +603,7 @@ export namespace Compiler {
|
||||
|
||||
let topDiagnostics = minimalDiagnosticsToString(diagnostics, options && options.pretty);
|
||||
topDiagnostics = Utils.removeTestPathPrefixes(topDiagnostics);
|
||||
topDiagnostics = topDiagnostics.replace(/^(lib(?:.*)\.d\.ts)\(\d+,\d+\)/igm, "$1(--,--)");
|
||||
topDiagnostics = topDiagnostics.replace(/^(lib.*\.d\.ts)\(\d+,\d+\)/gim, "$1(--,--)");
|
||||
|
||||
yield [diagnosticSummaryMarker, topDiagnostics + IO.newLine() + IO.newLine(), diagnostics.length];
|
||||
|
||||
@@ -666,7 +666,7 @@ export namespace Compiler {
|
||||
// Calculate the start of the squiggle
|
||||
const squiggleStart = Math.max(0, relativeOffset);
|
||||
// TODO/REVIEW: this doesn't work quite right in the browser if a multi file test has files whose names are just the right length relative to one another
|
||||
outputLines += newLine() + " " + line.substr(0, squiggleStart).replace(/[^\s]/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~");
|
||||
outputLines += newLine() + " " + line.substr(0, squiggleStart).replace(/\S/g, " ") + new Array(Math.min(length, line.length - squiggleStart) + 1).join("~");
|
||||
|
||||
// If the error ended here, or we're at the end of the file, emit its message
|
||||
if ((lineIndex === lines.length - 1) || nextLineStart > end) {
|
||||
@@ -862,7 +862,7 @@ export namespace Compiler {
|
||||
for (const file of allFiles) {
|
||||
const { unitName } = file;
|
||||
let typeLines = "=== " + unitName + " ===\r\n";
|
||||
const codeLines = ts.flatMap(file.content.split(/\r?\n/g), e => e.split(/[\r\u2028\u2029]/g));
|
||||
const codeLines = ts.flatMap(file.content.split(/\r?\n/), e => e.split(/[\r\u2028\u2029]/));
|
||||
const gen: IterableIterator<TypeWriterResult> = isSymbolBaseline ? fullWalker.getSymbols(unitName) : fullWalker.getTypes(unitName);
|
||||
let lastIndexWritten: number | undefined;
|
||||
for (const result of gen) {
|
||||
@@ -1103,7 +1103,7 @@ function splitVaryBySettingValue(text: string, varyBy: string): string[] | undef
|
||||
let star = false;
|
||||
const includes: string[] = [];
|
||||
const excludes: string[] = [];
|
||||
for (let s of text.split(/,/g)) {
|
||||
for (let s of text.split(/,/)) {
|
||||
s = s.trim().toLowerCase();
|
||||
if (s.length === 0) continue;
|
||||
if (s === "*") {
|
||||
@@ -1247,8 +1247,8 @@ export namespace TestCaseParser {
|
||||
}
|
||||
|
||||
// Regex for parsing options in the format "@Alpha: Value of any sort"
|
||||
const optionRegex = /^[/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
const linkRegex = /^[/]{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
const optionRegex = /^\/{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
const linkRegex = /^\/{2}\s*@link\s*:\s*([^\r\n]*)\s*->\s*([^\r\n]*)/gm; // multiple matches on multiple lines
|
||||
|
||||
export function parseSymlinkFromTest(line: string, symlinks: vfs.FileSet | undefined, absoluteRootDir?: string) {
|
||||
const linkMetaData = linkRegex.exec(line);
|
||||
|
||||
@@ -333,7 +333,7 @@ const maxHarnessFrames = 1;
|
||||
export function filterStack(error: Error, stackTraceLimit = Infinity) {
|
||||
const stack = (error as any).stack as string;
|
||||
if (stack) {
|
||||
const lines = stack.split(/\r\n?|\n/g);
|
||||
const lines = stack.split(/\r\n?|\n/);
|
||||
const filtered: string[] = [];
|
||||
let frameCount = 0;
|
||||
let harnessFrameCount = 0;
|
||||
@@ -355,7 +355,7 @@ export function filterStack(error: Error, stackTraceLimit = Infinity) {
|
||||
harnessFrameCount++;
|
||||
}
|
||||
|
||||
line = line.replace(/\bfile:\/\/\/(.*?)(?=(:\d+)*($|\)))/, (_, path) => ts.sys.resolvePath(path));
|
||||
line = line.replace(/\bfile:\/\/\/(.*?)(?=(?::\d+)*(?:$|\)))/, (_, path) => ts.sys.resolvePath(path));
|
||||
frameCount++;
|
||||
}
|
||||
|
||||
@@ -373,11 +373,11 @@ function isStackFrame(line: string) {
|
||||
}
|
||||
|
||||
function isMocha(line: string) {
|
||||
return /[\\/](node_modules|components)[\\/]mocha(js)?[\\/]|[\\/]mocha\.js/.test(line);
|
||||
return /[\\/](?:node_modules|components)[\\/]mocha(?:js)?[\\/]|[\\/]mocha\.js/.test(line);
|
||||
}
|
||||
|
||||
function isNode(line: string) {
|
||||
return /\((timers|events|node|module)\.js:/.test(line);
|
||||
return /\((?:timers|events|node|module)\.js:/.test(line);
|
||||
}
|
||||
|
||||
function isHarness(line: string) {
|
||||
|
||||
@@ -159,7 +159,7 @@ function getProgramStructure(program: ts.Program | undefined) {
|
||||
const baseline: string[] = [];
|
||||
program?.getSourceFiles().slice().sort((f1, f2) => ts.comparePathsCaseSensitive(f1.path, f2.path)).forEach(f => {
|
||||
baseline.push(` File: ${f.fileName} Path: ${f.path} ResolvedPath: ${f.resolvedPath} impliedNodeFormat: ${f.impliedNodeFormat}`);
|
||||
baseline.push(f.text.split(/\r?\n/g).map(l => l ? " " + l : "").join("\n"));
|
||||
baseline.push(f.text.split(/\r?\n/).map(l => l ? " " + l : "").join("\n"));
|
||||
getResolutionCacheDetails(
|
||||
baseline,
|
||||
"Modules",
|
||||
|
||||
@@ -55,7 +55,7 @@ export abstract class RunnerBase {
|
||||
/** Replaces instances of full paths with fileNames only */
|
||||
static removeFullPaths(path: string) {
|
||||
// If its a full path (starts with "C:" or "/") replace with just the filename
|
||||
let fixedPath = /^(\w:|\/)/.test(path) ? ts.getBaseFileName(path) : path;
|
||||
let fixedPath = /^(?:\w:|\/)/.test(path) ? ts.getBaseFileName(path) : path;
|
||||
|
||||
// when running in the browser the 'full path' is the host name, shows up in error baselines
|
||||
const localHost = /http:\/localhost:\d+/g;
|
||||
|
||||
@@ -321,7 +321,7 @@ export class TypeWriterWalker {
|
||||
const declSourceFile = declaration.getSourceFile();
|
||||
const declLineAndCharacter = declSourceFile.getLineAndCharacterOfPosition(declaration.pos);
|
||||
const fileName = ts.getBaseFileName(declSourceFile.fileName);
|
||||
const isLibFile = /lib(.*)\.d\.ts/i.test(fileName);
|
||||
const isLibFile = /lib.*\.d\.ts/i.test(fileName);
|
||||
const declText = `Decl(${fileName}, ${isLibFile ? "--" : declLineAndCharacter.line}, ${isLibFile ? "--" : declLineAndCharacter.character})`;
|
||||
symbolString += declText;
|
||||
(declaration as any).__symbolTestOutputCache = declText;
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@ import * as ts from "./_namespaces/ts.js";
|
||||
* Common utilities
|
||||
*/
|
||||
|
||||
const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(ts|lib|src)\//g;
|
||||
const testPathPrefixRegExp = /(?:(file:\/{3})|\/)\.(?:ts|lib|src)\//g;
|
||||
export function removeTestPathPrefixes(text: string, retainTrailingDirectorySeparator?: boolean): string {
|
||||
return text !== undefined ? text.replace(testPathPrefixRegExp, (_, scheme) => scheme || (retainTrailingDirectorySeparator ? "/" : "")) : undefined!; // TODO: GH#18217
|
||||
}
|
||||
|
||||
function createDiagnosticMessageReplacer<R extends (messageArgs: string[], ...args: string[]) => string[]>(diagnosticMessage: ts.DiagnosticMessage, replacer: R) {
|
||||
const messageParts = diagnosticMessage.message.split(/{\d+}/g);
|
||||
const messageParts = diagnosticMessage.message.split(/\{\d+\}/);
|
||||
const regExp = new RegExp(`^(?:${messageParts.map(ts.regExpEscape).join("(.*?)")})$`);
|
||||
type Args<R> = R extends (messageArgs: string[], ...args: infer A) => string[] ? A : [];
|
||||
return (text: string, ...args: Args<R>) => text.replace(regExp, (_, ...fixedArgs) => ts.formatStringFromArgs(diagnosticMessage.message, replacer(fixedArgs, ...args)));
|
||||
|
||||
@@ -26,7 +26,7 @@ export import changeExtension = ts.changeAnyExtension;
|
||||
export import isTypeScript = ts.hasTSFileExtension;
|
||||
export import isJavaScript = ts.hasJSFileExtension;
|
||||
|
||||
const invalidRootComponentRegExp = /^(?!(\/|\/\/\w+\/|[a-zA-Z]:\/?|)$)/;
|
||||
const invalidRootComponentRegExp = /^(?!(?:\/|\/\/\w+\/|[a-z]:\/?)?$)/i;
|
||||
const invalidNavigableComponentRegExp = /[:*?"<>|]/;
|
||||
const invalidNavigableComponentWithWildcardsRegExp = /[:"<>|]/;
|
||||
const invalidNonNavigableComponentRegExp = /^\.{1,2}$|[:*?"<>|]/;
|
||||
|
||||
@@ -5041,7 +5041,7 @@ export class ProjectService {
|
||||
if (
|
||||
!pluginConfigEntry.name ||
|
||||
isExternalModuleNameRelative(pluginConfigEntry.name) ||
|
||||
/[\\/]\.\.?($|[\\/])/.test(pluginConfigEntry.name)
|
||||
/[\\/]\.\.?(?:$|[\\/])/.test(pluginConfigEntry.name)
|
||||
) {
|
||||
this.logger.info(`Skipped loading plugin ${pluginConfigEntry.name || JSON.stringify(pluginConfigEntry)} because only package name is allowed plugin name`);
|
||||
return;
|
||||
|
||||
@@ -927,9 +927,9 @@ export function getEncodedSyntacticClassifications(cancellationToken: Cancellati
|
||||
}
|
||||
|
||||
function tryClassifyTripleSlashComment(start: number, width: number): boolean {
|
||||
const tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/im;
|
||||
const tripleSlashXMLCommentRegEx = /^(\/\/\/\s*)(<)(?:(\S+)((?:[^/]|\/[^>])*)(\/>)?)?/m;
|
||||
// Require a leading whitespace character (the parser already does) to prevent terrible backtracking performance
|
||||
const attributeRegex = /(\s)(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/img;
|
||||
const attributeRegex = /(\s)(\S+)(\s*)(=)(\s*)('[^']+'|"[^"]+")/g;
|
||||
|
||||
const text = sourceFile.text.substr(start, width);
|
||||
const match = tripleSlashXMLCommentRegEx.exec(text);
|
||||
|
||||
@@ -147,7 +147,7 @@ function findEndOfTextBetween(jsDocComment: JSDoc, from: number, to: number): nu
|
||||
const comment = jsDocComment.getText().substring(from - jsDocComment.getStart(), to - jsDocComment.getStart());
|
||||
|
||||
for (let i = comment.length; i > 0; i--) {
|
||||
if (!/[*/\s]/g.test(comment.substring(i - 1, i))) {
|
||||
if (!/[*/\s]/.test(comment.substring(i - 1, i))) {
|
||||
return from + i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1100,5 +1100,5 @@ function cleanText(text: string): string {
|
||||
// \r - Carriage Return
|
||||
// \u2028 - Line separator
|
||||
// \u2029 - Paragraph separator
|
||||
return text.replace(/\\?(\r?\n|\r|\u2028|\u2029)/g, "");
|
||||
return text.replace(/\\?(?:\r?\n|[\r\u2028\u2029])/g, "");
|
||||
}
|
||||
|
||||
@@ -138,14 +138,14 @@ function addRegionOutliningSpans(sourceFile: SourceFile, out: OutliningSpan[]):
|
||||
for (const currentLineStart of lineStarts) {
|
||||
const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart);
|
||||
const lineText = sourceFile.text.substring(currentLineStart, lineEnd);
|
||||
const result = isRegionDelimiter(lineText);
|
||||
const result = parseRegionDelimiter(lineText);
|
||||
if (!result || isInComment(sourceFile, currentLineStart)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!result[1]) {
|
||||
if (result.isStart) {
|
||||
const span = createTextSpanFromBounds(sourceFile.text.indexOf("//", currentLineStart), lineEnd);
|
||||
regions.push(createOutliningSpan(span, OutliningSpanKind.Region, span, /*autoCollapse*/ false, result[2] || "#region"));
|
||||
regions.push(createOutliningSpan(span, OutliningSpanKind.Region, span, /*autoCollapse*/ false, result.name || "#region"));
|
||||
}
|
||||
else {
|
||||
const region = regions.pop();
|
||||
@@ -158,8 +158,8 @@ function addRegionOutliningSpans(sourceFile: SourceFile, out: OutliningSpan[]):
|
||||
}
|
||||
}
|
||||
|
||||
const regionDelimiterRegExp = /^#(end)?region(?:\s+(.*))?(?:\r)?$/;
|
||||
function isRegionDelimiter(lineText: string) {
|
||||
const regionDelimiterRegExp = /^#(end)?region(.*)\r?$/;
|
||||
function parseRegionDelimiter(lineText: string) {
|
||||
// We trim the leading whitespace and // without the regex since the
|
||||
// multiple potential whitespace matches can make for some gnarly backtracking behavior
|
||||
lineText = lineText.trimStart();
|
||||
@@ -167,7 +167,11 @@ function isRegionDelimiter(lineText: string) {
|
||||
return null; // eslint-disable-line no-restricted-syntax
|
||||
}
|
||||
lineText = lineText.slice(2).trim();
|
||||
return regionDelimiterRegExp.exec(lineText);
|
||||
const result = regionDelimiterRegExp.exec(lineText);
|
||||
if (result) {
|
||||
return { isStart: !result[1], name: result[2].trim() };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: SourceFile, cancellationToken: CancellationToken, out: OutliningSpan[]): void {
|
||||
@@ -184,7 +188,7 @@ function addOutliningForLeadingCommentsForPos(pos: number, sourceFile: SourceFil
|
||||
case SyntaxKind.SingleLineCommentTrivia:
|
||||
// never fold region delimiters into single-line comment regions
|
||||
const commentText = sourceText.slice(pos, end);
|
||||
if (isRegionDelimiter(commentText)) {
|
||||
if (parseRegionDelimiter(commentText)) {
|
||||
combineAndAddMultipleSingleLineComments();
|
||||
singleLineCommentCount = 0;
|
||||
break;
|
||||
|
||||
@@ -3166,7 +3166,7 @@ export function createLanguageService(
|
||||
//
|
||||
// The following three regexps are used to match the start of the text up to the TODO
|
||||
// comment portion.
|
||||
const singleLineCommentStart = /(?:\/\/+\s*)/.source;
|
||||
const singleLineCommentStart = /(?:\/{2,}\s*)/.source;
|
||||
const multiLineCommentStart = /(?:\/\*+\s*)/.source;
|
||||
const anyNumberOfSpacesAndAsterisksAtStartOfLine = /(?:^(?:\s|\*)*)/.source;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
tryParseRawSourceMap,
|
||||
} from "./_namespaces/ts.js";
|
||||
|
||||
const base64UrlRegExp = /^data:(?:application\/json(?:;charset=[uU][tT][fF]-8);base64,([A-Za-z0-9+/=]+)$)?/;
|
||||
const base64UrlRegExp = /^data:(?:application\/json;charset=[uU][tT][fF]-8;base64,([A-Za-z0-9+/=]+)$)?/;
|
||||
|
||||
/** @internal */
|
||||
export interface SourceMapper {
|
||||
|
||||
@@ -31,7 +31,7 @@ function runTests(runners: RunnerBase[]) {
|
||||
for (const full of runner.enumerateTestFiles()) {
|
||||
const base = vpath.basename(full).toLowerCase();
|
||||
// allow existing dupes in fourslash/shims and fourslash/server
|
||||
if (seen.has(base) && !/fourslash\/(shim|server)/.test(full)) {
|
||||
if (seen.has(base) && !/fourslash\/(?:shim|server)/.test(full)) {
|
||||
dupes.push([seen.get(base)!, full]);
|
||||
}
|
||||
else {
|
||||
@@ -52,7 +52,7 @@ function tryGetConfig(args: string[]) {
|
||||
const prefix = "--config=";
|
||||
const configPath = ts.forEach(args, arg => arg.lastIndexOf(prefix, 0) === 0 && arg.substr(prefix.length));
|
||||
// strip leading and trailing quotes from the path (necessary on Windows since shell does not do it automatically)
|
||||
return configPath && configPath.replace(/(^["'])|(["']$)/g, "");
|
||||
return configPath && configPath.replace(/^["']|["']$/g, "");
|
||||
}
|
||||
|
||||
export function createRunner(kind: TestRunnerKind): RunnerBase {
|
||||
|
||||
@@ -6,7 +6,7 @@ describe("unittests:: config:: initTSConfig", () => {
|
||||
describe(name, () => {
|
||||
const commandLine = ts.parseCommandLine(commandLinesArgs);
|
||||
const initResult = ts.generateTSConfig(commandLine.options, commandLine.fileNames, "\n");
|
||||
const outputFileName = `config/initTSConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
|
||||
const outputFileName = `config/initTSConfig/${name.replace(/[^a-z0-9\-. ]/gi, "")}/tsconfig.json`;
|
||||
|
||||
it(`Correct output for ${outputFileName}`, () => {
|
||||
Harness.Baseline.runBaseline(outputFileName, initResult, { PrintDiff: true });
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as ts from "../../_namespaces/ts.js";
|
||||
describe("unittests:: config:: showConfig", () => {
|
||||
function showTSConfigCorrectly(name: string, commandLinesArgs: string[], configJson?: object) {
|
||||
describe(name, () => {
|
||||
const outputFileName = `config/showConfig/${name.replace(/[^a-z0-9\-./ ]/ig, "")}/tsconfig.json`;
|
||||
const outputFileName = `config/showConfig/${name.replace(/[^a-z0-9\-./ ]/gi, "")}/tsconfig.json`;
|
||||
|
||||
it(`Correct output for ${outputFileName}`, () => {
|
||||
const cwd = `/${name}`;
|
||||
|
||||
@@ -7,8 +7,8 @@ import { TestServerHost } from "./virtualFileSystemWithWatch.js";
|
||||
|
||||
export function sanitizeSysOutput(output: string) {
|
||||
return output
|
||||
.replace(/Elapsed::\s[0-9]+(?:\.\d+)?ms/g, "Elapsed:: *ms")
|
||||
.replace(/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\s(A|P)M/g, "HH:MM:SS AM");
|
||||
.replace(/Elapsed::\s\d+(?:\.\d+)?ms/g, "Elapsed:: *ms")
|
||||
.replace(/\d\d:\d\d:\d\d\s(?:A|P)M/g, "HH:MM:SS AM");
|
||||
}
|
||||
|
||||
export type CommandLineProgram = [ts.Program, ts.BuilderProgram?];
|
||||
|
||||
@@ -7,7 +7,7 @@ describe("unittests:: jsonParserRecovery", () => {
|
||||
const file = ts.parseJsonText(name, text);
|
||||
assert(file.parseDiagnostics.length, "Should have parse errors");
|
||||
Harness.Baseline.runBaseline(
|
||||
`jsonParserRecovery/${name.replace(/[^a-z0-9_-]/ig, "_")}.errors.txt`,
|
||||
`jsonParserRecovery/${name.replace(/[^\w-]/g, "_")}.errors.txt`,
|
||||
Harness.Compiler.getErrorBaseline([{
|
||||
content: text,
|
||||
unitName: name,
|
||||
|
||||
@@ -126,7 +126,7 @@ describe("unittests:: PrinterAPI", () => {
|
||||
const file = program.getSourceFile("/test.d.ts")!;
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed });
|
||||
const output = printer.printFile(file);
|
||||
assert.equal(output.split(/\r?\n/g).length, 3);
|
||||
assert.equal(output.split(/\r?\n/).length, 3);
|
||||
});
|
||||
it("with statements", () => {
|
||||
const host = new fakes.CompilerHost(
|
||||
@@ -140,7 +140,7 @@ describe("unittests:: PrinterAPI", () => {
|
||||
const file = program.getSourceFile("/test.d.ts")!;
|
||||
const printer = ts.createPrinter({ newLine: ts.NewLineKind.CarriageReturnLineFeed });
|
||||
const output = printer.printFile(file);
|
||||
assert.equal(output.split(/\r?\n/g).length, 4);
|
||||
assert.equal(output.split(/\r?\n/).length, 4);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ describe("unittests:: services:: Transpile", () => {
|
||||
|
||||
transpileOptions.reportDiagnostics = true;
|
||||
|
||||
const justName = "transpile/" + name.replace(/[^a-z0-9\-. ()=]/ig, "") + (transpileOptions.compilerOptions.jsx ? ts.Extension.Tsx : ts.Extension.Ts);
|
||||
const justName = "transpile/" + name.replace(/[^a-z0-9\-. ()=]/gi, "") + (transpileOptions.compilerOptions.jsx ? ts.Extension.Tsx : ts.Extension.Ts);
|
||||
const toBeCompiled = [{
|
||||
unitName,
|
||||
content: input,
|
||||
|
||||
@@ -526,7 +526,7 @@ describe("unittests:: tsserver:: CachingFileSystemInformation:: tsserverProjectS
|
||||
ts.forEach(filesAndFoldersToAdd, f => {
|
||||
f.path = f.path
|
||||
.replace("/a/b/node_modules/.staging", "/a/b/node_modules")
|
||||
.replace(/[-.][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w][\d\w]/g, "");
|
||||
.replace(/[-.]\w\w\w\w\w\w\w\w/g, "");
|
||||
});
|
||||
|
||||
host.deleteFolder(root + "/a/b/node_modules/.staging", /*recursive*/ true);
|
||||
|
||||
Reference in New Issue
Block a user