Skip to content

Consistently use '...args' for diagnostic args #53193

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

Merged
merged 12 commits into from
Mar 20, 2023
13 changes: 7 additions & 6 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
declarationNameToString,
DeleteExpression,
DestructuringAssignment,
DiagnosticArguments,
DiagnosticCategory,
DiagnosticMessage,
DiagnosticRelatedInformation,
Expand Down Expand Up @@ -556,8 +557,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
* If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node)
* This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations.
*/
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation {
return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2);
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithLocation {
return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, ...args);
}

function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
Expand Down Expand Up @@ -840,7 +841,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
const declarationName = getNameOfDeclaration(node) || node;
forEach(symbol.declarations, (declaration, index) => {
const decl = getNameOfDeclaration(declaration) || declaration;
const diag = createDiagnosticForNode(decl, message, messageNeedsName ? getDisplayName(declaration) : undefined);
const diag = messageNeedsName ? createDiagnosticForNode(decl, message, getDisplayName(declaration)) : createDiagnosticForNode(decl, message);
file.bindDiagnostics.push(
multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag
);
Expand All @@ -849,7 +850,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}
});

const diag = createDiagnosticForNode(declarationName, message, messageNeedsName ? getDisplayName(node) : undefined);
const diag = messageNeedsName ? createDiagnosticForNode(declarationName, message, getDisplayName(node)) : createDiagnosticForNode(declarationName, message);
file.bindDiagnostics.push(addRelatedInfo(diag, ...relatedInformation));

symbol = createSymbol(SymbolFlags.None, name);
Expand Down Expand Up @@ -2613,9 +2614,9 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
}
}

function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
function errorOnFirstToken(node: Node, message: DiagnosticMessage, ...args: DiagnosticArguments) {
const span = getSpanOfTokenAtPosition(file, node.pos);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, ...args));
}

function errorOrSuggestionOnNode(isError: boolean, node: Node, message: DiagnosticMessage): void {
Expand Down
135 changes: 68 additions & 67 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
createGetCanonicalFileName,
Debug,
Diagnostic,
DiagnosticArguments,
DiagnosticMessage,
Diagnostics,
DidYouMeanOptionsDiagnostics,
Expand Down Expand Up @@ -1692,7 +1693,7 @@ export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOpt
return createDiagnosticForInvalidCustomType(opt, createCompilerDiagnostic);
}

function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic {
function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, ...args: DiagnosticArguments) => Diagnostic): Diagnostic {
const namesOfType = arrayFrom(opt.type.keys());
const stringNames = (opt.deprecatedKeys ? namesOfType.filter(k => !opt.deprecatedKeys!.has(k)) : namesOfType).map(key => `'${key}'`).join(", ");
return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, stringNames);
Expand Down Expand Up @@ -2994,9 +2995,9 @@ function parseJsonConfigFileContentWorker(
return "no-prop";
}

function createCompilerDiagnosticOnlyIfJson(message: DiagnosticMessage, arg0?: string, arg1?: string) {
function createCompilerDiagnosticOnlyIfJson(message: DiagnosticMessage, ...args: DiagnosticArguments) {
if (!sourceFile) {
errors.push(createCompilerDiagnostic(message, arg0, arg1));
errors.push(createCompilerDiagnostic(message, ...args));
}
}
}
Expand Down Expand Up @@ -3445,10 +3446,10 @@ function convertOptionsFromJson(optionsNameMap: Map<string, CommandLineOption>,
return defaultOptions;
}

function createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile: TsConfigSourceFile | undefined, node: Node | undefined, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number, arg3?: string | number) {
function createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile: TsConfigSourceFile | undefined, node: Node | undefined, message: DiagnosticMessage, ...args: DiagnosticArguments) {
return sourceFile && node ?
createDiagnosticForNodeInSourceFile(sourceFile, node, message, arg0, arg1, arg2, arg3) :
createCompilerDiagnostic(message, arg0, arg1, arg2, arg3);
createDiagnosticForNodeInSourceFile(sourceFile, node, message, ...args) :
createCompilerDiagnostic(message, ...args);
}

/** @internal */
Expand Down Expand Up @@ -3519,8 +3520,8 @@ function convertJsonOptionOfCustomType(
return validateJsonOptionValue(opt, val, errors, valueExpression, sourceFile);
}
else {
errors.push(createDiagnosticForInvalidCustomType(opt, (message, arg0, arg1) =>
createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, message, arg0, arg1)));
errors.push(createDiagnosticForInvalidCustomType(opt, (message, ...args) =>
createDiagnosticForNodeInSourceFileOrCompilerDiagnostic(sourceFile, valueExpression, message, ...args)));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -5242,7 +5242,7 @@
"category": "Error",
"code": 6258
},
"Found 1 error in {1}": {
"Found 1 error in {0}": {
"category": "Message",
"code": 6259
},
Expand Down
59 changes: 34 additions & 25 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import {
DefaultClause,
DeleteExpression,
Diagnostic,
DiagnosticArguments,
DiagnosticMessage,
Diagnostics,
DiagnosticWithDetachedLocation,
Expand Down Expand Up @@ -149,6 +150,7 @@ import {
isJsxOpeningElement,
isJsxOpeningFragment,
isKeyword,
isKeywordOrPunctuation,
isLeftHandSideExpression,
isLiteralKind,
isMetaProperty,
Expand Down Expand Up @@ -306,6 +308,8 @@ import {
PropertyDeclaration,
PropertyName,
PropertySignature,
PunctuationOrKeywordSyntaxKind,
PunctuationSyntaxKind,
QualifiedName,
QuestionDotToken,
QuestionToken,
Expand Down Expand Up @@ -380,6 +384,7 @@ import {
TypeQueryNode,
TypeReferenceNode,
UnaryExpression,
unescapeLeadingUnderscores,
UnionOrIntersectionTypeNode,
UnionTypeNode,
UpdateExpression,
Expand Down Expand Up @@ -2096,16 +2101,16 @@ namespace Parser {
return inContext(NodeFlags.AwaitContext);
}

function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
return parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), message, arg0);
function parseErrorAtCurrentToken(message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined {
return parseErrorAt(scanner.getTokenStart(), scanner.getTokenEnd(), message, ...args);
}

function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined {
// Don't report another error if it would just be at the same position as the last error.
const lastError = lastOrUndefined(parseDiagnostics);
let result: DiagnosticWithDetachedLocation | undefined;
if (!lastError || start !== lastError.start) {
result = createDetachedDiagnostic(fileName, start, length, message, arg0);
result = createDetachedDiagnostic(fileName, start, length, message, ...args);
parseDiagnostics.push(result);
}

Expand All @@ -2115,12 +2120,12 @@ namespace Parser {
return result;
}

function parseErrorAt(start: number, end: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
return parseErrorAtPosition(start, end - start, message, arg0);
function parseErrorAt(start: number, end: number, message: DiagnosticMessage, ...args: DiagnosticArguments): DiagnosticWithDetachedLocation | undefined {
return parseErrorAtPosition(start, end - start, message, ...args);
}

function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, arg0?: any): void {
parseErrorAt(range.pos, range.end, message, arg0);
function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, ...args: DiagnosticArguments): void {
parseErrorAt(range.pos, range.end, message, ...args);
}

function scanError(message: DiagnosticMessage, length: number): void {
Expand Down Expand Up @@ -2289,7 +2294,7 @@ namespace Parser {
return token() > SyntaxKind.LastReservedWord;
}

function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean {
function parseExpected(kind: PunctuationOrKeywordSyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean {
if (token() === kind) {
if (shouldAdvance) {
nextToken();
Expand Down Expand Up @@ -2444,11 +2449,12 @@ namespace Parser {
nextTokenJSDoc();
return true;
}
Debug.assert(isKeywordOrPunctuation(kind));
parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
return false;
}

function parseExpectedMatchingBrackets(openKind: SyntaxKind, closeKind: SyntaxKind, openParsed: boolean, openPosition: number) {
function parseExpectedMatchingBrackets(openKind: PunctuationSyntaxKind, closeKind: PunctuationSyntaxKind, openParsed: boolean, openPosition: number) {
if (token() === closeKind) {
nextToken();
return;
Expand Down Expand Up @@ -2489,16 +2495,18 @@ namespace Parser {
return undefined;
}

function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Token<TKind>;
function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Node {
function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Token<TKind>;
function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Node {
return parseOptionalToken(t) ||
createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t));
createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t)!);
}

function parseExpectedTokenJSDoc<TKind extends JSDocSyntaxKind>(t: TKind): Token<TKind>;
function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): Node {
return parseOptionalTokenJSDoc(t) ||
createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t));
const optional = parseOptionalTokenJSDoc(t);
if (optional) return optional;
Debug.assert(isKeywordOrPunctuation(t));
return createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t));
}

function parseTokenNode<T extends Node>(): T {
Expand Down Expand Up @@ -2565,14 +2573,14 @@ namespace Parser {
return node;
}

function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, arg0?: any): T;
function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T;
function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage?: DiagnosticMessage, arg0?: any): T {
function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T;
function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, ...args: DiagnosticArguments): T;
function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T {
if (reportAtCurrentPosition) {
parseErrorAtPosition(scanner.getTokenFullStart(), 0, diagnosticMessage!, arg0);
parseErrorAtPosition(scanner.getTokenFullStart(), 0, diagnosticMessage!, ...args);
}
else if (diagnosticMessage) {
parseErrorAtCurrentToken(diagnosticMessage, arg0);
parseErrorAtCurrentToken(diagnosticMessage, ...args);
}

const pos = getNodePos();
Expand Down Expand Up @@ -3356,7 +3364,7 @@ namespace Parser {
case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics.Expression_expected);
case ParsingContext.VariableDeclarations:
return isKeyword(token())
? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token()))
? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token())!)
: parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected);
case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected);
case ParsingContext.ArrayBindingElements: return parseErrorAtCurrentToken(Diagnostics.Array_element_destructuring_pattern_expected);
Expand All @@ -3366,7 +3374,7 @@ namespace Parser {
case ParsingContext.JSDocParameters: return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
case ParsingContext.Parameters:
return isKeyword(token())
? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token()))
? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token())!)
: parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected);
case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected);
Expand Down Expand Up @@ -3471,7 +3479,7 @@ namespace Parser {
return !!(arr as MissingList<Node>).isMissingList;
}

function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: PunctuationSyntaxKind, close: PunctuationSyntaxKind): NodeArray<T> {
if (parseExpected(open)) {
const result = parseDelimitedList(kind, parseElement);
parseExpected(close);
Expand Down Expand Up @@ -5653,6 +5661,7 @@ namespace Parser {
parseErrorAt(pos, end, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses);
}
else {
Debug.assert(isKeywordOrPunctuation(unaryOperator));
parseErrorAt(pos, end, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator));
}
}
Expand Down Expand Up @@ -9119,7 +9128,7 @@ namespace Parser {

function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag {
if (some(tags, isJSDocReturnTag)) {
parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, tagName.escapedText);
parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's one example of accidentally using an escaped name in an error message.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True - though it's always going to be the text return anyhow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably a bad example, yeah, it's just the first one shown in the unhidden diff.

}

const typeExpression = tryParseTypeExpression();
Expand All @@ -9128,7 +9137,7 @@ namespace Parser {

function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag {
if (some(tags, isJSDocTypeTag)) {
parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, tagName.escapedText);
parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText));
}

const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
Expand Down
Loading