diff --git a/.eslint-plugin-local/code-no-declare-const-enum.ts b/.eslint-plugin-local/code-no-declare-const-enum.ts new file mode 100644 index 00000000000..b448adee89c --- /dev/null +++ b/.eslint-plugin-local/code-no-declare-const-enum.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. + *--------------------------------------------------------------------------------------------*/ + +import * as eslint from 'eslint'; + +/** + * Disallows `declare const enum` declarations. esbuild does not inline + * `declare const enum` values, leaving the enum identifier in the output + * which causes a ReferenceError at runtime. + * + * Use `const enum` (without `declare`) instead. + * + * See https://github.com/evanw/esbuild/issues/4394 + */ +export default new class NoDeclareConstEnum implements eslint.Rule.RuleModule { + + readonly meta: eslint.Rule.RuleMetaData = { + messages: { + noDeclareConstEnum: '"declare const enum" is not supported by esbuild. Use "const enum" instead. See https://github.com/evanw/esbuild/issues/4394', + }, + schema: false, + fixable: 'code', + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + return { + TSEnumDeclaration(node: any) { + if (node.const && node.declare) { + context.report({ + node, + messageId: 'noDeclareConstEnum', + fix: (fixer) => { + // Remove "declare " from "declare const enum" + const sourceCode = context.sourceCode; + const text = sourceCode.getText(node); + const declareIndex = text.indexOf('declare'); + if (declareIndex !== -1) { + return fixer.removeRange([ + node.range[0] + declareIndex, + node.range[0] + declareIndex + 'declare '.length + ]); + } + return null; + } + }); + } + } + }; + } +}; diff --git a/eslint.config.js b/eslint.config.js index dfb489e0f0b..a0bcfc05560 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -78,6 +78,7 @@ export default tseslint.config( 'semi': 'warn', 'local/code-translation-remind': 'warn', 'local/code-no-native-private': 'warn', + 'local/code-no-declare-const-enum': 'warn', 'local/code-parameter-properties-must-have-explicit-accessibility': 'warn', 'local/code-no-nls-in-standalone-editor': 'warn', 'local/code-no-potentially-unsafe-disposables': 'warn', diff --git a/src/vs/workbench/contrib/chat/common/tools/promptTsxTypes.ts b/src/vs/workbench/contrib/chat/common/tools/promptTsxTypes.ts index 20de711820c..53617f61395 100644 --- a/src/vs/workbench/contrib/chat/common/tools/promptTsxTypes.ts +++ b/src/vs/workbench/contrib/chat/common/tools/promptTsxTypes.ts @@ -7,9 +7,12 @@ * This is a subset of the types export from jsonTypes.d.ts in @vscode/prompt-tsx. * It's just the types needed to stringify prompt-tsx tool results. * It should be kept in sync with the types in that file. + * + * Note: do NOT use `declare` with const enums, esbuild doesn't inline them. + * See https://github.com/evanw/esbuild/issues/4394 */ -export declare const enum PromptNodeType { +export const enum PromptNodeType { Piece = 1, Text = 2 } @@ -23,7 +26,7 @@ export interface TextJSON { * less descriptive than the actual constructor, as we only care to preserve * the element data that the renderer cares about. */ -export declare const enum PieceCtorKind { +export const enum PieceCtorKind { BaseChatMessage = 1, Other = 2, ImageChatMessage = 3