Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/oxlint/src-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type { Context, LanguageOptions } from "./plugins/context.ts";
export type { Fix, Fixer, FixFn } from "./plugins/fix.ts";
export type { CreateOnceRule, CreateRule, Plugin, Rule } from "./plugins/load.ts";
export type { Options } from "./plugins/options.ts";
export type { Diagnostic, Suggestion } from "./plugins/report.ts";
export type { Diagnostic, DiagnosticData, Suggestion } from "./plugins/report.ts";
export type {
Definition,
DefinitionType,
Expand Down
35 changes: 24 additions & 11 deletions apps/oxlint/src-js/plugins/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ interface DiagnosticBase {
messageId?: string | null | undefined;
node?: Ranged;
loc?: Location;
data?: Record<string, string | number> | null | undefined;
data?: DiagnosticData | null | undefined;
fix?: FixFn;
suggest?: Suggestion[];
}

/**
* Data to interpolate into a diagnostic message.
*/
export type DiagnosticData = Record<string, string | number>;

/**
* Suggested fix.
* NOT IMPLEMENTED YET.
Expand All @@ -47,7 +52,7 @@ interface SuggestionBase {
desc?: string;
messageId?: string;
fix: FixFn;
data?: Record<string, string | number> | null | undefined;
data?: DiagnosticData | null | undefined;
}

// Diagnostic in form sent to Rust
Expand Down Expand Up @@ -81,15 +86,7 @@ export function report(diagnostic: Diagnostic, ruleDetails: RuleDetails): void {
// Interpolate placeholders {{key}} with data values
if (hasOwn(diagnostic, "data")) {
const { data } = diagnostic;
if (data != null) {
message = message.replace(PLACEHOLDER_REGEX, (match, key) => {
key = key.trim();
const value = data[key];
// TS type def for `string.replace` callback is `(substring: string, ...args: any[]) => string`,
// but actually returning other types e.g. `number` or `boolean` is fine
return value !== undefined ? (value as string) : match;
});
}
if (data != null) message = replacePlaceholders(message, data);
}

// TODO: Validate `diagnostic`
Expand Down Expand Up @@ -186,3 +183,19 @@ function resolveMessageFromMessageId(messageId: string, ruleDetails: RuleDetails

return messages[messageId];
}

/**
* Replace placeholders in message with values from `data`.
* @param message - Message
* @param data - Data to replace placeholders with
* @returns Message with placeholders replaced with data values
*/
function replacePlaceholders(message: string, data: DiagnosticData): string {
return message.replace(PLACEHOLDER_REGEX, (match, key) => {
key = key.trim();
const value = data[key];
// TS type def for `string.replace` callback is `(substring: string, ...args: any[]) => string`,
// but actually returning other types e.g. `number` or `boolean` is fine
return value !== undefined ? (value as string) : match;
});
}
Loading