diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnsuppress similarity index 95% rename from .config/guardian/.gdnbaselines rename to .config/guardian/.gdnsuppress index 9408d050c9a..3ac8361e5fc 100644 --- a/.config/guardian/.gdnbaselines +++ b/.config/guardian/.gdnsuppress @@ -1,9 +1,10 @@ { + "hydrated": true, "properties": { - "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines" + "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/suppressions" }, "version": "1.0.0", - "baselines": { + "suppressionSets": { "default": { "name": "default", "createdDate": "2025-01-28 06:29:05Z", diff --git a/.eslint-plugin-local/README.md b/.eslint-plugin-local/README.md new file mode 100644 index 00000000000..1d100cfba07 --- /dev/null +++ b/.eslint-plugin-local/README.md @@ -0,0 +1,125 @@ +# Custom ESLint rules + +We use a set of custom [ESLint](http://eslint.org) to enforce repo specific coding rules and styles. These custom rules are run in addition to many standard ESLint rules we enable in the project. Some example custom rules includes: + +- Enforcing proper code layering +- Preventing checking in of `test.only(...)` +- Enforcing conventions in `vscode.d.ts` + +Custom rules are mostly used for enforcing or banning certain coding patterns. We tend to leave stylistic choices up to area owners unless there's a good reason to enforce something project wide. + +This doc provides a brief overview of how these rules are setup and how you can add a new one. + +# Resources +- [ESLint rules](https://eslint.org/docs/latest/extend/custom-rules) — General documentation about writing eslint rules +- [TypeScript ASTs and eslint](https://typescript-eslint.io/blog/asts-and-typescript-eslint/) — Look at how ESLint works with TS programs +- [ESTree selectors](https://eslint.org/docs/latest/extend/selectors) — Info about the selector syntax rules use to target specific nodes in an AST. Works similarly to css selectors. +- [TypeScript ESLint playground](https://typescript-eslint.io/play/#showAST=es) — Useful tool for figuring out the structure of TS programs and debugging custom rule selectors + + +# Custom Rule Configuration + +Custom rules are defined in the `.eslint-plugin-local` folder. Each rule is defined in its own TypeScript file. These follow the naming convention: + +- `code-RULE-NAME.ts` — General rules that apply to the entire repo. +- `vscode-dts-RULE-NAME.ts` — Rules that apply just to `vscode.d.ts`. + +These rules are then enabled in the `eslint.config.js` file. This is the main eslint configuration for our repo. It defines a set of file scopes which rules should apply to files in those scopes. + +For example, here's a configuration that enables the no `test.only` rule in all `*.test.ts` files in the VS Code repo: + +```ts +{ + // Define which files these rules apply to + files: [ + '**/*.test.ts' + ], + languageOptions: { parser: tseslint.parser, }, + plugins: { + 'local': pluginLocal, + }, + rules: { + // Enable the rule from .eslint-plugin-local/code-no-test-only.ts + 'local/code-no-test-only': 'error', + } +} +``` + +# Creating a new custom rule +This walks through the steps to create a new eslint rule: + +1. Create a new rule file under `.eslint-plugin-local`. Generally you should call it `code-YOUR-RULE-NAME.ts`, for example, `.eslint-plugin-local/code-no-not-null-assertions-on-undefined-values.ts` + +2. In this file, add the rule. Here's a template: + + ```ts + /*--------------------------------------------------------------------------------------------- + * 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'; + + export = new class YourRuleName implements eslint.Rule.RuleModule { + + readonly meta: eslint.Rule.RuleMetaData = { + messages: { + customMessageName: 'message text shown in errors/warnings', + }, + schema: false, + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + return { + [SELECTOR]: (node: any) => { + // Report errors if needed + return context.report({ + node, + messageId: 'customMessageName' + }); + } + }; + } + }; + ``` + + - Update the name of the class to match the name of your rule + - Add message entries for any errors you want to report + - Update `SELECTOR` with the [ESTree selector](https://eslint.org/docs/latest/extend/selectors) needed to target the nodes you are interested in. Use the [TypeScript ESLint playground](https://typescript-eslint.io/play/#showAST=es) to figure out which nodes you need and debug selectors + +3. Register the rule in `eslint.config.js` + + Generally this is just turning on the rule in the rule list like so: + + ```js + rules: { + // Name should match file name + 'local/code-no-not-null-assertions-on-undefined-values': 'warn', + ... + } + ``` + +Rules can also take custom arguments. For example, here's how we can pass arguments to a custom rule in the `eslint.config.js`: + +``` +rules: { + 'local/code-no-not-null-assertions-on-undefined-values': ['warn', { testsOk: true }], + ... +} +``` + +In these cases make sure to update the `meta.schema` property on your rule with the JSON schema for the arguments. You can access these arguments using `context.options` in the rule `create` function + + +## Adding fixes to custom rules +Fixes are a useful way to mechanically fix basic linting issues, such as auto inserting semicolons. These fixes typically work at the AST level, so they are a more reliable way to perform bulk fixes compared to find/replaces. + +To add a fix for a custom rule: + +1. On the `meta` for your rule, add `fixable: 'code'` + +2. When reporting an error in the rule, also include a `fix`. This is a function that takes a `fixer` argument and returns one or more fixes. + +See the [Double quoted to single quoted string covert fix](https://github.com/microsoft/vscode/blob/b074375e1884ae01033967bf0bbceeaa4795354a/.eslint-plugin-local/code-no-unexternalized-strings.ts#L128) for an example. The ESLint docs also have [details on adding fixes and the fixer api](https://eslint.org/docs/latest/extend/custom-rules#applying-fixes) + +The fixes can be run using `npx eslint --fix` in the VS Code repo diff --git a/.eslint-plugin-local/code-amd-node-module.ts b/.eslint-plugin-local/code-amd-node-module.ts index b622c98a89a..eb6a40c5e30 100644 --- a/.eslint-plugin-local/code-amd-node-module.ts +++ b/.eslint-plugin-local/code-amd-node-module.ts @@ -4,10 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; +import { readFileSync } from 'fs'; import { join } from 'path'; -export = new class ApiProviderNaming implements eslint.Rule.RuleModule { +export default new class ApiProviderNaming implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -21,7 +23,8 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule { const modules = new Set(); try { - const { dependencies, optionalDependencies } = require(join(__dirname, '../package.json')); + const packageJson = JSON.parse(readFileSync(join(import.meta.dirname, '../package.json'), 'utf-8')); + const { dependencies, optionalDependencies } = packageJson; const all = Object.keys(dependencies).concat(Object.keys(optionalDependencies)); for (const key of all) { modules.add(key); @@ -33,13 +36,13 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule { } - const checkImport = (node: any) => { + const checkImport = (node: ESTree.Literal & { parent?: ESTree.Node & { importKind?: string } }) => { - if (node.type !== 'Literal' || typeof node.value !== 'string') { + if (typeof node.value !== 'string') { return; } - if (node.parent.importKind === 'type') { + if (node.parent?.type === 'ImportDeclaration' && node.parent.importKind === 'type') { return; } diff --git a/.eslint-plugin-local/code-declare-service-brand.ts b/.eslint-plugin-local/code-declare-service-brand.ts index 85cf0671545..a077e7b38c6 100644 --- a/.eslint-plugin-local/code-declare-service-brand.ts +++ b/.eslint-plugin-local/code-declare-service-brand.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class DeclareServiceBrand implements eslint.Rule.RuleModule { +export default new class DeclareServiceBrand implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { fixable: 'code', @@ -14,7 +15,7 @@ export = new class DeclareServiceBrand implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['PropertyDefinition[key.name="_serviceBrand"][value]']: (node: any) => { + ['PropertyDefinition[key.name="_serviceBrand"][value]']: (node: ESTree.PropertyDefinition) => { return context.report({ node, message: `The '_serviceBrand'-property should not have a value`, diff --git a/.eslint-plugin-local/code-ensure-no-disposables-leak-in-test.ts b/.eslint-plugin-local/code-ensure-no-disposables-leak-in-test.ts index c657df9bd30..7f1d20482b8 100644 --- a/.eslint-plugin-local/code-ensure-no-disposables-leak-in-test.ts +++ b/.eslint-plugin-local/code-ensure-no-disposables-leak-in-test.ts @@ -4,9 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; -import { Node } from 'estree'; +import type * as estree from 'estree'; -export = new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rule.RuleModule { +export default new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { type: 'problem', @@ -18,7 +18,7 @@ export = new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rul }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - const config = <{ exclude: string[] }>context.options[0]; + const config = context.options[0] as { exclude: string[] }; const needle = context.getFilename().replace(/\\/g, '/'); if (config.exclude.some((e) => needle.endsWith(e))) { @@ -26,7 +26,7 @@ export = new class EnsureNoDisposablesAreLeakedInTestSuite implements eslint.Rul } return { - [`Program > ExpressionStatement > CallExpression[callee.name='suite']`]: (node: Node) => { + [`Program > ExpressionStatement > CallExpression[callee.name='suite']`]: (node: estree.Node) => { const src = context.getSourceCode().getText(node); if (!src.includes('ensureNoDisposablesAreLeakedInTestSuite(')) { context.report({ diff --git a/.eslint-plugin-local/code-import-patterns.ts b/.eslint-plugin-local/code-import-patterns.ts index e4beb9a4738..419e26d41ac 100644 --- a/.eslint-plugin-local/code-import-patterns.ts +++ b/.eslint-plugin-local/code-import-patterns.ts @@ -7,9 +7,9 @@ import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; import * as path from 'path'; import minimatch from 'minimatch'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -const REPO_ROOT = path.normalize(path.join(__dirname, '../')); +const REPO_ROOT = path.normalize(path.join(import.meta.dirname, '../')); interface ConditionalPattern { when?: 'hasBrowser' | 'hasNode' | 'hasElectron' | 'test'; @@ -31,7 +31,7 @@ interface LayerAllowRule { type RawOption = RawImportPatternsConfig | LayerAllowRule; function isLayerAllowRule(option: RawOption): option is LayerAllowRule { - return !!((option).when && (option).allow); + return !!((option as LayerAllowRule).when && (option as LayerAllowRule).allow); } interface ImportPatternsConfig { @@ -39,7 +39,7 @@ interface ImportPatternsConfig { restrictions: string[]; } -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -55,7 +55,7 @@ export = new class implements eslint.Rule.RuleModule { }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - const options = context.options; + const options = context.options as RawOption[]; const configs = this._processOptions(options); const relativeFilename = getRelativeFilename(context); @@ -217,7 +217,7 @@ export = new class implements eslint.Rule.RuleModule { configs.push(testConfig); } } else { - configs.push({ target, restrictions: restrictions.filter(r => typeof r === 'string') }); + configs.push({ target, restrictions: restrictions.filter(r => typeof r === 'string') as string[] }); } } this._optionsCache.set(options, configs); diff --git a/.eslint-plugin-local/code-layering.ts b/.eslint-plugin-local/code-layering.ts index f8b769a1bf6..ac77eb97cf0 100644 --- a/.eslint-plugin-local/code-layering.ts +++ b/.eslint-plugin-local/code-layering.ts @@ -5,14 +5,14 @@ import * as eslint from 'eslint'; import { join, dirname } from 'path'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; type Config = { allowed: Set; disallowed: Set; }; -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -38,8 +38,7 @@ export = new class implements eslint.Rule.RuleModule { const fileDirname = dirname(context.getFilename()); const parts = fileDirname.split(/\\|\//); - const ruleArgs = >context.options[0]; - + const ruleArgs = context.options[0] as Record; let config: Config | undefined; for (let i = parts.length - 1; i >= 0; i--) { if (ruleArgs[parts[i]]) { @@ -91,4 +90,3 @@ export = new class implements eslint.Rule.RuleModule { }); } }; - diff --git a/.eslint-plugin-local/code-limited-top-functions.ts b/.eslint-plugin-local/code-limited-top-functions.ts index 7b48d02a0fe..8c6abacc9d8 100644 --- a/.eslint-plugin-local/code-limited-top-functions.ts +++ b/.eslint-plugin-local/code-limited-top-functions.ts @@ -6,8 +6,9 @@ import * as eslint from 'eslint'; import { dirname, relative } from 'path'; import minimatch from 'minimatch'; +import type * as ESTree from 'estree'; -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -28,11 +29,11 @@ export = new class implements eslint.Rule.RuleModule { }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - let fileRelativePath = relative(dirname(__dirname), context.getFilename()); + let fileRelativePath = relative(dirname(import.meta.dirname), context.getFilename()); if (!fileRelativePath.endsWith('/')) { fileRelativePath += '/'; } - const ruleArgs = >context.options[0]; + const ruleArgs = context.options[0] as Record; const matchingKey = Object.keys(ruleArgs).find(key => fileRelativePath.startsWith(key) || minimatch(fileRelativePath, key)); if (!matchingKey) { @@ -43,8 +44,8 @@ export = new class implements eslint.Rule.RuleModule { const restrictedFunctions = ruleArgs[matchingKey]; return { - FunctionDeclaration: (node: any) => { - const isTopLevel = node.parent.type === 'Program'; + FunctionDeclaration: (node: ESTree.FunctionDeclaration & { parent?: ESTree.Node }) => { + const isTopLevel = node.parent?.type === 'Program'; const functionName = node.id.name; if (isTopLevel && !restrictedFunctions.includes(node.id.name)) { context.report({ @@ -53,10 +54,10 @@ export = new class implements eslint.Rule.RuleModule { }); } }, - ExportNamedDeclaration(node: any) { + ExportNamedDeclaration(node: ESTree.ExportNamedDeclaration & { parent?: ESTree.Node }) { if (node.declaration && node.declaration.type === 'FunctionDeclaration') { const functionName = node.declaration.id.name; - const isTopLevel = node.parent.type === 'Program'; + const isTopLevel = node.parent?.type === 'Program'; if (isTopLevel && !restrictedFunctions.includes(node.declaration.id.name)) { context.report({ node, diff --git a/.eslint-plugin-local/code-must-use-result.ts b/.eslint-plugin-local/code-must-use-result.ts index e249f36dccf..b97396c7e52 100644 --- a/.eslint-plugin-local/code-must-use-result.ts +++ b/.eslint-plugin-local/code-must-use-result.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; const VALID_USES = new Set([ @@ -11,22 +12,22 @@ const VALID_USES = new Set([ TSESTree.AST_NODE_TYPES.VariableDeclarator, ]); -export = new class MustUseResults implements eslint.Rule.RuleModule { +export default new class MustUseResults implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { schema: false }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - const config = <{ message: string; functions: string[] }[]>context.options[0]; + const config = context.options[0] as { message: string; functions: string[] }[]; const listener: eslint.Rule.RuleListener = {}; for (const { message, functions } of config) { for (const fn of functions) { const query = `CallExpression[callee.property.name='${fn}'], CallExpression[callee.name='${fn}']`; - listener[query] = (node: any) => { - const cast: TSESTree.CallExpression = node; - if (!VALID_USES.has(cast.parent?.type)) { + listener[query] = (node: ESTree.Node) => { + const callExpression = node as TSESTree.CallExpression; + if (!VALID_USES.has(callExpression.parent?.type)) { context.report({ node, message }); } }; diff --git a/.eslint-plugin-local/code-must-use-super-dispose.ts b/.eslint-plugin-local/code-must-use-super-dispose.ts index ca776d8a2ad..0213d200957 100644 --- a/.eslint-plugin-local/code-must-use-super-dispose.ts +++ b/.eslint-plugin-local/code-must-use-super-dispose.ts @@ -3,18 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class NoAsyncSuite implements eslint.Rule.RuleModule { +export default new class NoAsyncSuite implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - function doesCallSuperDispose(node: any) { + function doesCallSuperDispose(node: TSESTree.MethodDefinition) { if (!node.override) { return; } - const body = context.getSourceCode().getText(node); + const body = context.getSourceCode().getText(node as ESTree.Node); if (body.includes('super.dispose')) { return; diff --git a/.eslint-plugin-local/code-no-any-casts.ts b/.eslint-plugin-local/code-no-any-casts.ts index ec1ea1ec3d5..87c3c9466cd 100644 --- a/.eslint-plugin-local/code-no-any-casts.ts +++ b/.eslint-plugin-local/code-no-any-casts.ts @@ -6,7 +6,7 @@ import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; -export = new class NoAnyCasts implements eslint.Rule.RuleModule { +export default new class NoAnyCasts implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { diff --git a/.eslint-plugin-local/code-no-dangerous-type-assertions.ts b/.eslint-plugin-local/code-no-dangerous-type-assertions.ts index f900d778a94..b2e97943670 100644 --- a/.eslint-plugin-local/code-no-dangerous-type-assertions.ts +++ b/.eslint-plugin-local/code-no-dangerous-type-assertions.ts @@ -4,20 +4,16 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; -export = new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule { +export default new class NoDangerousTypeAssertions implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - // Disable in tests for now - if (context.getFilename().includes('.test')) { - return {}; - } - return { // Disallow type assertions on object literals: { ... } or {} as T - ['TSTypeAssertion > ObjectExpression, TSAsExpression > ObjectExpression']: (node: any) => { - const objectNode = node as TSESTree.Node; + ['TSTypeAssertion > ObjectExpression, TSAsExpression > ObjectExpression']: (node: ESTree.ObjectExpression) => { + const objectNode = node as TSESTree.ObjectExpression; const parent = objectNode.parent as TSESTree.TSTypeAssertion | TSESTree.TSAsExpression; if ( diff --git a/.eslint-plugin-local/code-no-deep-import-of-internal.ts b/.eslint-plugin-local/code-no-deep-import-of-internal.ts index 3f54665b49a..cb2d450d2ee 100644 --- a/.eslint-plugin-local/code-no-deep-import-of-internal.ts +++ b/.eslint-plugin-local/code-no-deep-import-of-internal.ts @@ -5,9 +5,9 @@ import * as eslint from 'eslint'; import { join, dirname } from 'path'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -28,8 +28,8 @@ export = new class implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { const patterns = context.options[0] as Record; - const internalModulePattern = Object.entries(patterns).map(([key, v]) => v ? key : undefined).filter(v => !!v); - const allowedPatterns = Object.entries(patterns).map(([key, v]) => !v ? key : undefined).filter(v => !!v); + const internalModulePattern = Object.entries(patterns).map(([key, v]) => v ? key : undefined).filter((v): v is string => !!v); + const allowedPatterns = Object.entries(patterns).map(([key, v]) => !v ? key : undefined).filter((v): v is string => !!v); return createImportRuleListener((node, path) => { const importerModuleDir = dirname(context.filename); diff --git a/.eslint-plugin-local/code-no-global-document-listener.ts b/.eslint-plugin-local/code-no-global-document-listener.ts index 049426a5a03..ad4ec0da820 100644 --- a/.eslint-plugin-local/code-no-global-document-listener.ts +++ b/.eslint-plugin-local/code-no-global-document-listener.ts @@ -5,7 +5,7 @@ import * as eslint from 'eslint'; -export = new class NoGlobalDocumentListener implements eslint.Rule.RuleModule { +export default new class NoGlobalDocumentListener implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { diff --git a/.eslint-plugin-local/code-no-in-operator.ts b/.eslint-plugin-local/code-no-in-operator.ts new file mode 100644 index 00000000000..026a8f5fe7a --- /dev/null +++ b/.eslint-plugin-local/code-no-in-operator.ts @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import type * as ESTree from 'estree'; +import { TSESTree } from '@typescript-eslint/utils'; + +/** + * Disallows the use of the `in` operator in TypeScript code, except within + * type predicate functions (functions with `arg is Type` return types). + * + * The `in` operator can lead to runtime errors and type safety issues. + * Consider using Object.hasOwn(), hasOwnProperty(), or other safer patterns. + * + * Exception: Type predicate functions are allowed to use the `in` operator + * since they are the standard way to perform runtime type checking. + */ +export default new class NoInOperator implements eslint.Rule.RuleModule { + + readonly meta: eslint.Rule.RuleMetaData = { + messages: { + noInOperator: 'The "in" operator should not be used. Use type discriminator properties and classes instead or the `hasKey`-utility.', + }, + schema: false, + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + + function checkInOperator(inNode: ESTree.BinaryExpression) { + const node = inNode as TSESTree.BinaryExpression; + // Check if we're inside a type predicate function + const ancestors = context.sourceCode.getAncestors(node as ESTree.Node); + + for (const ancestor of ancestors) { + if (ancestor.type === 'FunctionDeclaration' || + ancestor.type === 'FunctionExpression' || + ancestor.type === 'ArrowFunctionExpression') { + + // Check if this function has a type predicate return type + // Type predicates have the form: `arg is SomeType` + if ((ancestor as { returnType?: any }).returnType?.typeAnnotation?.type === 'TSTypePredicate') { + // This is a type predicate function, allow the "in" operator + return; + } + } + } + + context.report({ + node, + messageId: 'noInOperator' + }); + } + + return { + ['BinaryExpression[operator="in"]']: checkInOperator, + }; + } +}; diff --git a/.eslint-plugin-local/code-no-localization-template-literals.ts b/.eslint-plugin-local/code-no-localization-template-literals.ts new file mode 100644 index 00000000000..30a5de7f364 --- /dev/null +++ b/.eslint-plugin-local/code-no-localization-template-literals.ts @@ -0,0 +1,90 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import { TSESTree } from '@typescript-eslint/utils'; + +/** + * Prevents the use of template literals in localization function calls. + * + * vscode.l10n.t() and nls.localize() cannot handle string templating. + * Use placeholders instead: vscode.l10n.t('Message {0}', value) + * + * Examples: + * ❌ vscode.l10n.t(`Message ${value}`) + * ✅ vscode.l10n.t('Message {0}', value) + * + * ❌ nls.localize('key', `Message ${value}`) + * ✅ nls.localize('key', 'Message {0}', value) + */ +export default new class NoLocalizationTemplateLiterals implements eslint.Rule.RuleModule { + + readonly meta: eslint.Rule.RuleMetaData = { + messages: { + noTemplateLiteral: 'Template literals cannot be used in localization calls. Use placeholders like {0}, {1} instead.' + }, + docs: { + description: 'Prevents template literals in vscode.l10n.t() and nls.localize() calls', + }, + schema: false, + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + + function checkCallExpression(node: TSESTree.CallExpression) { + const callee = node.callee; + let isLocalizationCall = false; + let isNlsLocalize = false; + + // Check for vscode.l10n.t() + if (callee.type === 'MemberExpression') { + const object = callee.object; + const property = callee.property; + + // vscode.l10n.t + if (object.type === 'MemberExpression') { + const outerObject = object.object; + const outerProperty = object.property; + if (outerObject.type === 'Identifier' && outerObject.name === 'vscode' && + outerProperty.type === 'Identifier' && outerProperty.name === 'l10n' && + property.type === 'Identifier' && property.name === 't') { + isLocalizationCall = true; + } + } + + // l10n.t or nls.localize or any *.localize + if (object.type === 'Identifier' && property.type === 'Identifier') { + if (object.name === 'l10n' && property.name === 't') { + isLocalizationCall = true; + } else if (property.name === 'localize') { + isLocalizationCall = true; + isNlsLocalize = true; + } + } + } + + if (!isLocalizationCall) { + return; + } + + // For vscode.l10n.t(message, ...args) - check the first argument (message) + // For nls.localize(key, message, ...args) - check first two arguments (key and message) + const argsToCheck = isNlsLocalize ? 2 : 1; + for (let i = 0; i < argsToCheck && i < node.arguments.length; i++) { + const arg = node.arguments[i]; + if (arg && arg.type === 'TemplateLiteral' && arg.expressions.length > 0) { + context.report({ + node: arg, + messageId: 'noTemplateLiteral' + }); + } + } + } + + return { + CallExpression: (node: any) => checkCallExpression(node as TSESTree.CallExpression) + }; + } +}; diff --git a/.eslint-plugin-local/code-no-localized-model-description.ts b/.eslint-plugin-local/code-no-localized-model-description.ts new file mode 100644 index 00000000000..a624aeb8619 --- /dev/null +++ b/.eslint-plugin-local/code-no-localized-model-description.ts @@ -0,0 +1,128 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { TSESTree } from '@typescript-eslint/utils'; +import * as eslint from 'eslint'; +import * as visitorKeys from 'eslint-visitor-keys'; +import type * as ESTree from 'estree'; + +const MESSAGE_ID = 'noLocalizedModelDescription'; +type NodeWithChildren = TSESTree.Node & { + [key: string]: TSESTree.Node | TSESTree.Node[] | null | undefined; +}; +type PropertyKeyNode = TSESTree.Property['key'] | TSESTree.MemberExpression['property']; +type AssignmentTarget = TSESTree.AssignmentExpression['left']; + +export default new class NoLocalizedModelDescriptionRule implements eslint.Rule.RuleModule { + meta: eslint.Rule.RuleMetaData = { + messages: { + [MESSAGE_ID]: 'modelDescription values describe behavior to the language model and must not use localized strings.' + }, + type: 'problem', + schema: false + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + const reportIfLocalized = (expression: TSESTree.Expression | null | undefined) => { + if (expression && containsLocalizedCall(expression)) { + context.report({ node: expression, messageId: MESSAGE_ID }); + } + }; + + return { + Property: (node: ESTree.Property) => { + const propertyNode = node as TSESTree.Property; + if (!isModelDescriptionKey(propertyNode.key, propertyNode.computed)) { + return; + } + reportIfLocalized(propertyNode.value as TSESTree.Expression); + }, + AssignmentExpression: (node: ESTree.AssignmentExpression) => { + const assignment = node as TSESTree.AssignmentExpression; + if (!isModelDescriptionAssignmentTarget(assignment.left)) { + return; + } + reportIfLocalized(assignment.right); + } + }; + } +}; + +function isModelDescriptionKey(key: PropertyKeyNode, computed: boolean | undefined): boolean { + if (!computed && key.type === 'Identifier') { + return key.name === 'modelDescription'; + } + if (key.type === 'Literal' && key.value === 'modelDescription') { + return true; + } + return false; +} + +function isModelDescriptionAssignmentTarget(target: AssignmentTarget): target is TSESTree.MemberExpression { + if (target.type === 'MemberExpression') { + return isModelDescriptionKey(target.property, target.computed); + } + return false; +} + +function containsLocalizedCall(expression: TSESTree.Expression): boolean { + let found = false; + + const visit = (node: TSESTree.Node) => { + if (found) { + return; + } + + if (isLocalizeCall(node)) { + found = true; + return; + } + + for (const key of visitorKeys.KEYS[node.type] ?? []) { + const value = (node as NodeWithChildren)[key]; + if (Array.isArray(value)) { + for (const child of value) { + if (child) { + visit(child); + if (found) { + return; + } + } + } + } else if (value) { + visit(value); + } + } + }; + + visit(expression); + return found; +} + +function isLocalizeCall(node: TSESTree.Node): boolean { + if (node.type === 'CallExpression') { + return isLocalizeCallee(node.callee); + } + if (node.type === 'ChainExpression') { + return isLocalizeCall(node.expression); + } + return false; +} + + +function isLocalizeCallee(callee: TSESTree.CallExpression['callee']): boolean { + if (callee.type === 'Identifier') { + return callee.name === 'localize'; + } + if (callee.type === 'MemberExpression') { + if (!callee.computed && callee.property.type === 'Identifier') { + return callee.property.name === 'localize'; + } + if (callee.property.type === 'Literal' && callee.property.value === 'localize') { + return true; + } + } + return false; +} diff --git a/.eslint-plugin-local/code-no-native-private.ts b/.eslint-plugin-local/code-no-native-private.ts index e2d20694ca8..5d945ec34f7 100644 --- a/.eslint-plugin-local/code-no-native-private.ts +++ b/.eslint-plugin-local/code-no-native-private.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class ApiProviderNaming implements eslint.Rule.RuleModule { +export default new class ApiProviderNaming implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -17,13 +18,13 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['PropertyDefinition PrivateIdentifier']: (node: any) => { + ['PropertyDefinition PrivateIdentifier']: (node: ESTree.Node) => { context.report({ node, messageId: 'slow' }); }, - ['MethodDefinition PrivateIdentifier']: (node: any) => { + ['MethodDefinition PrivateIdentifier']: (node: ESTree.Node) => { context.report({ node, messageId: 'slow' diff --git a/.eslint-plugin-local/code-no-nls-in-standalone-editor.ts b/.eslint-plugin-local/code-no-nls-in-standalone-editor.ts index c0d60985604..2b3896795a8 100644 --- a/.eslint-plugin-local/code-no-nls-in-standalone-editor.ts +++ b/.eslint-plugin-local/code-no-nls-in-standalone-editor.ts @@ -5,9 +5,9 @@ import * as eslint from 'eslint'; import { join } from 'path'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule { +export default new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { diff --git a/.eslint-plugin-local/code-no-observable-get-in-reactive-context.ts b/.eslint-plugin-local/code-no-observable-get-in-reactive-context.ts index 2fa8e0bd9b5..94d3a1b4ead 100644 --- a/.eslint-plugin-local/code-no-observable-get-in-reactive-context.ts +++ b/.eslint-plugin-local/code-no-observable-get-in-reactive-context.ts @@ -6,9 +6,9 @@ import { TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; import * as visitorKeys from 'eslint-visitor-keys'; -import * as ESTree from 'estree'; +import type * as ESTree from 'estree'; -export = new class NoObservableGetInReactiveContext implements eslint.Rule.RuleModule { +export default new class NoObservableGetInReactiveContext implements eslint.Rule.RuleModule { meta: eslint.Rule.RuleMetaData = { type: 'problem', docs: { @@ -19,7 +19,7 @@ export = new class NoObservableGetInReactiveContext implements eslint.Rule.RuleM create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - 'CallExpression': (node: any) => { + 'CallExpression': (node: ESTree.CallExpression) => { const callExpression = node as TSESTree.CallExpression; if (!isReactiveFunctionWithReader(callExpression.callee)) { diff --git a/.eslint-plugin-local/code-no-potentially-unsafe-disposables.ts b/.eslint-plugin-local/code-no-potentially-unsafe-disposables.ts index 69976275051..bc250df1182 100644 --- a/.eslint-plugin-local/code-no-potentially-unsafe-disposables.ts +++ b/.eslint-plugin-local/code-no-potentially-unsafe-disposables.ts @@ -4,23 +4,24 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; /** * Checks for potentially unsafe usage of `DisposableStore` / `MutableDisposable`. * * These have been the source of leaks in the past. */ -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - function checkVariableDeclaration(inNode: any) { + function checkVariableDeclaration(inNode: ESTree.Node) { context.report({ node: inNode, message: `Use const for 'DisposableStore' to avoid leaks by accidental reassignment.` }); } - function checkProperty(inNode: any) { + function checkProperty(inNode: ESTree.Node) { context.report({ node: inNode, message: `Use readonly for DisposableStore/MutableDisposable to avoid leaks through accidental reassignment.` @@ -28,10 +29,10 @@ export = new class implements eslint.Rule.RuleModule { } return { - 'VariableDeclaration[kind!="const"] NewExpression[callee.name="DisposableStore"]': checkVariableDeclaration, + 'VariableDeclaration[kind!="const"] > VariableDeclarator > NewExpression[callee.name="DisposableStore"]': checkVariableDeclaration, 'PropertyDefinition[readonly!=true][typeAnnotation.typeAnnotation.typeName.name=/DisposableStore|MutableDisposable/]': checkProperty, - 'PropertyDefinition[readonly!=true] NewExpression[callee.name=/DisposableStore|MutableDisposable/]': checkProperty, + 'PropertyDefinition[readonly!=true] > NewExpression[callee.name=/DisposableStore|MutableDisposable/]': checkProperty, }; } }; diff --git a/.eslint-plugin-local/code-no-reader-after-await.ts b/.eslint-plugin-local/code-no-reader-after-await.ts index 545e1fd050a..6d0e8d39b06 100644 --- a/.eslint-plugin-local/code-no-reader-after-await.ts +++ b/.eslint-plugin-local/code-no-reader-after-await.ts @@ -5,11 +5,12 @@ import { TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class NoReaderAfterAwait implements eslint.Rule.RuleModule { +export default new class NoReaderAfterAwait implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - 'CallExpression': (node: any) => { + 'CallExpression': (node: ESTree.CallExpression) => { const callExpression = node as TSESTree.CallExpression; if (!isFunctionWithReader(callExpression.callee)) { diff --git a/.eslint-plugin-local/code-no-runtime-import.ts b/.eslint-plugin-local/code-no-runtime-import.ts index afebe0b0d68..2c53d84f973 100644 --- a/.eslint-plugin-local/code-no-runtime-import.ts +++ b/.eslint-plugin-local/code-no-runtime-import.ts @@ -7,9 +7,9 @@ import { TSESTree } from '@typescript-eslint/typescript-estree'; import * as eslint from 'eslint'; import { dirname, join, relative } from 'path'; import minimatch from 'minimatch'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -30,11 +30,11 @@ export = new class implements eslint.Rule.RuleModule { }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - let fileRelativePath = relative(dirname(__dirname), context.getFilename()); + let fileRelativePath = relative(dirname(import.meta.dirname), context.getFilename()); if (!fileRelativePath.endsWith('/')) { fileRelativePath += '/'; } - const ruleArgs = >context.options[0]; + const ruleArgs = context.options[0] as Record; const matchingKey = Object.keys(ruleArgs).find(key => fileRelativePath.startsWith(key) || minimatch(fileRelativePath, key)); if (!matchingKey) { diff --git a/.eslint-plugin-local/code-no-standalone-editor.ts b/.eslint-plugin-local/code-no-standalone-editor.ts index 36bf48b1417..dca4e22bfb0 100644 --- a/.eslint-plugin-local/code-no-standalone-editor.ts +++ b/.eslint-plugin-local/code-no-standalone-editor.ts @@ -5,9 +5,9 @@ import * as eslint from 'eslint'; import { join } from 'path'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -export = new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule { +export default new class NoNlsInStandaloneEditorRule implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { diff --git a/.eslint-plugin-local/code-no-static-self-ref.ts b/.eslint-plugin-local/code-no-static-self-ref.ts index 94287b8311c..9a47f87b9c1 100644 --- a/.eslint-plugin-local/code-no-static-self-ref.ts +++ b/.eslint-plugin-local/code-no-static-self-ref.ts @@ -4,20 +4,20 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; -import * as ESTree from 'estree'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; /** * WORKAROUND for https://github.com/evanw/esbuild/issues/3823 */ -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - function checkProperty(inNode: any) { + function checkProperty(inNode: TSESTree.PropertyDefinition) { - const classDeclaration = context.sourceCode.getAncestors(inNode).find(node => node.type === 'ClassDeclaration'); - const propertyDefinition = inNode; + const classDeclaration = context.sourceCode.getAncestors(inNode as ESTree.Node).find(node => node.type === 'ClassDeclaration'); + const propertyDefinition = inNode; if (!classDeclaration || !classDeclaration.id?.name) { return; diff --git a/.eslint-plugin-local/code-no-test-async-suite.ts b/.eslint-plugin-local/code-no-test-async-suite.ts index 60a0f2153ab..b53747390b0 100644 --- a/.eslint-plugin-local/code-no-test-async-suite.ts +++ b/.eslint-plugin-local/code-no-test-async-suite.ts @@ -3,8 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; +import { TSESTree } from '@typescript-eslint/utils'; function isCallExpression(node: TSESTree.Node): node is TSESTree.CallExpression { return node.type === 'CallExpression'; @@ -14,13 +15,14 @@ function isFunctionExpression(node: TSESTree.Node): node is TSESTree.FunctionExp return node.type.includes('FunctionExpression'); } -export = new class NoAsyncSuite implements eslint.Rule.RuleModule { +export default new class NoAsyncSuite implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - function hasAsyncSuite(node: any) { - if (isCallExpression(node) && node.arguments.length >= 2 && isFunctionExpression(node.arguments[1]) && node.arguments[1].async) { + function hasAsyncSuite(node: ESTree.Node) { + const tsNode = node as TSESTree.Node; + if (isCallExpression(tsNode) && tsNode.arguments.length >= 2 && isFunctionExpression(tsNode.arguments[1]) && tsNode.arguments[1].async) { return context.report({ - node: node, + node: tsNode, message: 'suite factory function should never be async' }); } diff --git a/.eslint-plugin-local/code-no-test-only.ts b/.eslint-plugin-local/code-no-test-only.ts index d4751eef2ee..389d32fe13b 100644 --- a/.eslint-plugin-local/code-no-test-only.ts +++ b/.eslint-plugin-local/code-no-test-only.ts @@ -4,12 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class NoTestOnly implements eslint.Rule.RuleModule { +export default new class NoTestOnly implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['MemberExpression[object.name=/^(test|suite)$/][property.name="only"]']: (node: any) => { + ['MemberExpression[object.name=/^(test|suite)$/][property.name="only"]']: (node: ESTree.MemberExpression) => { return context.report({ node, message: 'only is a dev-time tool and CANNOT be pushed' diff --git a/.eslint-plugin-local/code-no-unexternalized-strings.ts b/.eslint-plugin-local/code-no-unexternalized-strings.ts index 74c712e56fd..a7065cb2a0d 100644 --- a/.eslint-plugin-local/code-no-unexternalized-strings.ts +++ b/.eslint-plugin-local/code-no-unexternalized-strings.ts @@ -5,7 +5,7 @@ import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; -import * as ESTree from 'estree'; +import type * as ESTree from 'estree'; function isStringLiteral(node: TSESTree.Node | ESTree.Node | null | undefined): node is TSESTree.StringLiteral { return !!node && node.type === AST_NODE_TYPES.Literal && typeof node.value === 'string'; @@ -15,7 +15,16 @@ function isDoubleQuoted(node: TSESTree.StringLiteral): boolean { return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"'; } -export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule { +/** + * Enable bulk fixing double-quoted strings to single-quoted strings with the --fix eslint flag + * + * Disabled by default as this is often not the desired fix. Instead the string should be localized. However it is + * useful for bulk conversations of existing code. + */ +const enableDoubleToSingleQuoteFixes = false; + + +export default new class NoUnexternalizedStrings implements eslint.Rule.RuleModule { private static _rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/; @@ -27,6 +36,7 @@ export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule { badMessage: 'Message argument to \'{{message}}\' must be a string literal.' }, schema: false, + fixable: enableDoubleToSingleQuoteFixes ? 'code' : undefined, }; create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { @@ -90,9 +100,7 @@ export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule { function visitL10NCall(node: TSESTree.CallExpression) { // localize(key, message) - const [messageNode] = (node).arguments; - - // remove message-argument from doubleQuoted list and make + const [messageNode] = (node as TSESTree.CallExpression).arguments; // remove message-argument from doubleQuoted list and make // sure it is a string-literal if (isStringLiteral(messageNode)) { doubleQuotedStringLiterals.delete(messageNode); @@ -112,7 +120,30 @@ export = new class NoUnexternalizedStrings implements eslint.Rule.RuleModule { // (1) // report all strings that are in double quotes for (const node of doubleQuotedStringLiterals) { - context.report({ loc: node.loc, messageId: 'doubleQuoted' }); + context.report({ + loc: node.loc, + messageId: 'doubleQuoted', + fix: enableDoubleToSingleQuoteFixes ? (fixer) => { + // Get the raw string content, unescaping any escaped quotes + const content = (node as ESTree.SimpleLiteral).raw! + .slice(1, -1) + .replace(/(? Boolean) the function used to make the determination * @param list the input list @@ -83,7 +83,7 @@ module.exports = { return list.slice(); } - + /** * @param node a Program or BlockStatement node * @returns the leading sequence of directive nodes in the given node's body @@ -92,7 +92,7 @@ module.exports = { return takeWhile(looksLikeDirective, node.body); } - + /** * @param node any node * @param ancestors the given node's ancestors @@ -141,8 +141,8 @@ module.exports = { return { ExpressionStatement(node: TSESTree.ExpressionStatement) { - if (!isValidExpression(node.expression) && !isDirective(node, context.sourceCode.getAncestors(node))) { - context.report({ node: node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` }); + if (!isValidExpression(node.expression) && !isDirective(node, context.sourceCode.getAncestors(node as ESTree.Node) as TSESTree.Node[])) { + context.report({ node: node as ESTree.Node, message: `Expected an assignment or function call and instead saw an expression. ${node.expression}` }); } } }; diff --git a/.eslint-plugin-local/code-parameter-properties-must-have-explicit-accessibility.ts b/.eslint-plugin-local/code-parameter-properties-must-have-explicit-accessibility.ts index c9837052fa5..f00d3e1435c 100644 --- a/.eslint-plugin-local/code-parameter-properties-must-have-explicit-accessibility.ts +++ b/.eslint-plugin-local/code-parameter-properties-must-have-explicit-accessibility.ts @@ -3,19 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; +import * as eslint from 'eslint'; /** * Enforces that all parameter properties have an explicit access modifier (public, protected, private). * * This catches a common bug where a service is accidentally made public by simply writing: `readonly prop: Foo` */ -export = new class implements eslint.Rule.RuleModule { +export default new class implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - function check(inNode: any) { - const node: TSESTree.TSParameterProperty = inNode; + function check(node: TSESTree.TSParameterProperty) { // For now, only apply to injected services const firstDecorator = node.decorators?.at(0); @@ -28,7 +27,7 @@ export = new class implements eslint.Rule.RuleModule { if (!node.accessibility) { context.report({ - node: inNode, + node: node, message: 'Parameter properties must have an explicit access modifier.' }); } diff --git a/.eslint-plugin-local/code-policy-localization-key-match.ts b/.eslint-plugin-local/code-policy-localization-key-match.ts new file mode 100644 index 00000000000..10749d5bb00 --- /dev/null +++ b/.eslint-plugin-local/code-policy-localization-key-match.ts @@ -0,0 +1,146 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; +import type * as ESTree from 'estree'; + +/** + * Ensures that localization keys in policy blocks match the keys used in nls.localize() calls. + * + * For example, in a policy block with: + * ``` + * localization: { + * description: { + * key: 'autoApprove2.description', + * value: nls.localize('autoApprove2.description', '...') + * } + * } + * ``` + * + * The key property ('autoApprove2.description') must match the first argument + * to nls.localize() ('autoApprove2.description'). + */ +export default new class PolicyLocalizationKeyMatch implements eslint.Rule.RuleModule { + + readonly meta: eslint.Rule.RuleMetaData = { + messages: { + mismatch: 'Localization key "{{keyValue}}" does not match the key used in nls.localize("{{localizeKey}}", ...). They must be identical.' + }, + docs: { + description: 'Ensures that localization keys in policy blocks match the keys used in nls.localize() calls', + }, + schema: false, + }; + + create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { + + function checkLocalizationObject(node: ESTree.ObjectExpression) { + // Look for objects with structure: { key: '...', value: nls.localize('...', '...') } + + let keyProperty: ESTree.Property | undefined; + let valueProperty: ESTree.Property | undefined; + + for (const property of node.properties) { + if (property.type !== 'Property') { + continue; + } + + const propertyKey = property.key; + if (propertyKey.type === 'Identifier') { + if (propertyKey.name === 'key') { + keyProperty = property; + } else if (propertyKey.name === 'value') { + valueProperty = property; + } + } + } + + if (!keyProperty || !valueProperty) { + return; + } + + // Extract the key value (should be a string literal) + let keyValue: string | undefined; + if (keyProperty.value.type === 'Literal' && typeof keyProperty.value.value === 'string') { + keyValue = keyProperty.value.value; + } + + if (!keyValue) { + return; + } + + // Check if value is a call to localize or any namespace's localize method + if (valueProperty.value.type === 'CallExpression') { + const callee = valueProperty.value.callee; + + // Check if it's .localize or just localize + let isLocalizeCall = false; + if (callee.type === 'MemberExpression') { + const object = callee.object; + const property = callee.property; + if (object.type === 'Identifier' && + property.type === 'Identifier' && property.name === 'localize') { + isLocalizeCall = true; + } + } else if (callee.type === 'Identifier' && callee.name === 'localize') { + // Direct localize() call + isLocalizeCall = true; + } + + if (isLocalizeCall) { + // Get the first argument to localize (the key) + const args = valueProperty.value.arguments; + if (args.length > 0) { + const firstArg = args[0]; + if (firstArg.type === 'Literal' && typeof firstArg.value === 'string') { + const localizeKey = firstArg.value; + + // Compare the keys + if (keyValue !== localizeKey) { + context.report({ + node: keyProperty.value, + messageId: 'mismatch', + data: { + keyValue, + localizeKey + } + }); + } + } + } + } + } + } + + function isInPolicyBlock(node: ESTree.Node): boolean { + // Walk up the AST to see if we're inside a policy object + const ancestors = context.sourceCode.getAncestors(node); + + for (const ancestor of ancestors) { + if (ancestor.type === 'Property') { + // eslint-disable-next-line local/code-no-any-casts + const property = ancestor as any; + if (property.key && property.key.type === 'Identifier' && property.key.name === 'policy') { + return true; + } + } + } + + return false; + } + + return { + 'ObjectExpression': (node: ESTree.ObjectExpression) => { + // Only check objects inside policy blocks + if (!isInPolicyBlock(node)) { + return; + } + + // Check if this object has the pattern we're looking for + checkLocalizationObject(node); + } + }; + } +}; diff --git a/.eslint-plugin-local/code-translation-remind.ts b/.eslint-plugin-local/code-translation-remind.ts index cceaba4c419..42032321167 100644 --- a/.eslint-plugin-local/code-translation-remind.ts +++ b/.eslint-plugin-local/code-translation-remind.ts @@ -6,10 +6,10 @@ import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; import { readFileSync } from 'fs'; -import { createImportRuleListener } from './utils'; +import { createImportRuleListener } from './utils.ts'; -export = new class TranslationRemind implements eslint.Rule.RuleModule { +export default new class TranslationRemind implements eslint.Rule.RuleModule { private static NLS_MODULE = 'vs/nls'; diff --git a/.eslint-plugin-local/index.js b/.eslint-plugin-local/index.js deleted file mode 100644 index ad00191fb6f..00000000000 --- a/.eslint-plugin-local/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -// @ts-check -const glob = require('glob'); -const path = require('path'); - -require('ts-node').register({ - experimentalResolver: true, - transpileOnly: true, - compilerOptions: { - module: 'nodenext', - moduleResolution: 'nodenext', - } -}); - -// Re-export all .ts files as rules -/** @type {Record} */ -const rules = {}; -glob.sync(`${__dirname}/*.ts`).forEach((file) => { - rules[path.basename(file, '.ts')] = require(file); -}); - -exports.rules = rules; diff --git a/.eslint-plugin-local/index.ts b/.eslint-plugin-local/index.ts new file mode 100644 index 00000000000..101733773f0 --- /dev/null +++ b/.eslint-plugin-local/index.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import type { LooseRuleDefinition } from '@typescript-eslint/utils/ts-eslint'; +import glob from 'glob'; +import { createRequire } from 'module'; +import path from 'path'; + +const require = createRequire(import.meta.url); + +// Re-export all .ts files as rules +const rules: Record = {}; +glob.sync(`${import.meta.dirname}/*.ts`) + .filter(file => !file.endsWith('index.ts') && !file.endsWith('utils.ts')) + .map(file => { + rules[path.basename(file, '.ts')] = require(file).default; + }); + +export { rules }; diff --git a/.eslint-plugin-local/package.json b/.eslint-plugin-local/package.json index a0df0c86778..90e7facf0a0 100644 --- a/.eslint-plugin-local/package.json +++ b/.eslint-plugin-local/package.json @@ -1,3 +1,7 @@ { - "type": "commonjs" + "private": true, + "type": "module", + "scripts": { + "typecheck": "tsgo -p tsconfig.json --noEmit" + } } diff --git a/.eslint-plugin-local/tsconfig.json b/.eslint-plugin-local/tsconfig.json index 7676f59a781..4f199170a11 100644 --- a/.eslint-plugin-local/tsconfig.json +++ b/.eslint-plugin-local/tsconfig.json @@ -4,23 +4,26 @@ "lib": [ "ES2024" ], - "module": "commonjs", - "esModuleInterop": true, - "alwaysStrict": true, - "allowJs": true, + "rootDir": ".", + "module": "esnext", + "allowImportingTsExtensions": true, + "erasableSyntaxOnly": true, + "noEmit": true, "strict": true, "exactOptionalPropertyTypes": false, "useUnknownInCatchVariables": false, "noUnusedLocals": true, "noUnusedParameters": true, "newLine": "lf", - "noEmit": true + "typeRoots": [ + "." + ] }, "include": [ - "**/*.ts", - "**/*.js" + "./**/*.ts", ], "exclude": [ - "node_modules/**" + "node_modules/**", + "./tests/**" ] } diff --git a/.eslint-plugin-local/utils.ts b/.eslint-plugin-local/utils.ts index b7457884f85..e956e679148 100644 --- a/.eslint-plugin-local/utils.ts +++ b/.eslint-plugin-local/utils.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; export function createImportRuleListener(validateImport: (node: TSESTree.Literal, value: string) => any): eslint.Rule.RuleListener { @@ -16,24 +17,24 @@ export function createImportRuleListener(validateImport: (node: TSESTree.Literal return { // import ??? from 'module' - ImportDeclaration: (node: any) => { - _checkImport((node).source); + ImportDeclaration: (node: ESTree.ImportDeclaration) => { + _checkImport((node as TSESTree.ImportDeclaration).source); }, // import('module').then(...) OR await import('module') - ['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node: any) => { + ['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node: TSESTree.Literal) => { _checkImport(node); }, // import foo = ... - ['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node: any) => { + ['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node: TSESTree.Literal) => { _checkImport(node); }, // export ?? from 'module' - ExportAllDeclaration: (node: any) => { - _checkImport((node).source); + ExportAllDeclaration: (node: ESTree.ExportAllDeclaration) => { + _checkImport((node as TSESTree.ExportAllDeclaration).source); }, // export {foo} from 'module' - ExportNamedDeclaration: (node: any) => { - _checkImport((node).source); + ExportNamedDeclaration: (node: ESTree.ExportNamedDeclaration) => { + _checkImport((node as TSESTree.ExportNamedDeclaration).source); }, }; diff --git a/.eslint-plugin-local/vscode-dts-cancellation.ts b/.eslint-plugin-local/vscode-dts-cancellation.ts index 5e8e875af21..dd5ca293727 100644 --- a/.eslint-plugin-local/vscode-dts-cancellation.ts +++ b/.eslint-plugin-local/vscode-dts-cancellation.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as eslint from 'eslint'; import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/utils'; +import * as eslint from 'eslint'; -export = new class ApiProviderNaming implements eslint.Rule.RuleModule { +export default new class ApiProviderNaming implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -18,10 +18,10 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature[key.name=/^(provide|resolve).+/]']: (node: any) => { + ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature[key.name=/^(provide|resolve).+/]']: (node: TSESTree.Node) => { let found = false; - for (const param of (node).params) { + for (const param of (node as TSESTree.TSMethodSignature).params) { if (param.type === AST_NODE_TYPES.Identifier) { found = found || param.name === 'token'; } diff --git a/.eslint-plugin-local/vscode-dts-create-func.ts b/.eslint-plugin-local/vscode-dts-create-func.ts index 01db244ce76..91589f91584 100644 --- a/.eslint-plugin-local/vscode-dts-create-func.ts +++ b/.eslint-plugin-local/vscode-dts-create-func.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils'; -export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { +export default new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' }, @@ -17,9 +18,9 @@ export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSDeclareFunction Identifier[name=/create.*/]']: (node: any) => { + ['TSDeclareFunction Identifier[name=/create.*/]']: (node: ESTree.Node) => { - const decl = (node).parent; + const decl = (node as TSESTree.Identifier).parent as TSESTree.FunctionDeclaration; if (decl.returnType?.typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) { return; diff --git a/.eslint-plugin-local/vscode-dts-event-naming.ts b/.eslint-plugin-local/vscode-dts-event-naming.ts index c27d934f4f9..6f75c50ca12 100644 --- a/.eslint-plugin-local/vscode-dts-event-naming.ts +++ b/.eslint-plugin-local/vscode-dts-event-naming.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/utils'; -export = new class ApiEventNaming implements eslint.Rule.RuleModule { +export default new class ApiEventNaming implements eslint.Rule.RuleModule { private static _nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/; @@ -25,14 +26,14 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - const config = <{ allowed: string[]; verbs: string[] }>context.options[0]; + const config = context.options[0] as { allowed: string[]; verbs: string[] }; const allowed = new Set(config.allowed); const verbs = new Set(config.verbs); return { - ['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node: any) => { + ['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node: ESTree.Identifier) => { - const def = (node).parent?.parent?.parent; + const def = (node as TSESTree.Identifier).parent?.parent?.parent; const ident = this.getIdent(def); if (!ident) { diff --git a/.eslint-plugin-local/vscode-dts-interface-naming.ts b/.eslint-plugin-local/vscode-dts-interface-naming.ts index 6b33f9c5343..d6591b97d8d 100644 --- a/.eslint-plugin-local/vscode-dts-interface-naming.ts +++ b/.eslint-plugin-local/vscode-dts-interface-naming.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; -export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule { +export default new class ApiInterfaceNaming implements eslint.Rule.RuleModule { private static _nameRegExp = /^I[A-Z]/; @@ -20,9 +21,9 @@ export = new class ApiInterfaceNaming implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSInterfaceDeclaration Identifier']: (node: any) => { + ['TSInterfaceDeclaration Identifier']: (node: ESTree.Identifier) => { - const name = (node).name; + const name = (node as TSESTree.Identifier).name; if (ApiInterfaceNaming._nameRegExp.test(name)) { context.report({ node, diff --git a/.eslint-plugin-local/vscode-dts-literal-or-types.ts b/.eslint-plugin-local/vscode-dts-literal-or-types.ts index 44ef0fd2a7c..0815720cf92 100644 --- a/.eslint-plugin-local/vscode-dts-literal-or-types.ts +++ b/.eslint-plugin-local/vscode-dts-literal-or-types.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; +import * as eslint from 'eslint'; -export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { +export default new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' }, @@ -16,8 +16,8 @@ export = new class ApiLiteralOrTypes implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSTypeAnnotation TSUnionType']: (node: any) => { - if ((node).types.every(value => value.type === 'TSLiteralType')) { + ['TSTypeAnnotation TSUnionType']: (node: TSESTree.TSUnionType) => { + if (node.types.every(value => value.type === 'TSLiteralType')) { context.report({ node: node, messageId: 'useEnum' diff --git a/.eslint-plugin-local/vscode-dts-provider-naming.ts b/.eslint-plugin-local/vscode-dts-provider-naming.ts index 90409bfe058..64e0101a71e 100644 --- a/.eslint-plugin-local/vscode-dts-provider-naming.ts +++ b/.eslint-plugin-local/vscode-dts-provider-naming.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as eslint from 'eslint'; import { TSESTree } from '@typescript-eslint/utils'; +import * as eslint from 'eslint'; -export = new class ApiProviderNaming implements eslint.Rule.RuleModule { +export default new class ApiProviderNaming implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -19,18 +19,18 @@ export = new class ApiProviderNaming implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { - const config = <{ allowed: string[] }>context.options[0]; + const config = context.options[0] as { allowed: string[] }; const allowed = new Set(config.allowed); return { - ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node: any) => { - const interfaceName = ((node).parent?.parent).id.name; + ['TSInterfaceDeclaration[id.name=/.+Provider/] TSMethodSignature']: (node: TSESTree.Node) => { + const interfaceName = ((node as TSESTree.Identifier).parent?.parent as TSESTree.TSInterfaceDeclaration).id.name; if (allowed.has(interfaceName)) { // allowed return; } - const methodName = ((node).key as TSESTree.Identifier).name; + const methodName = ((node as TSESTree.TSMethodSignatureNonComputedName).key as TSESTree.Identifier).name; if (!ApiProviderNaming._providerFunctionNames.test(methodName)) { context.report({ diff --git a/.eslint-plugin-local/vscode-dts-string-type-literals.ts b/.eslint-plugin-local/vscode-dts-string-type-literals.ts index 0f6d711a3db..ee70d663281 100644 --- a/.eslint-plugin-local/vscode-dts-string-type-literals.ts +++ b/.eslint-plugin-local/vscode-dts-string-type-literals.ts @@ -4,9 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; import { TSESTree } from '@typescript-eslint/utils'; -export = new class ApiTypeDiscrimination implements eslint.Rule.RuleModule { +export default new class ApiTypeDiscrimination implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines' }, @@ -18,8 +19,8 @@ export = new class ApiTypeDiscrimination implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSPropertySignature[optional=false] TSTypeAnnotation TSLiteralType Literal']: (node: any) => { - const raw = String((node).raw); + ['TSPropertySignature[optional=false] TSTypeAnnotation TSLiteralType Literal']: (node: ESTree.Literal) => { + const raw = String((node as TSESTree.Literal).raw); if (/^('|").*\1$/.test(raw)) { diff --git a/.eslint-plugin-local/vscode-dts-use-export.ts b/.eslint-plugin-local/vscode-dts-use-export.ts index 904feaeec36..798572d4f21 100644 --- a/.eslint-plugin-local/vscode-dts-use-export.ts +++ b/.eslint-plugin-local/vscode-dts-use-export.ts @@ -5,8 +5,9 @@ import { TSESTree } from '@typescript-eslint/utils'; import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class VscodeDtsUseExport implements eslint.Rule.RuleModule { +export default new class VscodeDtsUseExport implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -17,8 +18,8 @@ export = new class VscodeDtsUseExport implements eslint.Rule.RuleModule { create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener { return { - ['TSModuleDeclaration :matches(TSInterfaceDeclaration, ClassDeclaration, VariableDeclaration, TSEnumDeclaration, TSTypeAliasDeclaration)']: (node: any) => { - const parent = (node).parent; + ['TSModuleDeclaration :matches(TSInterfaceDeclaration, ClassDeclaration, VariableDeclaration, TSEnumDeclaration, TSTypeAliasDeclaration)']: (node: ESTree.Node) => { + const parent = (node as TSESTree.Node).parent; if (parent && parent.type !== TSESTree.AST_NODE_TYPES.ExportNamedDeclaration) { context.report({ node, diff --git a/.eslint-plugin-local/vscode-dts-use-thenable.ts b/.eslint-plugin-local/vscode-dts-use-thenable.ts index 683394ad115..2c1ff4c9296 100644 --- a/.eslint-plugin-local/vscode-dts-use-thenable.ts +++ b/.eslint-plugin-local/vscode-dts-use-thenable.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class ApiEventNaming implements eslint.Rule.RuleModule { +export default new class ApiEventNaming implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -19,7 +20,7 @@ export = new class ApiEventNaming implements eslint.Rule.RuleModule { return { - ['TSTypeAnnotation TSTypeReference Identifier[name="Promise"]']: (node: any) => { + ['TSTypeAnnotation TSTypeReference Identifier[name="Promise"]']: (node: ESTree.Identifier) => { context.report({ node, diff --git a/.eslint-plugin-local/vscode-dts-vscode-in-comments.ts b/.eslint-plugin-local/vscode-dts-vscode-in-comments.ts index 33fd44d8af6..ab3c338096c 100644 --- a/.eslint-plugin-local/vscode-dts-vscode-in-comments.ts +++ b/.eslint-plugin-local/vscode-dts-vscode-in-comments.ts @@ -4,8 +4,9 @@ *--------------------------------------------------------------------------------------------*/ import * as eslint from 'eslint'; +import type * as ESTree from 'estree'; -export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule { +export default new class ApiVsCodeInComments implements eslint.Rule.RuleModule { readonly meta: eslint.Rule.RuleMetaData = { messages: { @@ -19,7 +20,7 @@ export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule { const sourceCode = context.getSourceCode(); return { - ['Program']: (_node: any) => { + ['Program']: (_node: ESTree.Program) => { for (const comment of sourceCode.getAllComments()) { if (comment.type !== 'Block') { diff --git a/.github/CODENOTIFY b/.github/CODENOTIFY index 21889363f06..ae6288844a3 100644 --- a/.github/CODENOTIFY +++ b/.github/CODENOTIFY @@ -5,6 +5,7 @@ src/vs/base/common/glob.ts @bpasero src/vs/base/common/oauth.ts @TylerLeonhardt src/vs/base/common/path.ts @bpasero src/vs/base/common/stream.ts @bpasero +src/vs/base/common/uri.ts @jrieken src/vs/base/browser/domSanitize.ts @mjbvz src/vs/base/browser/** @bpasero src/vs/base/node/pfs.ts @bpasero @@ -40,11 +41,20 @@ src/vs/platform/secrets/** @TylerLeonhardt src/vs/platform/sharedProcess/** @bpasero src/vs/platform/state/** @bpasero src/vs/platform/storage/** @bpasero +src/vs/platform/terminal/electron-main/** @Tyriar +src/vs/platform/terminal/node/** @Tyriar src/vs/platform/utilityProcess/** @bpasero src/vs/platform/window/** @bpasero src/vs/platform/windows/** @bpasero src/vs/platform/workspace/** @bpasero src/vs/platform/workspaces/** @bpasero +src/vs/platform/actions/common/menuService.ts @jrieken +src/vs/platform/instantiation/** @jrieken + +# Editor Core +src/vs/editor/contrib/snippet/** @jrieken +src/vs/editor/contrib/suggest/** @jrieken +src/vs/editor/contrib/format/** @jrieken # Bootstrap src/bootstrap-cli.ts @bpasero @@ -70,6 +80,7 @@ src/vs/workbench/services/chat/** @bpasero src/vs/workbench/services/contextmenu/** @bpasero src/vs/workbench/services/dialogs/** @alexr00 @bpasero src/vs/workbench/services/editor/** @bpasero +src/vs/workbench/services/editor/common/customEditorLabelService.ts @benibenj src/vs/workbench/services/environment/** @bpasero src/vs/workbench/services/files/** @bpasero src/vs/workbench/services/filesConfiguration/** @bpasero @@ -102,12 +113,23 @@ src/vs/workbench/contrib/files/** @bpasero src/vs/workbench/contrib/chat/browser/chatListRenderer.ts @roblourens src/vs/workbench/contrib/chat/browser/chatSetup.ts @bpasero src/vs/workbench/contrib/chat/browser/chatStatus.ts @bpasero +src/vs/workbench/contrib/chat/browser/chatInputPart.ts @bpasero +src/vs/workbench/contrib/chat/browser/chatWidget.ts @bpasero +src/vs/workbench/contrib/chat/browser/chatManagement/chatUsageWidget.ts @bpasero +src/vs/workbench/contrib/chat/browser/chatManagement/media/chatUsageWidget.css @bpasero +src/vs/workbench/contrib/chat/browser/agentSessions/** @bpasero +src/vs/workbench/contrib/chat/browser/chatSessions/** @bpasero src/vs/workbench/contrib/localization/** @TylerLeonhardt src/vs/workbench/contrib/quickaccess/browser/commandsQuickAccess.ts @TylerLeonhardt +src/vs/workbench/contrib/scm/** @lszomoru src/vs/workbench/contrib/update/browser/releaseNotesEditor.ts @alexr00 @joaomoreno +src/vs/workbench/contrib/preferences/** @rzhao271 # Build +build/azure-pipelines/** @lszomoru build/lib/i18n.ts @TylerLeonhardt +resources/linux/debian/** @rzhao271 +resources/linux/rpm/** @rzhao271 # Editor contrib src/vs/editor/standalone/browser/quickInput/** @TylerLeonhardt @@ -125,3 +147,10 @@ src/vs/workbench/api/browser/mainThreadSecretState.ts @TylerLeonhardt # Extensions extensions/microsoft-authentication/** @TylerLeonhardt extensions/github-authentication/** @TylerLeonhardt +extensions/git/** @lszomoru +extensions/git-base/** @lszomoru +extensions/github/** @lszomoru + +# Chat Editing, Inline Chat +src/vs/workbench/contrib/chat/browser/chatEditing/** @jrieken +src/vs/workbench/contrib/inlineChat/** @jrieken diff --git a/.github/agents/demonstrate.md b/.github/agents/demonstrate.md new file mode 100644 index 00000000000..1a59be8b211 --- /dev/null +++ b/.github/agents/demonstrate.md @@ -0,0 +1,109 @@ +--- +name: Demonstrate +description: Agent for demonstrating VS Code features +target: github-copilot +tools: ['edit', 'search', 'vscode-playwright-mcp/*', 'github/github-mcp-server/*', 'usages', 'fetch', 'githubRepo', 'todos'] +--- + +# Role and Objective + +You are a QA testing agent. Your task is to explore and demonstrate the UI changes introduced in the current PR branch using vscode-playwright-mcp tools. Your interactions will be recorded and attached to the PR to showcase the changes visually. + +# Core Requirements + +## Setup Phase + +1. Use GitHub MCP tools to get PR details (description, linked issues, comments) +2. Search the `microsoft/vscode-docs` repository for relevant documentation about the feature area +3. Examine changed files and commit messages to understand the scope +4. Identify what UI features or behaviors were modified +5. Start VS Code automation using `vscode_automation_start` +6. ALWAYS start by setting the setting `"chat.allowAnonymousAccess":true` using the `vscode_automation_settings_add_user_settings` tool. This will ensure that Chat works without requiring sign-in. + +## Testing Phase + +1. Use `browser_snapshot` to capture the current state +2. Execute the user workflows affected by the PR changes + +## Demonstration Goals + +- Show the new or modified UI in action +- Exercise the changed code paths through realistic user interactions +- Capture clear visual evidence of the improvements or changes +- Test edge cases or variations if applicable + +# Important Guidelines + +- Focus on DEMONSTRATING the changes, not verifying correctness +- You are NOT writing playwright tests - use the tools interactively to explore +- If the PR description or commits mention specific scenarios, prioritize testing those +- Make multiple passes if needed to capture different aspects of the changes +- You may make temporary modifications to facilitate better demonstration (e.g., adjusting settings, opening specific views) + +## GitHub MCP Tools + +**Prefer using GitHub MCP tools over `gh` CLI commands** - these provide structured data and better integration: + +### Pull Request Tools +- `pull_request_read` - Get PR details, diff, status, files, reviews, and comments + - Use `method="get"` for PR metadata (title, description, labels, etc.) + - Use `method="get_diff"` for the full diff + - Use `method="get_files"` for list of changed files + - Use `method="get_reviews"` for review summaries + - Use `method="get_review_comments"` for line-specific review comments +- `search_pull_requests` - Search PRs with filters (author, state, etc.) + +### Issue Tools +- `get_issue` - Get full issue details (description, labels, assignees, etc.) +- `get_issue_comments` - Get all comments on an issue +- `search_issues` - Search issues with filters +- `list_sub_issues` - Get sub-issues if using issue hierarchies + +## Pointers for Controlling VS Code + +- **Prefer `vscode_automation_*` tools over `browser_*` tools** when available - these are designed specifically for VS Code interactions and provide more reliable control. For example: + - `vscode_automation_chat_send_message` over using `browser_*` tools to send chat messages + - `vscode_automation_editor_type_text` over using `browser_*` tools to type in editors + +If you are typing into a monaco input and you can't use the standard methods, follow this sequence: + +**Monaco editors (used throughout VS Code) DO NOT work with standard Playwright methods like `.click()` on textareas or `.fill()` / `.type()`** + +**YOU MUST follow this exact sequence:** + +1. **Take a page snapshot** to identify the editor structure in the accessibility tree +2. **Find the parent `code` role element** that wraps the Monaco editor + - ❌ DO NOT click on `textarea` or `textbox` elements - these are overlaid by Monaco's rendering + - ✅ DO click on the `code` role element that is the parent container +3. **Click on the `code` element** to focus the editor - this properly delegates focus to Monaco's internal text handling +4. **Verify focus** by checking that the nested textbox element has the `[active]` attribute in a new snapshot +5. **Use `page.keyboard.press()` for EACH character individually** - standard Playwright `type()` or `fill()` methods don't work with Monaco editors since they intercept keyboard events at the page level + +**Example:** +```js +// ❌ WRONG - this will fail with timeout +await page.locator('textarea').click(); +await page.locator('textarea').fill('text'); + +// ✅ CORRECT +await page.locator('[role="code"]').click(); +await page.keyboard.press('t'); +await page.keyboard.press('e'); +await page.keyboard.press('x'); +await page.keyboard.press('t'); +``` + +**Why this is required:** Monaco editors intercept keyboard events at the page level and use a virtualized rendering system. Clicking textareas directly or using `.fill()` bypasses Monaco's event handling, causing timeouts and failures. + +# Workflow Pattern + +1. Gather context: + - Retrieve PR details using GitHub MCP (description, linked issues, review comments) + - Search microsoft/vscode-docs for documentation on the affected feature areas + - Examine changed files and commit messages +2. Plan which user interactions will best showcase the changes +3. Start automation and navigate to the relevant area +4. Perform the interactions +5. Document what you're demonstrating as you go +6. Ensure the recording clearly shows the before/after or new functionality +7. **ALWAYS stop the automation** by calling `vscode_automation_stop` - this is REQUIRED whether you successfully demonstrated the feature or encountered issues that prevented testing diff --git a/.github/chatmodes/Plan.chatmode.md b/.github/chatmodes/Plan.chatmode.md deleted file mode 100644 index 552daed6373..00000000000 --- a/.github/chatmodes/Plan.chatmode.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -description: Research and draft an implementation plan -tools: ['executePrompt', 'usages', 'problems', 'githubRepo', 'github.vscode-pull-request-github/activePullRequest', 'search', 'github/github-mcp-server/get_issue', 'github/github-mcp-server/get_issue_comments', 'github/github-mcp-server/get_issue', 'github/github-mcp-server/get_issue_comments', 'fetch'] ---- -You are pairing with the user to create a clear, detailed, and actionable plan for the given task, iterating through a of gathering context and drafting the plan for review. - - -Comprehensive context gathering for planning following : -1. Context gathering and research: - - MUST run `execute_prompt` tool: Instruct the agent to work autonomously without pausing for user feedback, following to gather context and writing a complete to return to you. - - If `execute_prompt` tool is NOT available: Run via tools yourself. -2. Present the plan to the user for feedback and refinement: - - Highlights key areas of ambiguity with specific questions and suggestions. - - MANDATORY: Pause for user feedback! - - Handle feedback: Refine the plan after doing further context gathering and research. - - - -Comprehensive information gathering using read-only tools: -- Examine existing codebase structure, architecture, documentation, and dependencies -- Start with high-level code searches before reading specific files -- Prioritize parallel tool calls for efficiency -- Analyze gaps between current state and desired outcome -- Assess potential integration points and conflicts - - - -- Style: - - Clear, concise, non-repetitive, and high-signal; optimized for quick human review - - Rich in references to specific/related files, symbols, and documentation; while avoiding excessive code snippets - - Tailored to the task and context: Higher complexity requires more detail, higher ambiguity more alternative approaches, etc. -- Briefly summarize problem understanding and proposed technical approach -- Implementation plan broken down into clear, iterative steps as ordered markdown list -- Call out any steps that are too vague or ambiguous to act on - diff --git a/.github/classifier.json b/.github/classifier.json index 0e95e0ed13a..1ca855d5074 100644 --- a/.github/classifier.json +++ b/.github/classifier.json @@ -17,6 +17,7 @@ "breadcrumbs": {"assign": ["jrieken"]}, "callhierarchy": {"assign": ["jrieken"]}, "chat-terminal": {"assign": ["Tyriar"]}, + "chat-terminal-output-monitor": {"assign": ["meganrogge"]}, "chrome-devtools": {"assign": ["deepak1556"]}, "cloud-changes": {"assign": ["joyceerhl"]}, "code-cli": {"assign": ["connor4312"]}, @@ -112,7 +113,7 @@ "interactive-window": {"assign": ["amunger", "rebornix"]}, "ipc": {"assign": ["joaomoreno"]}, "issue-bot": {"assign": ["chrmarti"]}, - "issue-reporter": {"assign": ["justschen"]}, + "issue-reporter": {"assign": ["yoyokrazy"]}, "javascript": {"assign": ["mjbvz"]}, "json": {"assign": ["aeschli"]}, "json-sorting": {"assign": ["aiday-mar"]}, @@ -223,33 +224,34 @@ "terminal": {"assign": ["meganrogge"]}, "terminal-accessibility": {"assign": ["meganrogge"]}, "terminal-conpty": {"assign": ["meganrogge"]}, - "terminal-editors": {"assign": ["Tyriar", "meganrogge"]}, + "terminal-editors": {"assign": ["meganrogge"]}, + "terminal-env-collection": {"assign": ["anthonykim1"]}, "terminal-external": {"assign": ["anthonykim1"]}, "terminal-find": {"assign": ["anthonykim1"]}, "terminal-inline-chat": {"assign": ["Tyriar", "meganrogge"]}, - "terminal-input": {"assign": ["Tyriar", "meganrogge"]}, + "terminal-input": {"assign": ["Tyriar"]}, "terminal-layout": {"assign": ["anthonykim1"]}, "terminal-ligatures": {"assign": ["Tyriar"]}, "terminal-links": {"assign": ["anthonykim1"]}, "terminal-local-echo": {"assign": ["anthonykim1"]}, "terminal-parser": {"assign": ["Tyriar"]}, - "terminal-persistence": {"assign": ["Tyriar", "meganrogge"]}, - "terminal-process": {"assign": ["Tyriar", "meganrogge"]}, + "terminal-persistence": {"assign": ["Tyriar"]}, + "terminal-process": {"assign": ["anthonykim1"]}, "terminal-profiles": {"assign": ["meganrogge"]}, "terminal-quick-fix": {"assign": ["meganrogge"]}, "terminal-rendering": {"assign": ["Tyriar"]}, - "terminal-search": {"assign": ["Tyriar", "meganrogge"]}, "terminal-shell-bash": {"assign": ["anthonykim1"]}, "terminal-shell-cmd": {"assign": ["anthonykim1"]}, "terminal-shell-fish": {"assign": ["anthonykim1"]}, "terminal-shell-git-bash": {"assign": ["anthonykim1"]}, "terminal-shell-integration": {"assign": ["anthonykim1"]}, - "terminal-shell-sh": {"assign": ["anthonykim1"]}, "terminal-shell-pwsh": {"assign": ["anthonykim1"]}, + "terminal-shell-sh": {"assign": ["anthonykim1"]}, "terminal-shell-zsh": {"assign": ["anthonykim1"]}, "terminal-sticky-scroll": {"assign": ["anthonykim1"]}, + "terminal-suggest": {"assign": ["meganrogge"]}, "terminal-tabs": {"assign": ["meganrogge"]}, - "terminal-winpty": {"assign": ["Tyriar", "meganrogge"]}, + "terminal-winpty": {"assign": ["anthonykim1"]}, "testing": {"assign": ["connor4312"]}, "themes": {"assign": ["aeschli"]}, "timeline": {"assign": ["lramos15"]}, diff --git a/.github/commands.json b/.github/commands.json index 374010f98ee..29288f1309b 100644 --- a/.github/commands.json +++ b/.github/commands.json @@ -632,8 +632,9 @@ "removeLabel": "~capi", "assign": [ "samvantran", - "thispaul" - ] + "sharonlo" + ], + "comment": "Thank you for creating this issue! Please provide one or more `requestIds` to help the platform team investigate. You can follow instructions [found here](https://github.com/microsoft/vscode/wiki/Copilot-Issues#language-model-requests-and-responses) to locate the `requestId` value.\n\nHappy Coding!" }, { "type": "label", @@ -653,5 +654,21 @@ ], "action": "updateLabels", "addLabel": "*edu" + }, + { + "type": "label", + "name": "~agent-behavior", + "action": "close", + "reason": "not_planned", + "addLabel": "agent-behavior", + "removeLabel": "~agent-behavior", + "comment": "Unfortunately I think you are hitting a AI quality issue that is not actionable enough for us to track a bug. We would recommend that you try other available models and look at the [Tips and tricks for Copilot in VS Code](https://code.visualstudio.com/docs/copilot/copilot-tips-and-tricks) doc page.\n\nWe are constantly improving AI quality in every release, thank you for the feedback! If you believe this is a technical bug, we recommend you report a new issue including logs described on the [Copilot Issues](https://github.com/microsoft/vscode/wiki/Copilot-Issues) wiki page." + }, + { + "type": "label", + "name": "~accessibility-sla", + "addLabel": "accessibility-sla", + "removeLabel": "~accessibility-sla", + "comment": "The Visual Studio and VS Code teams have an agreement with the Accessibility team that 3:1 contrast is enough for inside the editor." } ] diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 29bac72ad52..24500c211f2 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -48,12 +48,10 @@ Each extension follows the standard VS Code extension structure with `package.js ## Validating TypeScript changes -You MUST check compilation output before running ANY script or declaring work complete! +MANDATORY: Always check the `VS Code - Build` watch task output via #runTasks/getTaskOutput for compilation errors before running ANY script or declaring work complete, then fix all compilation errors before moving forward. -1. **ALWAYS** check the `VS Code - Build` watch task output for compilation errors -2. **NEVER** run tests if there are compilation errors -3. **NEVER** use `npm run compile` to compile TypeScript files, always check task output -4. **FIX** all compilation errors before moving forward +- NEVER run tests if there are compilation errors +- NEVER use `npm run compile` to compile TypeScript files but call #runTasks/getTaskOutput instead ### TypeScript compilation steps - Monitor the `VS Code - Build` task outputs for real-time compilation errors as you make changes @@ -134,3 +132,5 @@ function f(x: number, y: string): void { } - Use `describe` and `test` consistently with existing patterns - If you create any temporary new files, scripts, or helper files for iteration, clean up these files by removing them at the end of the task - Do not use `any` or `unknown` as the type for variables, parameters, or return values unless absolutely necessary. If they need type annotations, they should have proper types or interfaces defined. +- Never duplicate imports. Always reuse existing imports if they are present. +- Prefer regex capture groups with names over numbered capture groups. diff --git a/.github/prompts/build-champ.prompt.md b/.github/prompts/build-champ.prompt.md new file mode 100644 index 00000000000..58d22ecc41d --- /dev/null +++ b/.github/prompts/build-champ.prompt.md @@ -0,0 +1,50 @@ +--- +agent: agent +tools: ['github/github-mcp-server/*', 'microsoft/azure-devops-mcp/*', 'todos'] +--- +# Role +You are the build champion for the VS Code team. Your task is to triage a {{build}} by following these steps: + +# Instructions +1. Display the warning message written below. +2. Investigate the failing jobs of a given {{build}}. + - **Prioritize investigating failing unit test steps first** - these often reveal the root cause of failures +3. Find the most recent {{successful-build}} prior to the failed {{build}}, then identify the {{first-failing-build}} after the {{successful-build}}. Note the commit ids of {{successful-build}} and {{first-failing-build}}. + - Ensure the branch is the same for all builds involved. +4. Using the commit id between the two builds, identify all PRs that were merged in that range. +5. For each PR, analyze the changes to determine if they could have caused the failure. +6. Draft a minimal, succinct, inline-linked message including: + - Build URL + - Failing job URL + - Raw log URL + - GitHub compare view URL in the format: "GitHub Compare View ..." + - List of possible root cause PRs. Ensure the PR numbers are linked to the actual PRs. +7. If no PRs seem to be the cause, suggest rerunning the failed tests and filing an issue on GitHub if the problem persists. + +# Variables +- {{build}}: Provided by the user. If the build is provided as a github url, decode the build URL from it. +- {{successful-build}}: The most recent successful build prior to the failed {{build}}. +- {{first-failing-build}}: The first failing build after the {{successful-build}}. + +## Guidelines +- Include links to relevant PRs, commits, and builds in your output. +- For now, ignore Component Governance Warnings +- Be minimal in your output, focusing on clarity and conciseness. + +## Warning Message + +**⚠️ Known Issues with Build Champion Agent ⚠️** +This agent should be used in parallel while investigating build failures, as it has some known issues: +1. **Double check the error discovered by the agent:** The agent often confuses missing `.build/logs` as an infrastructure issue. This is incorrect, as the missing logs are typically caused by test or build failures. +2. **Pay attention to the build numbers discovered by the agent:** The agent sometimes incorrectly finds the previous successful build. +3. **Double check the list of PRs:** The agent sometimes fails to list all PRs merged between builds. Use the github compare link provided. + +**Please update this prompt file as you discover ways it can be improved.** + +--- + + +## Known Scenarios + +### Expired Approval Step +If a build appears to have an elapsed time of 30 days, this indicates this build was meant to be a release build, but no one approved the release. There is no action needed in this scenario. diff --git a/.github/prompts/codenotify.prompt.md b/.github/prompts/codenotify.prompt.md index 15f679fc1b1..23b42157397 100644 --- a/.github/prompts/codenotify.prompt.md +++ b/.github/prompts/codenotify.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent tools: ['edit', 'search', 'runCommands', 'fetch', 'todos'] --- diff --git a/.github/prompts/component.prompt.md b/.github/prompts/component.prompt.md index 9aa2eb6d176..5297e2b6ad4 100644 --- a/.github/prompts/component.prompt.md +++ b/.github/prompts/component.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent description: 'Help author a component specification for an agent.' tools: ['edit', 'search', 'usages', 'vscodeAPI', 'fetch', 'extensions', 'todos'] --- diff --git a/.github/prompts/data.prompt.md b/.github/prompts/data.prompt.md index a0956fb7d1d..4185ebb4141 100644 --- a/.github/prompts/data.prompt.md +++ b/.github/prompts/data.prompt.md @@ -1,7 +1,7 @@ --- -mode: agent +agent: agent description: 'Answer telemetry questions with data queries' -tools: ['runInTerminal', 'search', 'extensions', 'githubRepo', 'todos', 'kusto_query'] +tools: ['search', 'runCommands/runInTerminal', 'Azure MCP/kusto_query', 'githubRepo', 'extensions', 'todos'] --- diff --git a/.github/prompts/doc-comments.prompt.md b/.github/prompts/doc-comments.prompt.md new file mode 100644 index 00000000000..b3848435901 --- /dev/null +++ b/.github/prompts/doc-comments.prompt.md @@ -0,0 +1,30 @@ +--- +agent: agent +description: 'Update doc comments' +tools: ['edit', 'search', 'new', 'runCommands', 'runTasks', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'openSimpleBrowser', 'fetch', 'githubRepo', 'extensions', 'todos', 'runTests'] +--- +# Role + +You are an expert technical documentation editor specializing in public API documentation. + +## Instructions + +Review user's request and update code documentation comments in appropriate locations. + +## Guidelines + +- **Important** Do not, under any circumstances, change any of the public API naming or signatures. +- **Important** Fetch and review relevant code context (i.e. implementation source code) before making changes or adding comments. +- **Important** Do not use 'VS Code', 'Visual Studio Code' or similar product term anywhere in the comments (this causes lint errors). +- Follow American English grammar, orthography, and punctuation. +- Summary and description comments must use sentences if possible and end with a period. +- Use {@link \} where possible **and reasonable** to refer to code symbols. +- If a @link uses a custom label, keep it - for example: {@link Uri address} - do not remove the 'address' label. +- Use `code` formatting for code elements and keywords in comments, for example: `undefined`. +- Limit the maximum line length of comments to 120 characters. + +## Cleanup Mode + +If the user instructed you to "clean up" doc comments (e.g. by passing in "cleanup" as their prompt), +it is **very important** that you limit your changes to only fixing grammar, punctuation, formatting, and spelling mistakes. +**YOU MUST NOT** add new or remove or expand existing comments in cleanup mode. diff --git a/.github/prompts/find-issue.prompt.md b/.github/prompts/find-issue.prompt.md new file mode 100644 index 00000000000..acdd3908d84 --- /dev/null +++ b/.github/prompts/find-issue.prompt.md @@ -0,0 +1,100 @@ +--- +agent: agent +tools: ['github/github-mcp-server/issue_read', 'github/github-mcp-server/list_issues', 'github/github-mcp-server/search_issues', 'runSubagent'] +model: Claude Sonnet 4.5 (copilot) +description: 'Describe your issue...' +--- + +## Role +You are **FindIssue**, a focused GitHub issue investigator for this repository. +Your job is to locate any existing issues that match the user's natural-language description, while making your search process transparent. + +## Objective +When the user describes a potential bug, crash, or feature request: +1. Search the repository for similar issues using parallel tool calls when possible +2. Display *every search query* attempted for transparency +3. Return the most relevant issues (open or closed) with short summaries +4. If nothing matches, provide a complete new issue template in a dedicated section + +## Context +- Users may not phrase things the same way as existing issues. +- Always prefer **semantic relevance** and **clarity** over keyword quantity. +- Include **open** issues first, but consider **recently closed** ones when relevant. + +## Workflow +1. **Interpret Input** + - Summarize the user's request in 1 line (you may restate it as a possible issue title) + - **Identify the specific context and component** (e.g., "chat window UI" vs "prompt file editor" vs "settings page") + - Derive 2 concise search queries using likely keywords or variations (avoid creating too many queries) + +2. **Search** + - Run a subAgent that uses parallel tool calls of `github/github-mcp-server/search_issues` with `perPage: 5` and `owner: microsoft`. + - If no results, try variations: + * Remove UI-specific modifiers ("right click", "context menu") + * Substitute action verbs (hide→remove, dismiss→close) + * Remove platform/OS qualifiers + +3. **Read & Analyze** + - **First evaluate search results by title, state, and labels only** - often sufficient to determine relevance + - **Only read full issue content** (via `github/github-mcp-server/issue_read`) **for the top 1-2 most promising matches** that you cannot confidently assess from title alone + - **Verify the issue context matches the user's context** - check if the issue is about the same UI component, file type, or workflow step + - Evaluate relevance based on: + * Core concept match (most important) + * Component/context match + * Action/behavior match (user's requested action may differ from issue's proposed solution) + - **If the issue mentions similar features but in a different context, mark it as "related" not "exact match"** + +4. **Display Results** + - **First**, list the searches you performed, for transparency: + ``` + 🔍 Searches performed: + - "DataLoader null pointer Windows" + - "NullReferenceException loader crash" + - "Windows DataLoader crash" + ``` + - **Then**, summarize results in a Markdown table with the following columns: #, Title, State, Relevance, Notes. Use emojis for state (🔓 Open, 🔒 Closed) and relevance (✅ Exact, 🔗 Related). **Important**: Ensure the issue numbers are direct links to the issues. + +5. **Conclude** + - Matching context → recommend most relevant issue + - Different context → explain difference and suggest new issue + - Nothing found → suggest title and keywords for new issue + + +## Style +- Keep explanations short and scannable +- Use Markdown formatting (bullets, tables) +- Go straight to findings—no preamble + + +## Example + +**User:** +> "I get an access violation when I close the app after running the renderer." + +**Assistant:** +🔍 **Searches performed:** +- "renderer crash" (core concepts) +- "renderer exit crash" (core + action) +- "access violation renderer shutdown" (original phrasing) +- "renderer close segmentation fault" (synonym variation) + +Found 2 similar issues: +| # | Title | State | Relevance | Notes | +|---|--------|--------|-----------|-------| +| #201 | Renderer crash on exit | 🔓 Open | ✅ Exact | Matches shutdown sequence and context | +| #178 | App closes unexpectedly after render | 🔒 Closed | 🔗 Related | Similar timing but fixed in v2.3 | + +✅ **You can comment on #201** as it matches your issue. + +--- + +### 📝 Alternative: Suggested New Issue + +**Title:** +Renderer access violation on app exit + +**Description:** +The application crashes with an access violation error when closing after running the renderer. This occurs consistently during the shutdown sequence and prevents clean application termination. + +**Keywords:** +`renderer`, `shutdown`, `access-violation`, `crash` diff --git a/.github/prompts/fixIssueNo.prompt.md b/.github/prompts/fixIssueNo.prompt.md index 6438f4614fe..22130f14047 100644 --- a/.github/prompts/fixIssueNo.prompt.md +++ b/.github/prompts/fixIssueNo.prompt.md @@ -1,6 +1,6 @@ --- -mode: Plan -tools: ['runCommands', 'runTasks', 'runNotebooks', 'search', 'new', 'usages', 'vscodeAPI', 'problems', 'testFailure', 'openSimpleBrowser', 'fetch', 'githubRepo', 'todos', 'runTests', 'get_issue', 'get_issue_comments', 'get_me', 'get_pull_request', 'get_pull_request_diff', 'get_pull_request_files'] +agent: Plan +tools: ['runCommands', 'runTasks', 'runNotebooks', 'search', 'new', 'usages', 'vscodeAPI', 'problems', 'testFailure', 'openSimpleBrowser', 'fetch', 'githubRepo', 'todos', 'runTests', 'github/get_issue', 'github/get_issue_comments', 'github/get_me', 'github/get_pull_request', 'github/get_pull_request_diff', 'github/get_pull_request_files'] --- The user has given you a Github issue number. Use the `get_issue` to retrieve its details. Understand the issue and propose a solution to solve it. diff --git a/.github/prompts/implement.prompt.md b/.github/prompts/implement.prompt.md index 190ff25f9ec..4deb7ba76d7 100644 --- a/.github/prompts/implement.prompt.md +++ b/.github/prompts/implement.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent description: 'Implement the plan' tools: ['edit', 'runNotebooks', 'search', 'new', 'runCommands', 'runTasks', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'openSimpleBrowser', 'fetch', 'githubRepo', 'extensions', 'todos', 'runTests'] --- diff --git a/.github/prompts/no-any.prompt.md b/.github/prompts/no-any.prompt.md index f5a4b595e5c..7e78fefa27e 100644 --- a/.github/prompts/no-any.prompt.md +++ b/.github/prompts/no-any.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent description: 'Remove any usage of the any type in TypeScript files' --- diff --git a/.github/prompts/plan-deep.prompt.md b/.github/prompts/plan-deep.prompt.md index 351a0ebb252..a321fbe2cbb 100644 --- a/.github/prompts/plan-deep.prompt.md +++ b/.github/prompts/plan-deep.prompt.md @@ -1,7 +1,9 @@ --- -mode: Plan +agent: Plan description: Clarify before planning in more detail --- -Before doing your research look up related code (max 5 tool calls!) to get a high-level overview, then ask 3 clarifying questions. Once the user answered, go to *Context gathering and research*. +Before doing your research workflow, gather preliminary context using #runSubagent (instructed to use max 5 tool calls) to get a high-level overview. -Be extra detailed in your planning draft. +Then ask 3 clarifying questions and PAUSE for the user to answer them. + +AFTER the user has answered, start the . Add extra details to your planning draft. diff --git a/.github/prompts/plan-fast.prompt.md b/.github/prompts/plan-fast.prompt.md index a3d320fa04e..2ae8191933a 100644 --- a/.github/prompts/plan-fast.prompt.md +++ b/.github/prompts/plan-fast.prompt.md @@ -1,5 +1,5 @@ --- -mode: Plan +agent: Plan description: Iterate quicker on simple tasks --- Planning for faster iteration: Research as usual, but draft a much more shorter implementation plan that focused on just the main steps diff --git a/.github/prompts/plan.prompt.md b/.github/prompts/plan.prompt.md index bff5fa18743..e94ee7b24eb 100644 --- a/.github/prompts/plan.prompt.md +++ b/.github/prompts/plan.prompt.md @@ -1,19 +1,5 @@ --- -mode: agent +agent: Plan description: 'Start planning' -tools: ['runNotebooks/getNotebookSummary', 'runNotebooks/readNotebookCellOutput', 'search', 'runCommands/getTerminalOutput', 'runCommands/terminalSelection', 'runCommands/terminalLastCommand', 'github/github-mcp-server/get_issue', 'github/github-mcp-server/get_issue_comments', 'github/github-mcp-server/get_me', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'fetch', 'githubRepo', 'todos'] --- -Your goal is to prepare a detailed plan to fix the bug or add the new feature, for this you first need to: -* Understand the context of the bug or feature by reading the issue description and comments. -* Understand the codebase by reading the relevant instruction files. -* If its a bug, then identify the root cause of the bug, and explain this to the user. - -Based on your above understanding generate a plan to fix the bug or add the new feature. -Ensure the plan consists of a Markdown document that has the following sections: - -* Overview: A brief description of the bug/feature. -* Root Cause: A detailed explanation of the root cause of the bug, including any relevant code snippets or references to the codebase. (only if it's a bug) -* Requirements: A list of requirements to resolve the bug or add the new feature. -* Implementation Steps: A detailed list of steps to implement the bug fix or new feature. - -Remember, do not make any code edits, just generate a plan. Use thinking and reasoning skills to outline the steps needed to achieve the desired outcome. +Start planning. diff --git a/.github/prompts/playwright.prompt.md b/.github/prompts/playwright.prompt.md deleted file mode 100644 index 107c91475c0..00000000000 --- a/.github/prompts/playwright.prompt.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -mode: agent -description: 'Use playwright & automation tools to _see_ the code changes you have made' -tools: ['codebase', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'openSimpleBrowser', 'fetch', 'findTestFiles', 'searchResults', 'githubRepo', 'todos', 'runTests', 'editFiles', 'runNotebooks', 'search', 'new', 'runCommands', 'runTasks', 'vscode-playwright-mcp', 'get_commit', 'get_discussion', 'get_discussion_comments', 'get_issue', 'get_issue_comments'] ---- -You are being requested to visually confirm the code changes you are making using vscode-playwright-mcp. - -You MUST run vscode_automation_start & browser_snapshot. -You MUST verify the bad behavior you are investigating using vscode-playwright-mcp. -You MUST verify the code changes you have made using vscode-playwright-mcp. -You MUST take before and after screenshots. -Remember, you are NOT writing playwright tests; instead, focus on using the tools to validate and explore the changes. -You MAY need to make multiple passes, iterating between making code changes and verifying them with the tools. -You MUST reload the window (`Developer: Reload Window` command) after making changes to ensure they are applied correctly. -You MAY make temporary changes to the code to facilitate testing and exploration. For example, using the quick pick in the Configure Display Language action as a scratch pad to add buttons to it. diff --git a/.github/prompts/setup-environment.prompt.md b/.github/prompts/setup-environment.prompt.md index e35870dd477..fa934ad7029 100644 --- a/.github/prompts/setup-environment.prompt.md +++ b/.github/prompts/setup-environment.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent description: First Time Setup tools: ['runCommands', 'runTasks/runTask', 'search', 'todos', 'fetch'] --- diff --git a/.github/prompts/update-instructions.prompt.md b/.github/prompts/update-instructions.prompt.md index 8ba53454822..b38001671ef 100644 --- a/.github/prompts/update-instructions.prompt.md +++ b/.github/prompts/update-instructions.prompt.md @@ -1,5 +1,5 @@ --- -mode: agent +agent: agent --- Read the changes introduced on the current branch, including BOTH: diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index b520069a389..1b0af580378 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc diff --git a/.github/workflows/monaco-editor.yml b/.github/workflows/monaco-editor.yml index cedbd379a3d..b1d462546ac 100644 --- a/.github/workflows/monaco-editor.yml +++ b/.github/workflows/monaco-editor.yml @@ -23,7 +23,7 @@ jobs: with: persist-credentials: false - - uses: actions/setup-node@v5 + - uses: actions/setup-node@v6 with: node-version-file: .nvmrc diff --git a/.github/workflows/pr-darwin-test.yml b/.github/workflows/pr-darwin-test.yml index afcb9cc5bb4..e48140b9569 100644 --- a/.github/workflows/pr-darwin-test.yml +++ b/.github/workflows/pr-darwin-test.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -212,7 +212,7 @@ jobs: if: always() - name: Publish Crash Reports - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -223,7 +223,7 @@ jobs: # In order to properly symbolify above crash reports # (if any), we need the compiled native modules too - name: Publish Node Modules - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -232,7 +232,7 @@ jobs: if-no-files-found: ignore - name: Publish Log Files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() continue-on-error: true with: diff --git a/.github/workflows/pr-linux-test.yml b/.github/workflows/pr-linux-test.yml index ed8ff3a40ba..992be267cf9 100644 --- a/.github/workflows/pr-linux-test.yml +++ b/.github/workflows/pr-linux-test.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -258,7 +258,7 @@ jobs: if: always() - name: Publish Crash Reports - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -269,7 +269,7 @@ jobs: # In order to properly symbolify above crash reports # (if any), we need the compiled native modules too - name: Publish Node Modules - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -278,7 +278,7 @@ jobs: if-no-files-found: ignore - name: Publish Log Files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() continue-on-error: true with: diff --git a/.github/workflows/pr-node-modules.yml b/.github/workflows/pr-node-modules.yml index 65c57f078f9..fc7497aa3f6 100644 --- a/.github/workflows/pr-node-modules.yml +++ b/.github/workflows/pr-node-modules.yml @@ -16,7 +16,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -95,7 +95,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -167,7 +167,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -228,7 +228,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc diff --git a/.github/workflows/pr-win32-test.yml b/.github/workflows/pr-win32-test.yml index 0a1ec3aa45b..ec2baa2f5b9 100644 --- a/.github/workflows/pr-win32-test.yml +++ b/.github/workflows/pr-win32-test.yml @@ -27,7 +27,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -249,7 +249,7 @@ jobs: if: always() - name: Publish Crash Reports - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -260,7 +260,7 @@ jobs: # In order to properly symbolify above crash reports # (if any), we need the compiled native modules too - name: Publish Node Modules - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: failure() continue-on-error: true with: @@ -269,7 +269,7 @@ jobs: if-no-files-found: ignore - name: Publish Log Files - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 if: always() continue-on-error: true with: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 2361aaa31de..07186308186 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -24,7 +24,7 @@ jobs: uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: node-version-file: .nvmrc @@ -80,7 +80,7 @@ jobs: run: .github/workflows/check-clean-git-state.sh - name: Compile & Hygiene - run: npm exec -- npm-run-all -lp core-ci-pr extensions-ci-pr hygiene eslint valid-layers-check define-class-fields-check vscode-dts-compile-check tsec-compile-check + run: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check define-class-fields-check vscode-dts-compile-check tsec-compile-check test-build-scripts env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/telemetry.yml b/.github/workflows/telemetry.yml index 03c3f649d58..cb7d81e551f 100644 --- a/.github/workflows/telemetry.yml +++ b/.github/workflows/telemetry.yml @@ -11,7 +11,7 @@ jobs: with: persist-credentials: false - - uses: 'actions/setup-node@v5' + - uses: 'actions/setup-node@v6' with: node-version: 'lts/*' diff --git a/.npmrc b/.npmrc index 30da46b2d4c..2a3ca865751 100644 --- a/.npmrc +++ b/.npmrc @@ -1,8 +1,7 @@ disturl="https://electronjs.org/headers" -target="37.6.0" -ms_build_id="12506819" +target="39.2.0" +ms_build_id="12791201" runtime="electron" build_from_source="true" legacy-peer-deps="true" timeout=180000 -npm_config_node_gyp="node build/npm/gyp/node_modules/node-gyp/bin/node-gyp.js" diff --git a/.nvmrc b/.nvmrc index e2228113dd0..442c7587a99 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.19.0 +22.20.0 diff --git a/.vscode-test.js b/.vscode-test.js index 2e49c90126b..4c093d0e2b3 100644 --- a/.vscode-test.js +++ b/.vscode-test.js @@ -79,6 +79,10 @@ const extensions = [ workspaceFolder: `extensions/vscode-api-tests/testworkspace.code-workspace`, mocha: { timeout: 60_000 }, files: 'extensions/vscode-api-tests/out/workspace-tests/**/*.test.js', + }, + { + label: 'git-base', + mocha: { timeout: 60_000 } } ]; diff --git a/.vscode/extensions/vscode-selfhost-test-provider/src/extension.ts b/.vscode/extensions/vscode-selfhost-test-provider/src/extension.ts index cbb8d50bf99..2f9ac62abe4 100644 --- a/.vscode/extensions/vscode-selfhost-test-provider/src/extension.ts +++ b/.vscode/extensions/vscode-selfhost-test-provider/src/extension.ts @@ -45,7 +45,7 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.tests.registerTestFollowupProvider({ async provideFollowup(_result, test, taskIndex, messageIndex, _token) { return [{ - title: '$(sparkle) Fix with Copilot', + title: '$(sparkle) Fix', command: 'github.copilot.tests.fixTestFailure', arguments: [{ source: 'peekFollowup', test, message: test.taskStates[taskIndex].messages[messageIndex] }] }]; diff --git a/.vscode/launch.json b/.vscode/launch.json index 216afd8b573..07407e53ab6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -588,11 +588,33 @@ ] }, { - "name": "Monaco Editor Playground", + "name": "Monaco Editor - Playground", "type": "chrome", "request": "launch", - "url": "http://localhost:5001", - "preLaunchTask": "Launch Http Server", + "url": "https://microsoft.github.io/monaco-editor/playground.html?source=http%3A%2F%2Flocalhost%3A5199%2Fbuild%2Fmonaco-editor-playground%2Findex.ts%3Fesm#example-creating-the-editor-hello-world", + "preLaunchTask": "Launch Monaco Editor Vite", + "presentation": { + "group": "monaco", + "order": 4 + } + }, + { + "name": "Monaco Editor - Self Contained Diff Editor", + "type": "chrome", + "request": "launch", + "url": "http://localhost:5199/build/monaco-editor-playground/index.html", + "preLaunchTask": "Launch Monaco Editor Vite", + "presentation": { + "group": "monaco", + "order": 4 + } + }, + { + "name": "Monaco Editor - Workbench", + "type": "chrome", + "request": "launch", + "url": "http://localhost:5199/build/monaco-editor-playground/workbench-vite.html", + "preLaunchTask": "Launch Monaco Editor Vite", "presentation": { "group": "monaco", "order": 4 diff --git a/.vscode/notebooks/api.github-issues b/.vscode/notebooks/api.github-issues index 990ef26421f..d466fa1b04b 100644 --- a/.vscode/notebooks/api.github-issues +++ b/.vscode/notebooks/api.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"September 2025\"" + "value": "$REPO=repo:microsoft/vscode\n$MILESTONE=milestone:\"October 2025\"" }, { "kind": 1, diff --git a/.vscode/notebooks/endgame.github-issues b/.vscode/notebooks/endgame.github-issues index b5b35085ec3..8592ecd44c0 100644 --- a/.vscode/notebooks/endgame.github-issues +++ b/.vscode/notebooks/endgame.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "$MILESTONE=milestone:\"September 2025\"" + "value": "$MILESTONE=milestone:\"October 2025\"" }, { "kind": 1, diff --git a/.vscode/notebooks/my-endgame.github-issues b/.vscode/notebooks/my-endgame.github-issues index 53edd0b40c1..38ff70547c4 100644 --- a/.vscode/notebooks/my-endgame.github-issues +++ b/.vscode/notebooks/my-endgame.github-issues @@ -7,12 +7,12 @@ { "kind": 2, "language": "github-issues", - "value": "$MILESTONE=milestone:\"September 2025\"\n\n$MINE=assignee:@me" + "value": "$MILESTONE=milestone:\"October 2025\"\n\n$MINE=assignee:@me" }, { "kind": 2, "language": "github-issues", - "value": "$NOT_TEAM_MEMBERS=-author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:bamurtaugh -author:bpasero -author:chrmarti -author:Chuxel -author:claudiaregio -author:connor4312 -author:dbaeumer -author:deepak1556 -author:devinvalenciano -author:digitarald -author:DonJayamanne -author:egamma -author:fiveisprime -author:ntrogh -author:hediet -author:isidorn -author:joaomoreno -author:jrieken -author:kieferrm -author:lramos15 -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:rebornix -author:roblourens -author:rzhao271 -author:sandy081 -author:sbatten -author:stevencl -author:TylerLeonhardt -author:Tyriar -author:weinand -author:amunger -author:karthiknadig -author:eleanorjboyd -author:Yoyokrazy -author:ulugbekna -author:aiday-mar -author:bhavyaus -author:justschen -author:benibenj -author:luabud -author:anthonykim1 -author:joshspicer -author:osortega -author:hawkticehurst -author:pierceboggan -author:benvillalobos -author:dileepyavan -author:dineshc-msft -author:dmitrivMS -author:eli-w-king -author:jo-oikawa -author:jruales -author:jytjyt05 -author:kycutler -author:mrleemurray -author:pwang347 -author:vijayupadya -author:bryanchen-d" + "value": "$NOT_TEAM_MEMBERS=-author:aeschli -author:alexdima -author:alexr00 -author:AmandaSilver -author:bamurtaugh -author:bpasero -author:chrmarti -author:Chuxel -author:claudiaregio -author:connor4312 -author:dbaeumer -author:deepak1556 -author:devinvalenciano -author:digitarald -author:DonJayamanne -author:egamma -author:fiveisprime -author:ntrogh -author:hediet -author:isidorn -author:joaomoreno -author:jrieken -author:kieferrm -author:lramos15 -author:lszomoru -author:meganrogge -author:misolori -author:mjbvz -author:rebornix -author:roblourens -author:rzhao271 -author:sandy081 -author:sbatten -author:stevencl -author:TylerLeonhardt -author:Tyriar -author:weinand -author:amunger -author:karthiknadig -author:eleanorjboyd -author:Yoyokrazy -author:ulugbekna -author:aiday-mar -author:bhavyaus -author:justschen -author:benibenj -author:luabud -author:anthonykim1 -author:joshspicer -author:osortega -author:hawkticehurst -author:pierceboggan -author:benvillalobos -author:dileepyavan -author:dineshc-msft -author:dmitrivMS -author:eli-w-king -author:jo-oikawa -author:jruales -author:jytjyt05 -author:kycutler -author:mrleemurray -author:pwang347 -author:vijayupadya -author:bryanchen-d -author:cwebster-99" }, { "kind": 1, diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index c2a10646be8..c56ba69614c 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -7,7 +7,7 @@ { "kind": 2, "language": "github-issues", - "value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n// current milestone name\n$MILESTONE=milestone:\"September 2025\"\n" + "value": "// list of repos we work in\n$REPOS=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n\n// current milestone name\n$MILESTONE=milestone:\"October 2025\"\n" }, { "kind": 1, diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues index 4176ec6e30b..1c7e9dc1843 100644 --- a/.vscode/notebooks/verification.github-issues +++ b/.vscode/notebooks/verification.github-issues @@ -12,7 +12,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n$milestone=milestone:\"September 2025\"\n$closedRecently=closed:>2023-09-29" + "value": "$repos=repo:microsoft/lsprotocol repo:microsoft/monaco-editor repo:microsoft/vscode repo:microsoft/vscode-anycode repo:microsoft/vscode-autopep8 repo:microsoft/vscode-black-formatter repo:microsoft/vscode-copilot repo:microsoft/vscode-copilot-release repo:microsoft/vscode-dev repo:microsoft/vscode-dev-chrome-launcher repo:microsoft/vscode-emmet-helper repo:microsoft/vscode-extension-telemetry repo:microsoft/vscode-flake8 repo:microsoft/vscode-github-issue-notebooks repo:microsoft/vscode-hexeditor repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-isort repo:microsoft/vscode-js-debug repo:microsoft/vscode-jupyter repo:microsoft/vscode-jupyter-internal repo:microsoft/vscode-l10n repo:microsoft/vscode-livepreview repo:microsoft/vscode-markdown-languageservice repo:microsoft/vscode-markdown-tm-grammar repo:microsoft/vscode-mypy repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-pylint repo:microsoft/vscode-python repo:microsoft/vscode-python-debugger repo:microsoft/vscode-python-tools-extension-template repo:microsoft/vscode-references-view repo:microsoft/vscode-remote-release repo:microsoft/vscode-remote-repositories-github repo:microsoft/vscode-remote-tunnels repo:microsoft/vscode-remotehub repo:microsoft/vscode-settings-sync-server repo:microsoft/vscode-unpkg repo:microsoft/vscode-vsce\n$milestone=milestone:\"October 2025\"\n$closedRecently=closed:>2023-09-29" }, { "kind": 1, diff --git a/.vscode/notebooks/vscode-dev.github-issues b/.vscode/notebooks/vscode-dev.github-issues index efa2935ac05..4ba4724804c 100644 --- a/.vscode/notebooks/vscode-dev.github-issues +++ b/.vscode/notebooks/vscode-dev.github-issues @@ -2,7 +2,7 @@ { "kind": 2, "language": "github-issues", - "value": "$milestone=milestone:\"September 2025\"" + "value": "$milestone=milestone:\"October 2025\"" }, { "kind": 1, diff --git a/.vscode/searches/no-any-casts.code-search b/.vscode/searches/no-any-casts.code-search index b6d6fd03c1c..ff6b2a40f13 100644 --- a/.vscode/searches/no-any-casts.code-search +++ b/.vscode/searches/no-any-casts.code-search @@ -1,45 +1,45 @@ # Query: // eslint-disable-next-line local/code-no-any-casts -838 results - 314 files +785 results - 287 files -extensions/css-language-features/client/src/cssClient.ts: +vscode • extensions/css-language-features/client/src/cssClient.ts: 86: // eslint-disable-next-line local/code-no-any-casts -extensions/css-language-features/server/src/cssServer.ts: +vscode • extensions/css-language-features/server/src/cssServer.ts: 71: // eslint-disable-next-line local/code-no-any-casts 74: // eslint-disable-next-line local/code-no-any-casts 171: // eslint-disable-next-line local/code-no-any-casts -extensions/git-base/src/api/api1.ts: +vscode • extensions/git-base/src/api/api1.ts: 17: // eslint-disable-next-line local/code-no-any-casts 38: // eslint-disable-next-line local/code-no-any-casts -extensions/html-language-features/client/src/htmlClient.ts: +vscode • extensions/html-language-features/client/src/htmlClient.ts: 182: // eslint-disable-next-line local/code-no-any-casts -extensions/html-language-features/server/src/htmlServer.ts: +vscode • extensions/html-language-features/server/src/htmlServer.ts: 137: // eslint-disable-next-line local/code-no-any-casts 140: // eslint-disable-next-line local/code-no-any-casts 545: // eslint-disable-next-line local/code-no-any-casts -extensions/ipynb/src/deserializers.ts: +vscode • extensions/ipynb/src/deserializers.ts: 23: // eslint-disable-next-line local/code-no-any-casts 294: // eslint-disable-next-line local/code-no-any-casts -extensions/ipynb/src/helper.ts: +vscode • extensions/ipynb/src/helper.ts: 14: // eslint-disable-next-line local/code-no-any-casts 18: // eslint-disable-next-line local/code-no-any-casts 20: // eslint-disable-next-line local/code-no-any-casts 22: // eslint-disable-next-line local/code-no-any-casts 25: // eslint-disable-next-line local/code-no-any-casts -extensions/ipynb/src/serializers.ts: +vscode • extensions/ipynb/src/serializers.ts: 40: // eslint-disable-next-line local/code-no-any-casts 61: // eslint-disable-next-line local/code-no-any-casts 403: // eslint-disable-next-line local/code-no-any-casts 405: // eslint-disable-next-line local/code-no-any-casts -extensions/ipynb/src/test/notebookModelStoreSync.test.ts: +vscode • extensions/ipynb/src/test/notebookModelStoreSync.test.ts: 40: // eslint-disable-next-line local/code-no-any-casts 79: // eslint-disable-next-line local/code-no-any-casts 109: // eslint-disable-next-line local/code-no-any-casts @@ -55,67 +55,55 @@ extensions/ipynb/src/test/notebookModelStoreSync.test.ts: 424: // eslint-disable-next-line local/code-no-any-casts 459: // eslint-disable-next-line local/code-no-any-casts -extensions/json-language-features/client/src/jsonClient.ts: +vscode • extensions/json-language-features/client/src/jsonClient.ts: 775: // eslint-disable-next-line local/code-no-any-casts -extensions/json-language-features/server/src/jsonServer.ts: +vscode • extensions/json-language-features/server/src/jsonServer.ts: 144: // eslint-disable-next-line local/code-no-any-casts -extensions/markdown-language-features/notebook/index.ts: +vscode • extensions/markdown-language-features/notebook/index.ts: 383: // eslint-disable-next-line local/code-no-any-casts -extensions/markdown-language-features/preview-src/index.ts: +vscode • extensions/markdown-language-features/preview-src/index.ts: 26: // eslint-disable-next-line local/code-no-any-casts 253: // eslint-disable-next-line local/code-no-any-casts 444: // eslint-disable-next-line local/code-no-any-casts -extensions/markdown-language-features/src/markdownEngine.ts: +vscode • extensions/markdown-language-features/src/markdownEngine.ts: 146: // eslint-disable-next-line local/code-no-any-casts -extensions/markdown-language-features/src/languageFeatures/diagnostics.ts: - 53: // eslint-disable-next-line local/code-no-any-casts +vscode • extensions/markdown-language-features/src/languageFeatures/diagnostics.ts: + 54: // eslint-disable-next-line local/code-no-any-casts -extensions/notebook-renderers/src/index.ts: +vscode • extensions/notebook-renderers/src/index.ts: 68: // eslint-disable-next-line local/code-no-any-casts -extensions/notebook-renderers/src/test/notebookRenderer.test.ts: +vscode • extensions/notebook-renderers/src/test/notebookRenderer.test.ts: 130: // eslint-disable-next-line local/code-no-any-casts 137: // eslint-disable-next-line local/code-no-any-casts -extensions/vscode-api-tests/src/extension.ts: +vscode • extensions/vscode-api-tests/src/extension.ts: 10: // eslint-disable-next-line local/code-no-any-casts -extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts: +vscode • extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts: 181: // eslint-disable-next-line local/code-no-any-casts -extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts: +vscode • extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts: 59: // eslint-disable-next-line local/code-no-any-casts 76: // eslint-disable-next-line local/code-no-any-casts -extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts: +vscode • extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts: 16: // eslint-disable-next-line local/code-no-any-casts -extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts: +vscode • extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts: 18: // eslint-disable-next-line local/code-no-any-casts -scripts/playground-server.ts: +vscode • scripts/playground-server.ts: 257: // eslint-disable-next-line local/code-no-any-casts 336: // eslint-disable-next-line local/code-no-any-casts 352: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/browser.ts: - 134: // eslint-disable-next-line local/code-no-any-casts - 141: // eslint-disable-next-line local/code-no-any-casts - -src/vs/base/browser/canIUse.ts: - 36: // eslint-disable-next-line local/code-no-any-casts - -src/vs/base/browser/deviceAccess.ts: - 26: // eslint-disable-next-line local/code-no-any-casts - 63: // eslint-disable-next-line local/code-no-any-casts - 92: // eslint-disable-next-line local/code-no-any-casts - -src/vs/base/browser/dom.ts: +vscode • src/vs/base/browser/dom.ts: 718: // eslint-disable-next-line local/code-no-any-casts 1324: // eslint-disable-next-line local/code-no-any-casts 1519: // eslint-disable-next-line local/code-no-any-casts @@ -130,116 +118,113 @@ src/vs/base/browser/dom.ts: 2443: // eslint-disable-next-line local/code-no-any-casts 2528: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/mouseEvent.ts: +vscode • src/vs/base/browser/mouseEvent.ts: 100: // eslint-disable-next-line local/code-no-any-casts 138: // eslint-disable-next-line local/code-no-any-casts 155: // eslint-disable-next-line local/code-no-any-casts 157: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/trustedTypes.ts: - 19: // eslint-disable-next-line local/code-no-any-casts - 31: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/base/browser/trustedTypes.ts: + 21: // eslint-disable-next-line local/code-no-any-casts + 33: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/webWorkerFactory.ts: +vscode • src/vs/base/browser/webWorkerFactory.ts: 20: // eslint-disable-next-line local/code-no-any-casts 22: // eslint-disable-next-line local/code-no-any-casts 43: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/ui/grid/grid.ts: +vscode • src/vs/base/browser/ui/grid/grid.ts: 66: // eslint-disable-next-line local/code-no-any-casts 873: // eslint-disable-next-line local/code-no-any-casts 875: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/ui/grid/gridview.ts: +vscode • src/vs/base/browser/ui/grid/gridview.ts: 196: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/browser/ui/sash/sash.ts: +vscode • src/vs/base/browser/ui/sash/sash.ts: 491: // eslint-disable-next-line local/code-no-any-casts 497: // eslint-disable-next-line local/code-no-any-casts 503: // eslint-disable-next-line local/code-no-any-casts 505: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/console.ts: +vscode • src/vs/base/common/console.ts: 134: // eslint-disable-next-line local/code-no-any-casts 138: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/controlFlow.ts: +vscode • src/vs/base/common/controlFlow.ts: 57: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/decorators.ts: +vscode • src/vs/base/common/decorators.ts: 57: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/errors.ts: +vscode • src/vs/base/common/errors.ts: 142: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/hotReload.ts: +vscode • src/vs/base/common/hotReload.ts: 97: // eslint-disable-next-line local/code-no-any-casts 104: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/hotReloadHelpers.ts: +vscode • src/vs/base/common/hotReloadHelpers.ts: 39: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/lifecycle.ts: +vscode • src/vs/base/common/lifecycle.ts: 236: // eslint-disable-next-line local/code-no-any-casts 246: // eslint-disable-next-line local/code-no-any-casts 257: // eslint-disable-next-line local/code-no-any-casts 317: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/marshalling.ts: +vscode • src/vs/base/common/marshalling.ts: 53: // eslint-disable-next-line local/code-no-any-casts 55: // eslint-disable-next-line local/code-no-any-casts 57: // eslint-disable-next-line local/code-no-any-casts 65: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/network.ts: +vscode • src/vs/base/common/network.ts: 416: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/objects.ts: - 75: // eslint-disable-next-line local/code-no-any-casts - -src/vs/base/common/skipList.ts: +vscode • src/vs/base/common/skipList.ts: 38: // eslint-disable-next-line local/code-no-any-casts 47: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/types.ts: - 58: // eslint-disable-next-line local/code-no-any-casts - 66: // eslint-disable-next-line local/code-no-any-casts - 268: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/base/common/types.ts: + 65: // eslint-disable-next-line local/code-no-any-casts + 73: // eslint-disable-next-line local/code-no-any-casts + 275: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/uriIpc.ts: +vscode • src/vs/base/common/uriIpc.ts: 33: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/verifier.ts: +vscode • src/vs/base/common/verifier.ts: 82: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/changeTracker.ts: +vscode • src/vs/base/common/observableInternal/changeTracker.ts: 34: // eslint-disable-next-line local/code-no-any-casts 42: // eslint-disable-next-line local/code-no-any-casts 69: // eslint-disable-next-line local/code-no-any-casts 80: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/debugLocation.ts: +vscode • src/vs/base/common/observableInternal/debugLocation.ts: 19: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/debugName.ts: +vscode • src/vs/base/common/observableInternal/debugName.ts: 106: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/set.ts: +vscode • src/vs/base/common/observableInternal/set.ts: 51: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/experimental/reducer.ts: +vscode • src/vs/base/common/observableInternal/experimental/reducer.ts: 39: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/logging/consoleObservableLogger.ts: +vscode • src/vs/base/common/observableInternal/logging/consoleObservableLogger.ts: 80: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/logging/debugger/debuggerRpc.ts: +vscode • src/vs/base/common/observableInternal/logging/debugger/debuggerRpc.ts: 12: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/logging/debugger/rpc.ts: +vscode • src/vs/base/common/observableInternal/logging/debugger/rpc.ts: 94: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/observables/derived.ts: +vscode • src/vs/base/common/observableInternal/observables/derived.ts: 38: // eslint-disable-next-line local/code-no-any-casts 40: // eslint-disable-next-line local/code-no-any-casts 124: // eslint-disable-next-line local/code-no-any-casts @@ -247,75 +232,76 @@ src/vs/base/common/observableInternal/observables/derived.ts: 160: // eslint-disable-next-line local/code-no-any-casts 165: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/observables/derivedImpl.ts: +vscode • src/vs/base/common/observableInternal/observables/derivedImpl.ts: 313: // eslint-disable-next-line local/code-no-any-casts 414: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/observables/observableFromEvent.ts: +vscode • src/vs/base/common/observableInternal/observables/observableFromEvent.ts: 151: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/reactions/autorunImpl.ts: +vscode • src/vs/base/common/observableInternal/reactions/autorunImpl.ts: 185: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/common/observableInternal/utils/utilsCancellation.ts: +vscode • src/vs/base/common/observableInternal/utils/utilsCancellation.ts: 78: // eslint-disable-next-line local/code-no-any-casts 83: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/parts/ipc/test/node/ipc.net.test.ts: +vscode • src/vs/base/parts/ipc/test/node/ipc.net.test.ts: 87: // eslint-disable-next-line local/code-no-any-casts 92: // eslint-disable-next-line local/code-no-any-casts 652: // eslint-disable-next-line local/code-no-any-casts 785: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/buffer.test.ts: +vscode • src/vs/base/test/common/buffer.test.ts: 501: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/decorators.test.ts: +vscode • src/vs/base/test/common/decorators.test.ts: 130: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/filters.test.ts: +vscode • src/vs/base/test/common/filters.test.ts: 28: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/glob.test.ts: +vscode • src/vs/base/test/common/glob.test.ts: 497: // eslint-disable-next-line local/code-no-any-casts 518: // eslint-disable-next-line local/code-no-any-casts 763: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/json.test.ts: +vscode • src/vs/base/test/common/json.test.ts: 52: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/mock.ts: - 13: // eslint-disable-next-line local/code-no-any-casts - 22: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/base/test/common/mock.ts: + 14: // eslint-disable-next-line local/code-no-any-casts + 23: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/oauth.test.ts: - 1099: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/base/test/common/oauth.test.ts: + 1100: // eslint-disable-next-line local/code-no-any-casts + 1572: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/snapshot.ts: +vscode • src/vs/base/test/common/snapshot.ts: 123: // eslint-disable-next-line local/code-no-any-casts 125: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/timeTravelScheduler.ts: +vscode • src/vs/base/test/common/timeTravelScheduler.ts: 268: // eslint-disable-next-line local/code-no-any-casts 278: // eslint-disable-next-line local/code-no-any-casts 311: // eslint-disable-next-line local/code-no-any-casts 317: // eslint-disable-next-line local/code-no-any-casts 333: // eslint-disable-next-line local/code-no-any-casts -src/vs/base/test/common/troubleshooting.ts: +vscode • src/vs/base/test/common/troubleshooting.ts: 50: // eslint-disable-next-line local/code-no-any-casts 55: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/editor.api.ts: +vscode • src/vs/editor/editor.api.ts: 44: // eslint-disable-next-line local/code-no-any-casts 46: // eslint-disable-next-line local/code-no-any-casts 51: // eslint-disable-next-line local/code-no-any-casts 53: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/browser/config/editorConfiguration.ts: +vscode • src/vs/editor/browser/config/editorConfiguration.ts: 147: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/controller/mouseTarget.ts: +vscode • src/vs/editor/browser/controller/mouseTarget.ts: 992: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 996: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 1000: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any @@ -324,43 +310,43 @@ src/vs/editor/browser/controller/mouseTarget.ts: 1099: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 1119: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/controller/editContext/native/nativeEditContextUtils.ts: +vscode • src/vs/editor/browser/controller/editContext/native/nativeEditContextUtils.ts: 81: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 85: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/gpu/gpuUtils.ts: +vscode • src/vs/editor/browser/gpu/gpuUtils.ts: 52: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/gpu/viewGpuContext.ts: +vscode • src/vs/editor/browser/gpu/viewGpuContext.ts: 226: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/widget/diffEditor/diffEditorOptions.ts: +vscode • src/vs/editor/browser/widget/diffEditor/diffEditorOptions.ts: 179: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts: +vscode • src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts: 477: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/widget/diffEditor/utils.ts: +vscode • src/vs/editor/browser/widget/diffEditor/utils.ts: 184: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 195: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 303: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 310: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/widget/diffEditor/components/diffEditorEditors.ts: +vscode • src/vs/editor/browser/widget/diffEditor/components/diffEditorEditors.ts: 75: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/browser/widget/multiDiffEditor/diffEditorItemTemplate.ts: +vscode • src/vs/editor/browser/widget/multiDiffEditor/diffEditorItemTemplate.ts: 100: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 103: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/common/textModelEditSource.ts: +vscode • src/vs/editor/common/textModelEditSource.ts: 59: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 70: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/common/core/edits/stringEdit.ts: +vscode • src/vs/editor/common/core/edits/stringEdit.ts: 24: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length.ts: +vscode • src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length.ts: 26: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 30: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 51: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any @@ -379,54 +365,51 @@ src/vs/editor/common/model/bracketPairsTextModelPart/bracketPairsTree/length.ts: 177: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any 196: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/editor/contrib/colorPicker/browser/colorDetector.ts: +vscode • src/vs/editor/contrib/colorPicker/browser/colorDetector.ts: 100: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/contextmenu/browser/contextmenu.ts: - 232: // eslint-disable-next-line local/code-no-any-casts - -src/vs/editor/contrib/documentSymbols/test/browser/outlineModel.test.ts: +vscode • src/vs/editor/contrib/documentSymbols/test/browser/outlineModel.test.ts: 200: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/editorState/test/browser/editorState.test.ts: +vscode • src/vs/editor/contrib/editorState/test/browser/editorState.test.ts: 97: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/find/browser/findModel.ts: +vscode • src/vs/editor/contrib/find/browser/findModel.ts: 556: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/find/test/browser/findController.test.ts: +vscode • src/vs/editor/contrib/find/test/browser/findController.test.ts: 79: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/browser/structuredLogger.ts: +vscode • src/vs/editor/contrib/inlineCompletions/browser/structuredLogger.ts: 56: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts: +vscode • src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts: 640: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts: +vscode • src/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts: 274: // eslint-disable-next-line local/code-no-any-casts 296: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.ts: +vscode • src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.ts: 346: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/debugVisualization.ts: +vscode • src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/debugVisualization.ts: 15: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/test/browser/computeGhostText.test.ts: +vscode • src/vs/editor/contrib/inlineCompletions/test/browser/computeGhostText.test.ts: 23: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/test/browser/suggestWidgetModel.test.ts: +vscode • src/vs/editor/contrib/inlineCompletions/test/browser/suggestWidgetModel.test.ts: 163: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/inlineCompletions/test/browser/utils.ts: +vscode • src/vs/editor/contrib/inlineCompletions/test/browser/utils.ts: 240: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts: - 797: // eslint-disable-next-line local/code-no-any-casts - 816: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts: + 794: // eslint-disable-next-line local/code-no-any-casts + 813: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/standalone/browser/standaloneEditor.ts: +vscode • src/vs/editor/standalone/browser/standaloneEditor.ts: 504: // eslint-disable-next-line local/code-no-any-casts 506: // eslint-disable-next-line local/code-no-any-casts 508: // eslint-disable-next-line local/code-no-any-casts @@ -465,7 +448,7 @@ src/vs/editor/standalone/browser/standaloneEditor.ts: 614: // eslint-disable-next-line local/code-no-any-casts 619: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/standalone/browser/standaloneLanguages.ts: +vscode • src/vs/editor/standalone/browser/standaloneLanguages.ts: 753: // eslint-disable-next-line local/code-no-any-casts 755: // eslint-disable-next-line local/code-no-any-casts 757: // eslint-disable-next-line local/code-no-any-casts @@ -504,157 +487,157 @@ src/vs/editor/standalone/browser/standaloneLanguages.ts: 849: // eslint-disable-next-line local/code-no-any-casts 851: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/standalone/common/monarch/monarchCompile.ts: +vscode • src/vs/editor/standalone/common/monarch/monarchCompile.ts: 461: // eslint-disable-next-line local/code-no-any-casts 539: // eslint-disable-next-line local/code-no-any-casts 556: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/test/browser/testCodeEditor.ts: +vscode • src/vs/editor/test/browser/testCodeEditor.ts: 279: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/test/browser/config/editorConfiguration.test.ts: +vscode • src/vs/editor/test/browser/config/editorConfiguration.test.ts: 90: // eslint-disable-next-line local/code-no-any-casts 99: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/test/common/model/textModel.test.ts: +vscode • src/vs/editor/test/common/model/textModel.test.ts: 1167: // eslint-disable-next-line local/code-no-any-casts -src/vs/editor/test/common/model/textModelWithTokens.test.ts: +vscode • src/vs/editor/test/common/model/textModelWithTokens.test.ts: 272: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/contextkey/common/contextkey.ts: +vscode • src/vs/platform/contextkey/common/contextkey.ts: 939: // eslint-disable-next-line local/code-no-any-casts 1213: // eslint-disable-next-line local/code-no-any-casts 1273: // eslint-disable-next-line local/code-no-any-casts 1334: // eslint-disable-next-line local/code-no-any-casts 1395: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/contextkey/test/common/contextkey.test.ts: +vscode • src/vs/platform/contextkey/test/common/contextkey.test.ts: 96: // eslint-disable-next-line local/code-no-any-casts 98: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/environment/test/node/argv.test.ts: +vscode • src/vs/platform/environment/test/node/argv.test.ts: 47: // eslint-disable-next-line local/code-no-any-casts 59: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/extensionManagement/common/extensionManagementIpc.ts: +vscode • src/vs/platform/extensionManagement/common/extensionManagementIpc.ts: 243: // eslint-disable-next-line local/code-no-any-casts 245: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts: +vscode • src/vs/platform/extensionManagement/common/extensionsProfileScannerService.ts: 405: // eslint-disable-next-line local/code-no-any-casts 407: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/extensionManagement/common/implicitActivationEvents.ts: +vscode • src/vs/platform/extensionManagement/common/implicitActivationEvents.ts: 73: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/files/browser/htmlFileSystemProvider.ts: +vscode • src/vs/platform/files/browser/htmlFileSystemProvider.ts: 311: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/platform/files/test/node/diskFileService.integrationTest.ts: +vscode • src/vs/platform/files/test/node/diskFileService.integrationTest.ts: 106: // eslint-disable-next-line local/code-no-any-casts 109: // eslint-disable-next-line local/code-no-any-casts 112: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/instantiation/common/instantiationService.ts: +vscode • src/vs/platform/instantiation/common/instantiationService.ts: 328: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/list/browser/listService.ts: +vscode • src/vs/platform/list/browser/listService.ts: 877: // eslint-disable-next-line local/code-no-any-casts 918: // eslint-disable-next-line local/code-no-any-casts 965: // eslint-disable-next-line local/code-no-any-casts 1012: // eslint-disable-next-line local/code-no-any-casts 1057: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/observable/common/wrapInHotClass.ts: +vscode • src/vs/platform/observable/common/wrapInHotClass.ts: 12: // eslint-disable-next-line local/code-no-any-casts 40: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/observable/common/wrapInReloadableClass.ts: +vscode • src/vs/platform/observable/common/wrapInReloadableClass.ts: 31: // eslint-disable-next-line local/code-no-any-casts 38: // eslint-disable-next-line local/code-no-any-casts 59: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/policy/node/nativePolicyService.ts: +vscode • src/vs/platform/policy/node/nativePolicyService.ts: 47: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/profiling/common/profilingTelemetrySpec.ts: +vscode • src/vs/platform/profiling/common/profilingTelemetrySpec.ts: 73: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/quickinput/browser/tree/quickTree.ts: - 73: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/platform/quickinput/browser/tree/quickTree.ts: + 74: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/quickinput/test/browser/quickinput.test.ts: +vscode • src/vs/platform/quickinput/test/browser/quickinput.test.ts: 69: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/remote/browser/browserSocketFactory.ts: +vscode • src/vs/platform/remote/browser/browserSocketFactory.ts: 89: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/remote/common/remoteAgentConnection.ts: +vscode • src/vs/platform/remote/common/remoteAgentConnection.ts: 784: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/remote/test/electron-browser/remoteAuthorityResolverService.test.ts: +vscode • src/vs/platform/remote/test/electron-browser/remoteAuthorityResolverService.test.ts: 19: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/request/electron-utility/requestService.ts: +vscode • src/vs/platform/request/electron-utility/requestService.ts: 15: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/terminal/node/terminalProcess.ts: +vscode • src/vs/platform/terminal/node/terminalProcess.ts: 546: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/userDataSync/common/extensionsSync.ts: +vscode • src/vs/platform/userDataSync/common/extensionsSync.ts: 60: // eslint-disable-next-line local/code-no-any-casts 64: // eslint-disable-next-line local/code-no-any-casts -src/vs/platform/webContentExtractor/test/electron-main/cdpAccessibilityDomain.test.ts: +vscode • src/vs/platform/webContentExtractor/test/electron-main/cdpAccessibilityDomain.test.ts: 22: // eslint-disable-next-line local/code-no-any-casts -src/vs/server/node/extensionHostConnection.ts: +vscode • src/vs/server/node/extensionHostConnection.ts: 240: // eslint-disable-next-line local/code-no-any-casts -src/vs/server/node/remoteExtensionHostAgentServer.ts: +vscode • src/vs/server/node/remoteExtensionHostAgentServer.ts: 765: // eslint-disable-next-line local/code-no-any-casts 767: // eslint-disable-next-line local/code-no-any-casts 769: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/workbench.web.main.internal.ts: +vscode • src/vs/workbench/workbench.web.main.internal.ts: 198: // eslint-disable-next-line local/code-no-any-casts 223: // eslint-disable-next-line local/code-no-any-casts 225: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/workbench.web.main.ts: +vscode • src/vs/workbench/workbench.web.main.ts: 58: // eslint-disable-next-line local/code-no-any-casts 60: // eslint-disable-next-line local/code-no-any-casts 82: // eslint-disable-next-line local/code-no-any-casts 91: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/browser/mainThreadExtensionService.ts: +vscode • src/vs/workbench/api/browser/mainThreadExtensionService.ts: 57: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts: - 1000: // eslint-disable-next-line local/code-no-any-casts - 1011: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/api/browser/mainThreadLanguageFeatures.ts: + 1013: // eslint-disable-next-line local/code-no-any-casts + 1024: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/browser/mainThreadQuickOpen.ts: +vscode • src/vs/workbench/api/browser/mainThreadQuickOpen.ts: 195: // eslint-disable-next-line local/code-no-any-casts 198: // eslint-disable-next-line local/code-no-any-casts 203: // eslint-disable-next-line local/code-no-any-casts 216: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/browser/viewsExtensionPoint.ts: +vscode • src/vs/workbench/api/browser/viewsExtensionPoint.ts: 528: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHost.api.impl.ts: +vscode • src/vs/workbench/api/common/extHost.api.impl.ts: 161: // eslint-disable-next-line local/code-no-any-casts 315: // eslint-disable-next-line local/code-no-any-casts 324: // eslint-disable-next-line local/code-no-any-casts 563: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHost.protocol.ts: - 2106: // eslint-disable-next-line local/code-no-any-casts - 2108: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/api/common/extHost.protocol.ts: + 2109: // eslint-disable-next-line local/code-no-any-casts + 2111: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostDebugService.ts: +vscode • src/vs/workbench/api/common/extHostDebugService.ts: 243: // eslint-disable-next-line local/code-no-any-casts 491: // eslint-disable-next-line local/code-no-any-casts 493: // eslint-disable-next-line local/code-no-any-casts @@ -663,76 +646,76 @@ src/vs/workbench/api/common/extHostDebugService.ts: 770: // eslint-disable-next-line local/code-no-any-casts 778: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts: +vscode • src/vs/workbench/api/common/extHostDocumentSaveParticipant.ts: 65: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostExtensionActivator.ts: +vscode • src/vs/workbench/api/common/extHostExtensionActivator.ts: 405: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostExtensionService.ts: +vscode • src/vs/workbench/api/common/extHostExtensionService.ts: 566: // eslint-disable-next-line local/code-no-any-casts 1009: // eslint-disable-next-line local/code-no-any-casts 1050: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostLanguageFeatures.ts: +vscode • src/vs/workbench/api/common/extHostLanguageFeatures.ts: 197: // eslint-disable-next-line local/code-no-any-casts 714: // eslint-disable-next-line local/code-no-any-casts 735: // eslint-disable-next-line local/code-no-any-casts 748: // eslint-disable-next-line local/code-no-any-casts 771: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostLanguageModels.ts: - 174: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/api/common/extHostLanguageModels.ts: + 175: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostLanguageModelTools.ts: +vscode • src/vs/workbench/api/common/extHostLanguageModelTools.ts: 221: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostMcp.ts: +vscode • src/vs/workbench/api/common/extHostMcp.ts: 163: // eslint-disable-next-line local/code-no-any-casts 165: // eslint-disable-next-line local/code-no-any-casts 168: // eslint-disable-next-line local/code-no-any-casts 170: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostSearch.ts: +vscode • src/vs/workbench/api/common/extHostSearch.ts: 221: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostTerminalService.ts: +vscode • src/vs/workbench/api/common/extHostTerminalService.ts: 1287: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostTimeline.ts: +vscode • src/vs/workbench/api/common/extHostTimeline.ts: 160: // eslint-disable-next-line local/code-no-any-casts 163: // eslint-disable-next-line local/code-no-any-casts 166: // eslint-disable-next-line local/code-no-any-casts 169: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostTypeConverters.ts: +vscode • src/vs/workbench/api/common/extHostTypeConverters.ts: 463: // eslint-disable-next-line local/code-no-any-casts 856: // eslint-disable-next-line local/code-no-any-casts - 3142: // eslint-disable-next-line local/code-no-any-casts - 3144: // eslint-disable-next-line local/code-no-any-casts - 3146: // eslint-disable-next-line local/code-no-any-casts - 3148: // eslint-disable-next-line local/code-no-any-casts - 3150: // eslint-disable-next-line local/code-no-any-casts - 3152: // eslint-disable-next-line local/code-no-any-casts - 3154: // eslint-disable-next-line local/code-no-any-casts - 3156: // eslint-disable-next-line local/code-no-any-casts - 3163: // eslint-disable-next-line local/code-no-any-casts + 3173: // eslint-disable-next-line local/code-no-any-casts + 3175: // eslint-disable-next-line local/code-no-any-casts + 3177: // eslint-disable-next-line local/code-no-any-casts + 3179: // eslint-disable-next-line local/code-no-any-casts + 3181: // eslint-disable-next-line local/code-no-any-casts + 3183: // eslint-disable-next-line local/code-no-any-casts + 3185: // eslint-disable-next-line local/code-no-any-casts + 3187: // eslint-disable-next-line local/code-no-any-casts + 3194: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/common/extHostTypes.ts: +vscode • src/vs/workbench/api/common/extHostTypes.ts: 3175: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/node/extensionHostProcess.ts: +vscode • src/vs/workbench/api/node/extensionHostProcess.ts: 107: // eslint-disable-next-line local/code-no-any-casts 119: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/node/extHostConsoleForwarder.ts: +vscode • src/vs/workbench/api/node/extHostConsoleForwarder.ts: 31: // eslint-disable-next-line local/code-no-any-casts 53: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/node/extHostMcpNode.ts: +vscode • src/vs/workbench/api/node/extHostMcpNode.ts: 57: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/node/proxyResolver.ts: +vscode • src/vs/workbench/api/node/proxyResolver.ts: 92: // eslint-disable-next-line local/code-no-any-casts 95: // eslint-disable-next-line local/code-no-any-casts 103: // eslint-disable-next-line local/code-no-any-casts @@ -741,21 +724,21 @@ src/vs/workbench/api/node/proxyResolver.ts: 132: // eslint-disable-next-line local/code-no-any-casts 373: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostApiCommands.test.ts: - 870: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/api/test/browser/extHostApiCommands.test.ts: + 874: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostAuthentication.integrationTest.ts: +vscode • src/vs/workbench/api/test/browser/extHostAuthentication.integrationTest.ts: 75: // eslint-disable-next-line local/code-no-any-casts 164: // eslint-disable-next-line local/code-no-any-casts 173: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostCommands.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostCommands.test.ts: 92: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostConfiguration.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostConfiguration.test.ts: 750: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostDocumentData.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostDocumentData.test.ts: 46: // eslint-disable-next-line local/code-no-any-casts 48: // eslint-disable-next-line local/code-no-any-casts 50: // eslint-disable-next-line local/code-no-any-casts @@ -763,17 +746,17 @@ src/vs/workbench/api/test/browser/extHostDocumentData.test.ts: 54: // eslint-disable-next-line local/code-no-any-casts 56: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostDocumentSaveParticipant.test.ts: 84: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostLanguageFeatures.test.ts: 1068: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostNotebookKernel.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostNotebookKernel.test.ts: 164: // eslint-disable-next-line local/code-no-any-casts 166: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostTelemetry.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostTelemetry.test.ts: 107: // eslint-disable-next-line local/code-no-any-casts 109: // eslint-disable-next-line local/code-no-any-casts 111: // eslint-disable-next-line local/code-no-any-casts @@ -781,55 +764,55 @@ src/vs/workbench/api/test/browser/extHostTelemetry.test.ts: 121: // eslint-disable-next-line local/code-no-any-casts 128: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostTesting.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostTesting.test.ts: 640: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostTextEditor.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostTextEditor.test.ts: 265: // eslint-disable-next-line local/code-no-any-casts 290: // eslint-disable-next-line local/code-no-any-casts 327: // eslint-disable-next-line local/code-no-any-casts 340: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostTypes.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostTypes.test.ts: 87: // eslint-disable-next-line local/code-no-any-casts 89: // eslint-disable-next-line local/code-no-any-casts 91: // eslint-disable-next-line local/code-no-any-casts 209: // eslint-disable-next-line local/code-no-any-casts 211: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/extHostWorkspace.test.ts: +vscode • src/vs/workbench/api/test/browser/extHostWorkspace.test.ts: 541: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/mainThreadAuthentication.integrationTest.ts: +vscode • src/vs/workbench/api/test/browser/mainThreadAuthentication.integrationTest.ts: 115: // eslint-disable-next-line local/code-no-any-casts 122: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts: +vscode • src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts: 86: // eslint-disable-next-line local/code-no-any-casts 93: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/mainThreadEditors.test.ts: +vscode • src/vs/workbench/api/test/browser/mainThreadEditors.test.ts: 115: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts: +vscode • src/vs/workbench/api/test/browser/mainThreadTreeViews.test.ts: 60: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/common/extensionHostMain.test.ts: +vscode • src/vs/workbench/api/test/common/extensionHostMain.test.ts: 80: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/common/extHostTerminalShellIntegration.test.ts: +vscode • src/vs/workbench/api/test/common/extHostTerminalShellIntegration.test.ts: 86: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/common/testRPCProtocol.ts: +vscode • src/vs/workbench/api/test/common/testRPCProtocol.ts: 36: // eslint-disable-next-line local/code-no-any-casts 163: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/test/node/extHostSearch.test.ts: +vscode • src/vs/workbench/api/test/node/extHostSearch.test.ts: 177: // eslint-disable-next-line local/code-no-any-casts 1004: // eslint-disable-next-line local/code-no-any-casts 1050: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/worker/extensionHostWorker.ts: +vscode • src/vs/workbench/api/worker/extensionHostWorker.ts: 83: // eslint-disable-next-line local/code-no-any-casts 85: // eslint-disable-next-line local/code-no-any-casts 87: // eslint-disable-next-line local/code-no-any-casts @@ -843,35 +826,35 @@ src/vs/workbench/api/worker/extensionHostWorker.ts: 106: // eslint-disable-next-line local/code-no-any-casts 158: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/api/worker/extHostConsoleForwarder.ts: +vscode • src/vs/workbench/api/worker/extHostConsoleForwarder.ts: 20: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/browser/actions/developerActions.ts: +vscode • src/vs/workbench/browser/actions/developerActions.ts: 781: // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any -src/vs/workbench/contrib/accessibilitySignals/browser/commands.ts: +vscode • src/vs/workbench/contrib/accessibilitySignals/browser/commands.ts: 54: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/bulkEdit/test/browser/bulkCellEdits.test.ts: +vscode • src/vs/workbench/contrib/bulkEdit/test/browser/bulkCellEdits.test.ts: 29: // eslint-disable-next-line local/code-no-any-casts 39: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts: +vscode • src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts: + 86: // eslint-disable-next-line local/code-no-any-casts 88: // eslint-disable-next-line local/code-no-any-casts - 90: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/browser/chatSessions/common.ts: +vscode • src/vs/workbench/contrib/chat/browser/chatSessions/common.ts: 126: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/common/chatModel.ts: +vscode • src/vs/workbench/contrib/chat/common/chatModel.ts: 1214: // eslint-disable-next-line local/code-no-any-casts - 1531: // eslint-disable-next-line local/code-no-any-casts - 1863: // eslint-disable-next-line local/code-no-any-casts + 1537: // eslint-disable-next-line local/code-no-any-casts + 1869: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/common/chatServiceImpl.ts: - 439: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/chat/common/chatServiceImpl.ts: + 437: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/test/browser/chatEditingModifiedNotebookEntry.test.ts: +vscode • src/vs/workbench/contrib/chat/test/browser/chatEditingModifiedNotebookEntry.test.ts: 30: // eslint-disable-next-line local/code-no-any-casts 35: // eslint-disable-next-line local/code-no-any-casts 63: // eslint-disable-next-line local/code-no-any-casts @@ -892,14 +875,14 @@ src/vs/workbench/contrib/chat/test/browser/chatEditingModifiedNotebookEntry.test 1532: // eslint-disable-next-line local/code-no-any-casts 1537: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/test/browser/chatEditingSessionStorage.test.ts: +vscode • src/vs/workbench/contrib/chat/test/browser/chatEditingSessionStorage.test.ts: 41: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/test/browser/chatTodoListWidget.test.ts: +vscode • src/vs/workbench/contrib/chat/test/browser/chatTodoListWidget.test.ts: 35: // eslint-disable-next-line local/code-no-any-casts 144: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/test/common/chatRequestParser.test.ts: +vscode • src/vs/workbench/contrib/chat/test/common/chatRequestParser.test.ts: 72: // eslint-disable-next-line local/code-no-any-casts 84: // eslint-disable-next-line local/code-no-any-casts 96: // eslint-disable-next-line local/code-no-any-casts @@ -923,273 +906,219 @@ src/vs/workbench/contrib/chat/test/common/chatRequestParser.test.ts: 330: // eslint-disable-next-line local/code-no-any-casts 346: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/chat/test/common/tools/manageTodoListTool.test.ts: +vscode • src/vs/workbench/contrib/chat/test/common/tools/manageTodoListTool.test.ts: 16: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/browser/debugSession.ts: +vscode • src/vs/workbench/contrib/debug/browser/debugSession.ts: 1193: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts: - 46: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/browser/rawDebugSession.ts: - 813: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/common/debugger.ts: - 168: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/common/debugUtils.ts: - 66: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts: +vscode • src/vs/workbench/contrib/debug/test/browser/breakpoints.test.ts: 450: // eslint-disable-next-line local/code-no-any-casts 466: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/browser/callStack.test.ts: - 28: // eslint-disable-next-line local/code-no-any-casts - 124: // eslint-disable-next-line local/code-no-any-casts - 206: // eslint-disable-next-line local/code-no-any-casts - 261: // eslint-disable-next-line local/code-no-any-casts - 461: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/test/browser/debugConfigurationManager.test.ts: +vscode • src/vs/workbench/contrib/debug/test/browser/debugConfigurationManager.test.ts: 92: // eslint-disable-next-line local/code-no-any-casts 129: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/browser/debugMemory.test.ts: +vscode • src/vs/workbench/contrib/debug/test/browser/debugMemory.test.ts: 76: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/browser/mockDebugModel.ts: - 19: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/debug/test/browser/rawDebugSession.test.ts: +vscode • src/vs/workbench/contrib/debug/test/browser/rawDebugSession.test.ts: 28: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/browser/repl.test.ts: +vscode • src/vs/workbench/contrib/debug/test/browser/repl.test.ts: 139: // eslint-disable-next-line local/code-no-any-casts 142: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/common/debugModel.test.ts: - 50: // eslint-disable-next-line local/code-no-any-casts - 62: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/debug/test/common/debugModel.test.ts: 70: // eslint-disable-next-line local/code-no-any-casts 75: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/debug/test/common/mockDebug.ts: - 695: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/editTelemetry/browser/helpers/utils.ts: +vscode • src/vs/workbench/contrib/editTelemetry/browser/helpers/utils.ts: 15: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/editTelemetry/browser/telemetry/arcTelemetrySender.ts: +vscode • src/vs/workbench/contrib/editTelemetry/browser/telemetry/arcTelemetrySender.ts: 147: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts: +vscode • src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts: 1182: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts: +vscode • src/vs/workbench/contrib/extensions/test/electron-browser/extensionsActions.test.ts: 99: // eslint-disable-next-line local/code-no-any-casts 101: // eslint-disable-next-line local/code-no-any-casts 103: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts: +vscode • src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts: 100: // eslint-disable-next-line local/code-no-any-casts 102: // eslint-disable-next-line local/code-no-any-casts 104: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/files/test/browser/editorAutoSave.test.ts: +vscode • src/vs/workbench/contrib/files/test/browser/editorAutoSave.test.ts: 46: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/files/test/browser/explorerView.test.ts: +vscode • src/vs/workbench/contrib/files/test/browser/explorerView.test.ts: 94: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts: +vscode • src/vs/workbench/contrib/inlineChat/test/browser/inlineChatController.test.ts: 160: // eslint-disable-next-line local/code-no-any-casts 662: // eslint-disable-next-line local/code-no-any-casts 711: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/markdown/test/browser/markdownSettingRenderer.test.ts: +vscode • src/vs/workbench/contrib/markdown/test/browser/markdownSettingRenderer.test.ts: 72: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/markers/browser/markersTable.ts: +vscode • src/vs/workbench/contrib/markers/browser/markersTable.ts: 343: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts: +vscode • src/vs/workbench/contrib/markers/test/browser/markersModel.test.ts: 143: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/mcp/common/uriTemplate.ts: - 159: // eslint-disable-next-line local/code-no-any-casts - 191: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/mcp/test/common/mcpRegistry.test.ts: - 68: // eslint-disable-next-line local/code-no-any-casts - 212: // eslint-disable-next-line local/code-no-any-casts - 218: // eslint-disable-next-line local/code-no-any-casts - 262: // eslint-disable-next-line local/code-no-any-casts - 264: // eslint-disable-next-line local/code-no-any-casts - 271: // eslint-disable-next-line local/code-no-any-casts - 280: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/mcp/test/common/mcpResourceFilesystem.test.ts: - 53: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/mcp/test/common/mcpSamplingLog.test.ts: - 18: // eslint-disable-next-line local/code-no-any-casts - 52: // eslint-disable-next-line local/code-no-any-casts - 95: // eslint-disable-next-line local/code-no-any-casts - 128: // eslint-disable-next-line local/code-no-any-casts - 147: // eslint-disable-next-line local/code-no-any-casts - 168: // eslint-disable-next-line local/code-no-any-casts - 220: // eslint-disable-next-line local/code-no-any-casts - 231: // eslint-disable-next-line local/code-no-any-casts - 254: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/mergeEditor/browser/utils.ts: +vscode • src/vs/workbench/contrib/mergeEditor/browser/utils.ts: 89: // eslint-disable-next-line local/code-no-any-casts 99: // eslint-disable-next-line local/code-no-any-casts 120: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/mergeEditor/browser/commands/commands.ts: +vscode • src/vs/workbench/contrib/mergeEditor/browser/commands/commands.ts: 69: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts: +vscode • src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts: 309: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/controller/notebookIndentationActions.ts: +vscode • src/vs/workbench/contrib/notebook/browser/controller/notebookIndentationActions.ts: 127: // eslint-disable-next-line local/code-no-any-casts 199: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/services/notebookEditorServiceImpl.ts: +vscode • src/vs/workbench/contrib/notebook/browser/services/notebookEditorServiceImpl.ts: 74: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts: +vscode • src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts: 122: // eslint-disable-next-line local/code-no-any-casts 1462: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel.ts: +vscode • src/vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel.ts: 329: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts: +vscode • src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts: 170: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/viewParts/notebookHorizontalTracker.ts: +vscode • src/vs/workbench/contrib/notebook/browser/viewParts/notebookHorizontalTracker.ts: 75: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelQuickPickStrategy.ts: +vscode • src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelQuickPickStrategy.ts: 424: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts: - 563: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts: + 575: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts: - 1095: // eslint-disable-next-line local/code-no-any-casts - 1137: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts: + 1110: // eslint-disable-next-line local/code-no-any-casts + 1152: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/notebookCellLayoutManager.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/notebookCellLayoutManager.test.ts: 50: // eslint-disable-next-line local/code-no-any-casts 66: // eslint-disable-next-line local/code-no-any-casts 85: // eslint-disable-next-line local/code-no-any-casts 96: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/notebookEditorModel.test.ts: 284: // eslint-disable-next-line local/code-no-any-casts 308: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/NotebookEditorWidgetService.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/NotebookEditorWidgetService.test.ts: 37: // eslint-disable-next-line local/code-no-any-casts 91: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/contrib/notebookOutline.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/contrib/notebookOutline.test.ts: 72: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/diff/editorHeightCalculator.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/diff/editorHeightCalculator.test.ts: 26: // eslint-disable-next-line local/code-no-any-casts 59: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/notebook/test/browser/diff/notebookDiff.test.ts: +vscode • src/vs/workbench/contrib/notebook/test/browser/diff/notebookDiff.test.ts: 652: // eslint-disable-next-line local/code-no-any-casts 654: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/search/browser/searchActionsFind.ts: +vscode • src/vs/workbench/contrib/search/browser/searchActionsFind.ts: 460: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/search/browser/searchMessage.ts: +vscode • src/vs/workbench/contrib/search/browser/searchMessage.ts: 51: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/search/browser/searchTreeModel/searchModel.ts: +vscode • src/vs/workbench/contrib/search/browser/searchTreeModel/searchModel.ts: 306: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/search/browser/searchTreeModel/searchTreeCommon.ts: +vscode • src/vs/workbench/contrib/search/browser/searchTreeModel/searchTreeCommon.ts: 299: // eslint-disable-next-line local/code-no-any-casts 301: // eslint-disable-next-line local/code-no-any-casts 318: // eslint-disable-next-line local/code-no-any-casts 324: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/search/test/browser/searchModel.test.ts: +vscode • src/vs/workbench/contrib/search/test/browser/searchModel.test.ts: 201: // eslint-disable-next-line local/code-no-any-casts 229: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts: +vscode • src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts: 205: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts: +vscode • src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts: 155: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts: +vscode • src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts: 328: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts: - 1492: // eslint-disable-next-line local/code-no-any-casts - 1501: // eslint-disable-next-line local/code-no-any-casts - 1540: // eslint-disable-next-line local/code-no-any-casts - 1586: // eslint-disable-next-line local/code-no-any-casts - 1740: // eslint-disable-next-line local/code-no-any-casts - 1787: // eslint-disable-next-line local/code-no-any-casts - 1790: // eslint-disable-next-line local/code-no-any-casts - 2656: // eslint-disable-next-line local/code-no-any-casts - 2837: // eslint-disable-next-line local/code-no-any-casts - 3569: // eslint-disable-next-line local/code-no-any-casts - 3603: // eslint-disable-next-line local/code-no-any-casts - 3609: // eslint-disable-next-line local/code-no-any-casts - 3738: // eslint-disable-next-line local/code-no-any-casts - 3797: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts: + 1491: // eslint-disable-next-line local/code-no-any-casts + 1500: // eslint-disable-next-line local/code-no-any-casts + 1539: // eslint-disable-next-line local/code-no-any-casts + 1585: // eslint-disable-next-line local/code-no-any-casts + 1739: // eslint-disable-next-line local/code-no-any-casts + 1786: // eslint-disable-next-line local/code-no-any-casts + 1789: // eslint-disable-next-line local/code-no-any-casts + 2655: // eslint-disable-next-line local/code-no-any-casts + 2836: // eslint-disable-next-line local/code-no-any-casts + 3568: // eslint-disable-next-line local/code-no-any-casts + 3602: // eslint-disable-next-line local/code-no-any-casts + 3608: // eslint-disable-next-line local/code-no-any-casts + 3737: // eslint-disable-next-line local/code-no-any-casts + 3796: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/tasks/common/problemMatcher.ts: +vscode • src/vs/workbench/contrib/tasks/common/problemMatcher.ts: 361: // eslint-disable-next-line local/code-no-any-casts 374: // eslint-disable-next-line local/code-no-any-casts 1015: // eslint-disable-next-line local/code-no-any-casts 1906: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/tasks/common/taskConfiguration.ts: +vscode • src/vs/workbench/contrib/tasks/common/taskConfiguration.ts: 1720: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/tasks/common/tasks.ts: - 655: // eslint-disable-next-line local/code-no-any-casts - 696: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/tasks/common/tasks.ts: + 667: // eslint-disable-next-line local/code-no-any-casts + 708: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/tasks/test/browser/taskTerminalStatus.test.ts: +vscode • src/vs/workbench/contrib/tasks/test/browser/taskTerminalStatus.test.ts: 84: // eslint-disable-next-line local/code-no-any-casts 86: // eslint-disable-next-line local/code-no-any-casts 89: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/terminalInstance.test.ts: 99: // eslint-disable-next-line local/code-no-any-casts 445: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/terminalProcessManager.test.ts: 55: // eslint-disable-next-line local/code-no-any-casts 96: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.integrationTest.ts: - 101: // eslint-disable-next-line local/code-no-any-casts - 127: // eslint-disable-next-line local/code-no-any-casts - 172: // eslint-disable-next-line local/code-no-any-casts - 227: // eslint-disable-next-line local/code-no-any-casts - 244: // eslint-disable-next-line local/code-no-any-casts - 261: // eslint-disable-next-line local/code-no-any-casts - 275: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/terminal/test/browser/terminalProfileService.integrationTest.ts: + 104: // eslint-disable-next-line local/code-no-any-casts + 130: // eslint-disable-next-line local/code-no-any-casts + 175: // eslint-disable-next-line local/code-no-any-casts + 230: // eslint-disable-next-line local/code-no-any-casts + 247: // eslint-disable-next-line local/code-no-any-casts + 264: // eslint-disable-next-line local/code-no-any-casts + 278: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts: 58: // eslint-disable-next-line local/code-no-any-casts 65: // eslint-disable-next-line local/code-no-any-casts 75: // eslint-disable-next-line local/code-no-any-casts @@ -1205,7 +1134,7 @@ src/vs/workbench/contrib/terminal/test/browser/terminalService.test.ts: 165: // eslint-disable-next-line local/code-no-any-casts 178: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilityStore.test.ts: 28: // eslint-disable-next-line local/code-no-any-casts 34: // eslint-disable-next-line local/code-no-any-casts 42: // eslint-disable-next-line local/code-no-any-casts @@ -1222,7 +1151,7 @@ src/vs/workbench/contrib/terminal/test/browser/capabilities/terminalCapabilitySt 135: // eslint-disable-next-line local/code-no-any-casts 144: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.integrationTest.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.integrationTest.ts: 59: // eslint-disable-next-line local/code-no-any-casts 67: // eslint-disable-next-line local/code-no-any-casts 75: // eslint-disable-next-line local/code-no-any-casts @@ -1232,39 +1161,39 @@ src/vs/workbench/contrib/terminal/test/browser/xterm/shellIntegrationAddon.integ 107: // eslint-disable-next-line local/code-no-any-casts 165: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts: +vscode • src/vs/workbench/contrib/terminal/test/browser/xterm/xtermTerminal.test.ts: 51: // eslint-disable-next-line local/code-no-any-casts 70: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/accessibility/test/browser/bufferContentTracker.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/accessibility/test/browser/bufferContentTracker.test.ts: 71: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/outputMonitor.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/outputMonitor.test.ts: 40: // eslint-disable-next-line local/code-no-any-casts 56: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/runInTerminalTool.test.ts: - 379: // eslint-disable-next-line local/code-no-any-casts - 833: // eslint-disable-next-line local/code-no-any-casts - 857: // eslint-disable-next-line local/code-no-any-casts - 862: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/runInTerminalTool.test.ts: + 380: // eslint-disable-next-line local/code-no-any-casts + 834: // eslint-disable-next-line local/code-no-any-casts + 858: // eslint-disable-next-line local/code-no-any-casts + 863: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/history/test/common/history.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/history/test/common/history.test.ts: 102: // eslint-disable-next-line local/code-no-any-casts 108: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkHelpers.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkHelpers.test.ts: 242: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkManager.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkManager.test.ts: 95: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkOpeners.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalLinkOpeners.test.ts: 150: // eslint-disable-next-line local/code-no-any-casts 290: // eslint-disable-next-line local/code-no-any-casts 553: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalWordLinkDetector.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalWordLinkDetector.test.ts: 49: // eslint-disable-next-line local/code-no-any-casts 59: // eslint-disable-next-line local/code-no-any-casts 69: // eslint-disable-next-line local/code-no-any-casts @@ -1276,113 +1205,77 @@ src/vs/workbench/contrib/terminalContrib/links/test/browser/terminalWordLinkDete 136: // eslint-disable-next-line local/code-no-any-casts 142: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts: - 787: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/contrib/terminalContrib/suggest/browser/terminalSuggestAddon.ts: + 786: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts: +vscode • src/vs/workbench/contrib/terminalContrib/typeAhead/test/browser/terminalTypeAhead.test.ts: 39: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/testing/browser/testResultsView/testResultsOutput.ts: - 123: // eslint-disable-next-line local/code-no-any-casts - 125: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/common/observableUtils.ts: - 17: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/common/testingStates.ts: - 78: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/browser/codeCoverageDecorations.test.ts: - 19: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/browser/testObjectTree.ts: +vscode • src/vs/workbench/contrib/testing/test/browser/testObjectTree.ts: 122: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/testing/test/browser/explorerProjections/nameProjection.test.ts: - 35: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/browser/explorerProjections/treeProjection.test.ts: - 42: // eslint-disable-next-line local/code-no-any-casts - 137: // eslint-disable-next-line local/code-no-any-casts - 154: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/common/testCoverage.test.ts: - 27: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/common/testProfileService.test.ts: - 49: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/common/testResultService.test.ts: - 210: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/testing/test/common/testStubs.ts: - 85: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/contrib/themes/browser/themes.contribution.ts: +vscode • src/vs/workbench/contrib/themes/browser/themes.contribution.ts: 614: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts: +vscode • src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts: 600: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/assignment/common/assignmentFilters.ts: - 104: // eslint-disable-next-line local/code-no-any-casts - -src/vs/workbench/services/authentication/test/browser/authenticationMcpAccessService.test.ts: +vscode • src/vs/workbench/services/authentication/test/browser/authenticationMcpAccessService.test.ts: 236: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/configurationResolver/common/configurationResolverExpression.ts: +vscode • src/vs/workbench/services/configurationResolver/common/configurationResolverExpression.ts: 81: // eslint-disable-next-line local/code-no-any-casts 106: // eslint-disable-next-line local/code-no-any-casts 306: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/driver/browser/driver.ts: +vscode • src/vs/workbench/services/driver/browser/driver.ts: 193: // eslint-disable-next-line local/code-no-any-casts 215: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts: +vscode • src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.ts: 61: // eslint-disable-next-line local/code-no-any-casts 63: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/extensions/common/extensionsRegistry.ts: +vscode • src/vs/workbench/services/extensions/common/extensionsRegistry.ts: 229: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/extensions/test/common/extensionManifestPropertiesService.test.ts: +vscode • src/vs/workbench/services/extensions/test/common/extensionManifestPropertiesService.test.ts: 49: // eslint-disable-next-line local/code-no-any-casts 54: // eslint-disable-next-line local/code-no-any-casts 97: // eslint-disable-next-line local/code-no-any-casts 102: // eslint-disable-next-line local/code-no-any-casts 107: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts: +vscode • src/vs/workbench/services/extensions/test/common/rpcProtocol.test.ts: 185: // eslint-disable-next-line local/code-no-any-casts 222: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts: +vscode • src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts: 47: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/search/common/search.ts: +vscode • src/vs/workbench/services/search/common/search.ts: 628: // eslint-disable-next-line local/code-no-any-casts 631: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/search/node/rawSearchService.ts: +vscode • src/vs/workbench/services/search/node/rawSearchService.ts: 438: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts: +vscode • src/vs/workbench/services/textfile/test/node/encoding/encoding.test.ts: 44: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/textMate/common/TMGrammarFactory.ts: +vscode • src/vs/workbench/services/textMate/common/TMGrammarFactory.ts: 147: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/themes/browser/fileIconThemeData.ts: +vscode • src/vs/workbench/services/themes/browser/fileIconThemeData.ts: 122: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/themes/browser/productIconThemeData.ts: +vscode • src/vs/workbench/services/themes/browser/productIconThemeData.ts: 123: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/themes/common/colorThemeData.ts: +vscode • src/vs/workbench/services/themes/common/colorThemeData.ts: 650: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts: +vscode • src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts: 67: // eslint-disable-next-line local/code-no-any-casts 74: // eslint-disable-next-line local/code-no-any-casts 102: // eslint-disable-next-line local/code-no-any-casts @@ -1406,7 +1299,7 @@ src/vs/workbench/services/views/test/browser/viewContainerModel.test.ts: 755: // eslint-disable-next-line local/code-no-any-casts 833: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts: +vscode • src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts: 25: // eslint-disable-next-line local/code-no-any-casts 27: // eslint-disable-next-line local/code-no-any-casts 335: // eslint-disable-next-line local/code-no-any-casts @@ -1416,54 +1309,54 @@ src/vs/workbench/services/views/test/browser/viewDescriptorService.test.ts: 645: // eslint-disable-next-line local/code-no-any-casts 678: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/part.test.ts: +vscode • src/vs/workbench/test/browser/part.test.ts: 133: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/window.test.ts: +vscode • src/vs/workbench/test/browser/window.test.ts: 42: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/workbenchTestServices.ts: - 304: // eslint-disable-next-line local/code-no-any-casts - 696: // eslint-disable-next-line local/code-no-any-casts - 1063: // eslint-disable-next-line local/code-no-any-casts - 1966: // eslint-disable-next-line local/code-no-any-casts - 1984: // eslint-disable-next-line local/code-no-any-casts +vscode • src/vs/workbench/test/browser/workbenchTestServices.ts: + 305: // eslint-disable-next-line local/code-no-any-casts + 698: // eslint-disable-next-line local/code-no-any-casts + 1065: // eslint-disable-next-line local/code-no-any-casts + 1968: // eslint-disable-next-line local/code-no-any-casts + 1986: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/parts/editor/editorInput.test.ts: +vscode • src/vs/workbench/test/browser/parts/editor/editorInput.test.ts: 98: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/parts/editor/editorPane.test.ts: +vscode • src/vs/workbench/test/browser/parts/editor/editorPane.test.ts: 131: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts: +vscode • src/vs/workbench/test/browser/parts/editor/resourceEditorInput.test.ts: 95: // eslint-disable-next-line local/code-no-any-casts 106: // eslint-disable-next-line local/code-no-any-casts 113: // eslint-disable-next-line local/code-no-any-casts 120: // eslint-disable-next-line local/code-no-any-casts 127: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/common/resources.test.ts: +vscode • src/vs/workbench/test/common/resources.test.ts: 51: // eslint-disable-next-line local/code-no-any-casts 59: // eslint-disable-next-line local/code-no-any-casts 72: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/common/workbenchTestServices.ts: +vscode • src/vs/workbench/test/common/workbenchTestServices.ts: 293: // eslint-disable-next-line local/code-no-any-casts -src/vs/workbench/test/electron-browser/workbenchTestServices.ts: +vscode • src/vs/workbench/test/electron-browser/workbenchTestServices.ts: 255: // eslint-disable-next-line local/code-no-any-casts -test/automation/src/code.ts: +vscode • test/automation/src/code.ts: 127: // eslint-disable-next-line local/code-no-any-casts -test/automation/src/terminal.ts: +vscode • test/automation/src/terminal.ts: 315: // eslint-disable-next-line local/code-no-any-casts -test/mcp/src/application.ts: +vscode • test/mcp/src/application.ts: 309: // eslint-disable-next-line local/code-no-any-casts -test/mcp/src/playwright.ts: +vscode • test/mcp/src/playwright.ts: 17: // eslint-disable-next-line local/code-no-any-casts -test/mcp/src/automationTools/problems.ts: +vscode • test/mcp/src/automationTools/problems.ts: 76: // eslint-disable-next-line local/code-no-any-casts diff --git a/.vscode/settings.json b/.vscode/settings.json index 9176c8db754..9fc915163ee 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { // --- Chat --- - // "inlineChat.enableV2": true, + "inlineChat.enableV2": true, "chat.tools.terminal.autoApprove": { "/^npm (test|lint|run compile)\\b/": true, "/^npx tsc\\b.*--noEmit/": true, @@ -9,7 +9,6 @@ "scripts/test-integration.bat": true, "scripts/test-integration.sh": true, }, - // --- Editor --- "editor.insertSpaces": false, "editor.experimental.asyncTokenization": true, @@ -18,7 +17,6 @@ // "editor.experimental.preferTreeSitter.typescript": true, // "editor.experimental.preferTreeSitter.regex": true, // "editor.experimental.preferTreeSitter.css": true, - // --- Language Specific --- "[plaintext]": { "files.insertFinalNewline": false @@ -38,7 +36,6 @@ "[github-issues]": { "editor.wordWrap": "on" }, - // --- Files --- "files.trimTrailingWhitespace": true, "files.insertFinalNewline": true, @@ -81,7 +78,6 @@ "build/npm/*.js": true, "build/*.js": true }, - // --- Search --- "search.exclude": { "**/node_modules": true, @@ -104,7 +100,6 @@ "build/loader.min": true, "**/*.snap": true, }, - // --- TypeScript --- "typescript.tsdk": "node_modules/typescript/lib", "typescript.preferences.importModuleSpecifier": "relative", @@ -117,7 +112,6 @@ "vscode-notebook-renderer", "src/vs/workbench/workbench.web.main.internal.ts" ], - // --- Languages --- "json.schemas": [ { @@ -134,7 +128,6 @@ } ], "css.format.spaceAroundSelectorSeparator": true, - // --- Git --- "git.ignoreLimitWarning": true, "git.branchProtection": [ @@ -152,7 +145,6 @@ "ts": "warning", "eslint": "warning" }, - // --- GitHub --- "githubPullRequests.experimental.createView": true, "githubPullRequests.assignCreated": "${user}", @@ -162,7 +154,6 @@ ], "githubPullRequests.codingAgent.enabled": true, "githubPullRequests.codingAgent.uiIntegration": true, - // --- Testing & Debugging --- "testing.autoRun.mode": "rerun", "debug.javascript.terminalOptions": { @@ -176,7 +167,6 @@ "${workspaceFolder}/extensions/*/out/**/*.js", ] }, - // --- Coverage --- "lcov.path": [ "./.build/coverage/lcov.info", @@ -191,7 +181,6 @@ } } ], - // --- Tools --- "npm.exclude": "**/extensions/**", "eslint.useFlatConfig": true, @@ -210,13 +199,10 @@ "git", "sash" ], - // --- Workbench --- // "application.experimental.rendererProfiling": true, // https://github.com/microsoft/vscode/issues/265654 - "editor.aiStats.enabled": true, // Team selfhosting on ai stats "chat.emptyState.history.enabled": true, - "github.copilot.chat.advanced.taskTools.enabled": true, "chat.promptFilesRecommendations": { "plan-fast": true, "plan-deep": true @@ -226,5 +212,7 @@ "kusto" ], "azureMcp.serverMode": "all", - "azureMcp.readOnly": true + "azureMcp.readOnly": true, + "chat.tools.terminal.outputLocation": "none", + "chat.agentSessionsViewLocation": "single-view" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 51a34c77a57..96d5015f4d1 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -279,9 +279,12 @@ "detail": "node_modules/tsec/bin/tsec -p src/tsconfig.json --noEmit" }, { - "label": "Launch Http Server", + "label": "Launch Monaco Editor Vite", "type": "shell", - "command": "node_modules/.bin/ts-node -T ./scripts/playground-server", + "command": "npm run dev", + "options": { + "cwd": "./build/monaco-editor-playground/" + }, "isBackground": true, "problemMatcher": { "pattern": { @@ -292,10 +295,7 @@ "beginsPattern": "never match", "endsPattern": ".*" } - }, - "dependsOn": [ - "Core - Build" - ] + } }, { "label": "Launch MCP Server", diff --git a/README.md b/README.md index b7a101827f6..9ef3a879555 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Many of the core components and extensions to VS Code live in their own reposito ## Bundled Extensions -VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (code completion, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` extension provides rich language support for `JSON`. +VS Code includes a set of built-in extensions located in the [extensions](extensions) folder, including grammars and snippets for many languages. Extensions that provide rich language support (inline suggestions, Go to Definition) for a language have the suffix `language-features`. For example, the `json` extension provides coloring for `JSON` and the `json-language-features` extension provides rich language support for `JSON`. ## Development Container diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index c4eacb7ba16..f47e5a6c50f 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -524,576 +524,30 @@ Title to copyright in this work will at all times remain with copyright holders. --------------------------------------------------------- -dompurify 3.1.7 - Apache 2.0 -https://github.com/cure53/DOMPurify - -DOMPurify -Copyright 2025 Dr.-Ing. Mario Heiderich, Cure53 - -DOMPurify is free software; you can redistribute it and/or modify it under the -terms of either: - -a) the Apache License Version 2.0, or -b) the Mozilla Public License Version 2.0 - ------------------------------------------------------------------------------ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ------------------------------------------------------------------------------ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. +dotenv-org/dotenv-vscode 0.26.0 - MIT License +https://github.com/dotenv-org/dotenv-vscode + +MIT License + +Copyright (c) 2022 Scott Motte + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- @@ -1546,7 +1000,7 @@ SOFTWARE. --------------------------------------------------------- -jlelong/vscode-latex-basics 1.14.0 - MIT +jlelong/vscode-latex-basics 1.15.0 - MIT https://github.com/jlelong/vscode-latex-basics Copyright (c) vscode-latex-basics authors @@ -1662,7 +1116,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO --------------------------------------------------------- -language-docker 0.0.0 - Apache-2.0 +language-docker 28.3.3 - Apache-2.0 https://github.com/moby/moby Apache License @@ -2823,7 +2277,7 @@ written authorization of the copyright holder. --------------------------------------------------------- -vscode-codicons 0.0.14 - MIT and Creative Commons Attribution 4.0 +vscode-codicons 0.0.41 - MIT and Creative Commons Attribution 4.0 https://github.com/microsoft/vscode-codicons Attribution 4.0 International diff --git a/build/.cachesalt b/build/.cachesalt index d55dde3c035..2ada6502dbd 100644 --- a/build/.cachesalt +++ b/build/.cachesalt @@ -1 +1 @@ -2025-07-23T19:44:03.051Z +2025-11-13T05:15:29.922Z diff --git a/build/.gitignore b/build/.gitignore index 61cf49cb9a1..679674617c7 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -1 +1,2 @@ *.js.map +lib/policies/policyDto.* diff --git a/build/.moduleignore b/build/.moduleignore index 3e654cfe5c3..0459b46f743 100644 --- a/build/.moduleignore +++ b/build/.moduleignore @@ -60,6 +60,8 @@ fsevents/test/** !@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm !@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm !@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +!@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +!@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm native-keymap/binding.gyp native-keymap/build/** diff --git a/build/azure-pipelines/alpine/product-build-alpine-cli.yml b/build/azure-pipelines/alpine/product-build-alpine-cli.yml index 9f3f60a6b24..8b3920b5237 100644 --- a/build/azure-pipelines/alpine/product-build-alpine-cli.yml +++ b/build/azure-pipelines/alpine/product-build-alpine-cli.yml @@ -34,6 +34,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../cli/cli-apply-patches.yml@self - script: | diff --git a/build/azure-pipelines/alpine/product-build-alpine.yml b/build/azure-pipelines/alpine/product-build-alpine.yml index c6d5ba27eda..ddf226b4306 100644 --- a/build/azure-pipelines/alpine/product-build-alpine.yml +++ b/build/azure-pipelines/alpine/product-build-alpine.yml @@ -1,4 +1,6 @@ parameters: + - name: VSCODE_QUALITY + type: string - name: VSCODE_ARCH type: string @@ -55,6 +57,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../distro/download-distro.yml@self - task: AzureKeyVault@2 diff --git a/build/azure-pipelines/common/bump-insiders-version.yml b/build/azure-pipelines/common/bump-insiders-version.yml new file mode 100644 index 00000000000..3cb9aa88128 --- /dev/null +++ b/build/azure-pipelines/common/bump-insiders-version.yml @@ -0,0 +1,23 @@ +steps: + - script: | + set -e + BUILD_NAME="$(Build.BuildNumber)" # example "20251114.34 (insider)" + VSCODE_PATCH_VERSION="$(echo $BUILD_NAME | cut -d' ' -f1 | awk -F. '{printf "%s%03d", $1, $2}')" + VSCODE_MAJOR_MINOR_VERSION="$(node -p "require('./package.json').version.replace(/\.\d+$/, '')")" + VSCODE_INSIDERS_VERSION="${VSCODE_MAJOR_MINOR_VERSION}.${VSCODE_PATCH_VERSION}" + echo "Setting Insiders version to: $VSCODE_INSIDERS_VERSION" + node -e "require('fs').writeFileSync('package.json', JSON.stringify({...require('./package.json'), version: process.argv[1]}, null, 2))" $VSCODE_INSIDERS_VERSION + displayName: Override Insiders Version + condition: and(succeeded(), not(contains(variables['Agent.OS'], 'windows'))) + + - pwsh: | + $ErrorActionPreference = "Stop" + $buildName = "$(Build.BuildNumber)" # example "20251114.34 (insider)" + $buildParts = ($buildName -split ' ')[0] -split '\.' + $patchVersion = "{0}{1:000}" -f $buildParts[0], [int]$buildParts[1] + $majorMinorVersion = node -p "require('./package.json').version.replace(/\.\d+$/, '')" + $insidersVersion = "$majorMinorVersion.$patchVersion" + Write-Host "Setting Insiders version to: $insidersVersion" + node -e "require('fs').writeFileSync('package.json', JSON.stringify({...require('./package.json'), version: process.argv[1]}, null, 2))" $insidersVersion + displayName: Override Insiders Version + condition: and(succeeded(), contains(variables['Agent.OS'], 'windows')) diff --git a/build/azure-pipelines/common/checkForArtifact.js b/build/azure-pipelines/common/checkForArtifact.js index 371ca6b9520..899448f78bd 100644 --- a/build/azure-pipelines/common/checkForArtifact.js +++ b/build/azure-pipelines/common/checkForArtifact.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const publish_1 = require("./publish"); const retry_1 = require("./retry"); async function getPipelineArtifacts() { diff --git a/build/azure-pipelines/common/codesign.js b/build/azure-pipelines/common/codesign.js index 4e82538d105..e3a8f330dcd 100644 --- a/build/azure-pipelines/common/codesign.js +++ b/build/azure-pipelines/common/codesign.js @@ -1,12 +1,12 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.printBanner = printBanner; -exports.streamProcessOutputAndCheckResult = streamProcessOutputAndCheckResult; -exports.spawnCodesignProcess = spawnCodesignProcess; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.printBanner = printBanner; +exports.streamProcessOutputAndCheckResult = streamProcessOutputAndCheckResult; +exports.spawnCodesignProcess = spawnCodesignProcess; const zx_1 = require("zx"); function printBanner(title) { title = `${title} (${new Date().toISOString()})`; diff --git a/build/azure-pipelines/common/computeBuiltInDepsCacheKey.js b/build/azure-pipelines/common/computeBuiltInDepsCacheKey.js index 8f8c833f226..10fa9087454 100644 --- a/build/azure-pipelines/common/computeBuiltInDepsCacheKey.js +++ b/build/azure-pipelines/common/computeBuiltInDepsCacheKey.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const crypto_1 = __importDefault(require("crypto")); diff --git a/build/azure-pipelines/common/computeNodeModulesCacheKey.js b/build/azure-pipelines/common/computeNodeModulesCacheKey.js index 59d570e96e6..c09c13be9d4 100644 --- a/build/azure-pipelines/common/computeNodeModulesCacheKey.js +++ b/build/azure-pipelines/common/computeNodeModulesCacheKey.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const crypto_1 = __importDefault(require("crypto")); diff --git a/build/azure-pipelines/common/createBuild.js b/build/azure-pipelines/common/createBuild.js index feb06cbe67f..c605ed6218e 100644 --- a/build/azure-pipelines/common/createBuild.js +++ b/build/azure-pipelines/common/createBuild.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const identity_1 = require("@azure/identity"); const cosmos_1 = require("@azure/cosmos"); const retry_1 = require("./retry"); diff --git a/build/azure-pipelines/common/getPublishAuthTokens.js b/build/azure-pipelines/common/getPublishAuthTokens.js index d0ead104b1c..9c22e9ad94b 100644 --- a/build/azure-pipelines/common/getPublishAuthTokens.js +++ b/build/azure-pipelines/common/getPublishAuthTokens.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.getAccessToken = getAccessToken; const msal_node_1 = require("@azure/msal-node"); diff --git a/build/azure-pipelines/common/listNodeModules.js b/build/azure-pipelines/common/listNodeModules.js index 7112ecab9cc..301b5f930b6 100644 --- a/build/azure-pipelines/common/listNodeModules.js +++ b/build/azure-pipelines/common/listNodeModules.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); if (process.argv.length !== 3) { diff --git a/build/azure-pipelines/common/publish.js b/build/azure-pipelines/common/publish.js index 1886bd4c939..49b718344a0 100644 --- a/build/azure-pipelines/common/publish.js +++ b/build/azure-pipelines/common/publish.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.e = e; exports.requestAZDOAPI = requestAZDOAPI; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const stream_1 = require("stream"); diff --git a/build/azure-pipelines/common/releaseBuild.js b/build/azure-pipelines/common/releaseBuild.js index 2eaef6de443..b74e2847cbc 100644 --- a/build/azure-pipelines/common/releaseBuild.js +++ b/build/azure-pipelines/common/releaseBuild.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const cosmos_1 = require("@azure/cosmos"); const retry_1 = require("./retry"); function getEnv(name) { diff --git a/build/azure-pipelines/common/retry.js b/build/azure-pipelines/common/retry.js index aaa90dd7006..91f60bf24b2 100644 --- a/build/azure-pipelines/common/retry.js +++ b/build/azure-pipelines/common/retry.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.retry = retry; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.retry = retry; async function retry(fn) { let lastError; for (let run = 1; run <= 10; run++) { diff --git a/build/azure-pipelines/common/sign-win32.js b/build/azure-pipelines/common/sign-win32.js index 1a6a6a97e02..f4e3f27c1f2 100644 --- a/build/azure-pipelines/common/sign-win32.js +++ b/build/azure-pipelines/common/sign-win32.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const sign_1 = require("./sign"); const path_1 = __importDefault(require("path")); (0, sign_1.main)([ diff --git a/build/azure-pipelines/common/sign.js b/build/azure-pipelines/common/sign.js index 2136e03d1f1..47c034dea1c 100644 --- a/build/azure-pipelines/common/sign.js +++ b/build/azure-pipelines/common/sign.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Temp = void 0; exports.main = main; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const child_process_1 = __importDefault(require("child_process")); const fs_1 = __importDefault(require("fs")); const crypto_1 = __importDefault(require("crypto")); diff --git a/build/azure-pipelines/common/waitForArtifacts.js b/build/azure-pipelines/common/waitForArtifacts.js index d84a34ecea7..b9ffb73962d 100644 --- a/build/azure-pipelines/common/waitForArtifacts.js +++ b/build/azure-pipelines/common/waitForArtifacts.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const publish_1 = require("../common/publish"); const retry_1 = require("../common/retry"); async function getPipelineArtifacts() { diff --git a/build/azure-pipelines/darwin/codesign.js b/build/azure-pipelines/darwin/codesign.js index d779280a7be..30a3bdc332b 100644 --- a/build/azure-pipelines/darwin/codesign.js +++ b/build/azure-pipelines/darwin/codesign.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const codesign_1 = require("../common/codesign"); const publish_1 = require("../common/publish"); async function main() { diff --git a/build/azure-pipelines/darwin/product-build-darwin-ci.yml b/build/azure-pipelines/darwin/product-build-darwin-ci.yml index 6dfc202c3ce..93ea356295d 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-ci.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-ci.yml @@ -1,4 +1,6 @@ parameters: + - name: VSCODE_QUALITY + type: string - name: VSCODE_CIBUILD type: boolean - name: VSCODE_TEST_SUITE @@ -10,9 +12,33 @@ jobs: timeoutInMinutes: 30 variables: VSCODE_ARCH: arm64 + templateContext: + outputs: + - output: pipelineArtifact + targetPath: $(Build.SourcesDirectory)/.build/crashes + artifactName: crash-dump-macos-$(VSCODE_ARCH)-${{ lower(parameters.VSCODE_TEST_SUITE) }}-$(System.JobAttempt) + displayName: Publish Crash Reports + sbomEnabled: false + isProduction: false + condition: failed() + - output: pipelineArtifact + targetPath: $(Build.SourcesDirectory)/node_modules + artifactName: node-modules-macos-$(VSCODE_ARCH)-${{ lower(parameters.VSCODE_TEST_SUITE) }}-$(System.JobAttempt) + displayName: Publish Node Modules + sbomEnabled: false + isProduction: false + condition: failed() + - output: pipelineArtifact + targetPath: $(Build.SourcesDirectory)/.build/logs + artifactName: logs-macos-$(VSCODE_ARCH)-${{ lower(parameters.VSCODE_TEST_SUITE) }}-$(System.JobAttempt) + displayName: Publish Log Files + sbomEnabled: false + isProduction: false + condition: succeededOrFailed() steps: - template: ./steps/product-build-darwin-compile.yml@self parameters: + VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }} VSCODE_ARCH: arm64 VSCODE_CIBUILD: ${{ parameters.VSCODE_CIBUILD }} ${{ if eq(parameters.VSCODE_TEST_SUITE, 'Electron') }}: diff --git a/build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml b/build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml index 3b98f9ef6c8..c26f2ad25c8 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml @@ -16,7 +16,7 @@ jobs: artifactName: vscode_cli_darwin_x64_cli displayName: Publish signed artifact with ID vscode_cli_darwin_x64_cli sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/sign/unsigned_vscode_cli_darwin_x64_cli - sbomPackageName: "VS Code macOS unsigned_vscode_cli_darwin_x64_cli CLI" + sbomPackageName: "VS Code macOS x64 CLI" sbomPackageVersion: $(Build.SourceVersion) - ${{ if eq(parameters.VSCODE_BUILD_MACOS_ARM64, true) }}: - output: pipelineArtifact @@ -24,7 +24,7 @@ jobs: artifactName: vscode_cli_darwin_arm64_cli displayName: Publish signed artifact with ID vscode_cli_darwin_arm64_cli sbomBuildDropPath: $(Build.ArtifactStagingDirectory)/sign/unsigned_vscode_cli_darwin_arm64_cli - sbomPackageName: "VS Code macOS unsigned_vscode_cli_darwin_arm64_cli CLI" + sbomPackageName: "VS Code macOS arm64 CLI" sbomPackageVersion: $(Build.SourceVersion) steps: - template: ../common/checkout.yml@self diff --git a/build/azure-pipelines/darwin/product-build-darwin-cli.yml b/build/azure-pipelines/darwin/product-build-darwin-cli.yml index 35a9b3566ce..667cf016ffd 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-cli.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-cli.yml @@ -35,6 +35,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../cli/cli-apply-patches.yml@self - task: Npm@1 diff --git a/build/azure-pipelines/darwin/product-build-darwin-universal.yml b/build/azure-pipelines/darwin/product-build-darwin-universal.yml index 23c85dc714a..a41494beb3d 100644 --- a/build/azure-pipelines/darwin/product-build-darwin-universal.yml +++ b/build/azure-pipelines/darwin/product-build-darwin-universal.yml @@ -1,3 +1,7 @@ +parameters: + - name: VSCODE_QUALITY + type: string + jobs: - job: macOSUniversal displayName: macOS (UNIVERSAL) @@ -22,6 +26,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../distro/download-distro.yml@self - task: AzureKeyVault@2 diff --git a/build/azure-pipelines/darwin/product-build-darwin.yml b/build/azure-pipelines/darwin/product-build-darwin.yml index 770a54f7925..34d70ac79d1 100644 --- a/build/azure-pipelines/darwin/product-build-darwin.yml +++ b/build/azure-pipelines/darwin/product-build-darwin.yml @@ -1,4 +1,6 @@ parameters: + - name: VSCODE_QUALITY + type: string - name: VSCODE_ARCH type: string - name: VSCODE_CIBUILD @@ -72,6 +74,7 @@ jobs: steps: - template: ./steps/product-build-darwin-compile.yml@self parameters: + VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }} VSCODE_ARCH: ${{ parameters.VSCODE_ARCH }} VSCODE_CIBUILD: ${{ parameters.VSCODE_CIBUILD }} VSCODE_RUN_ELECTRON_TESTS: ${{ parameters.VSCODE_RUN_ELECTRON_TESTS }} diff --git a/build/azure-pipelines/darwin/steps/product-build-darwin-compile.yml b/build/azure-pipelines/darwin/steps/product-build-darwin-compile.yml index bc8e962f91b..523548e469e 100644 --- a/build/azure-pipelines/darwin/steps/product-build-darwin-compile.yml +++ b/build/azure-pipelines/darwin/steps/product-build-darwin-compile.yml @@ -1,4 +1,6 @@ parameters: + - name: VSCODE_QUALITY + type: string - name: VSCODE_ARCH type: string - name: VSCODE_CIBUILD @@ -21,6 +23,9 @@ steps: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../../common/bump-insiders-version.yml@self + - template: ../../distro/download-distro.yml@self - task: AzureKeyVault@2 @@ -118,7 +123,7 @@ steps: - template: ../../common/install-builtin-extensions.yml@self - ${{ if ne(parameters.VSCODE_CIBUILD, true) }}: - - script: node build/lib/policies darwin + - script: node build/lib/policies/policyGenerator build/lib/policies/policyData.jsonc darwin displayName: Generate policy definitions retryCountOnTaskFailure: 3 diff --git a/build/azure-pipelines/distro/mixin-npm.js b/build/azure-pipelines/distro/mixin-npm.js index 40f5ee134af..87958a5d449 100644 --- a/build/azure-pipelines/distro/mixin-npm.js +++ b/build/azure-pipelines/distro/mixin-npm.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const { dirs } = require('../../npm/dirs'); diff --git a/build/azure-pipelines/distro/mixin-quality.js b/build/azure-pipelines/distro/mixin-quality.js index 08aee7c89bd..335f63ca1fc 100644 --- a/build/azure-pipelines/distro/mixin-quality.js +++ b/build/azure-pipelines/distro/mixin-quality.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); function log(...args) { diff --git a/build/azure-pipelines/linux/codesign.js b/build/azure-pipelines/linux/codesign.js index 93ec2434ea8..98b97db5666 100644 --- a/build/azure-pipelines/linux/codesign.js +++ b/build/azure-pipelines/linux/codesign.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const codesign_1 = require("../common/codesign"); const publish_1 = require("../common/publish"); async function main() { diff --git a/build/azure-pipelines/linux/product-build-linux-cli.yml b/build/azure-pipelines/linux/product-build-linux-cli.yml index 9052a29e18e..548bc04acb6 100644 --- a/build/azure-pipelines/linux/product-build-linux-cli.yml +++ b/build/azure-pipelines/linux/product-build-linux-cli.yml @@ -34,6 +34,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../cli/cli-apply-patches.yml@self - task: Npm@1 diff --git a/build/azure-pipelines/linux/product-build-linux-node-modules.yml b/build/azure-pipelines/linux/product-build-linux-node-modules.yml index 3867a81a55f..e3fd5c35173 100644 --- a/build/azure-pipelines/linux/product-build-linux-node-modules.yml +++ b/build/azure-pipelines/linux/product-build-linux-node-modules.yml @@ -116,6 +116,10 @@ jobs: source ./build/azure-pipelines/linux/setup-env.sh + # Run preinstall script before root dependencies are installed + # so that v8 headers are patched correctly for native modules. + node build/npm/preinstall.js + for i in {1..5}; do # try 5 times npm ci && break if [ $i -eq 5 ]; then diff --git a/build/azure-pipelines/linux/setup-env.sh b/build/azure-pipelines/linux/setup-env.sh index 8bd2af238c4..b7804545b6b 100755 --- a/build/azure-pipelines/linux/setup-env.sh +++ b/build/azure-pipelines/linux/setup-env.sh @@ -25,7 +25,7 @@ fi if [ "$npm_config_arch" == "x64" ]; then # Download clang based on chromium revision used by vscode - curl -s https://raw.githubusercontent.com/chromium/chromium/138.0.7204.251/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux + curl -s https://raw.githubusercontent.com/chromium/chromium/142.0.7444.162/tools/clang/scripts/update.py | python - --output-dir=$PWD/.build/CR_Clang --host-os=linux # Download libcxx headers and objects from upstream electron releases DEBUG=libcxx-fetcher \ @@ -37,9 +37,9 @@ if [ "$npm_config_arch" == "x64" ]; then # Set compiler toolchain # Flags for the client build are based on - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/138.0.7204.251:build/config/arm.gni - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/138.0.7204.251:build/config/compiler/BUILD.gn - # https://source.chromium.org/chromium/chromium/src/+/refs/tags/138.0.7204.251:build/config/c++/BUILD.gn + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/142.0.7444.162:build/config/arm.gni + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/142.0.7444.162:build/config/compiler/BUILD.gn + # https://source.chromium.org/chromium/chromium/src/+/refs/tags/142.0.7444.162:build/config/c++/BUILD.gn export CC="$PWD/.build/CR_Clang/bin/clang --gcc-toolchain=$VSCODE_CLIENT_SYSROOT_DIR/x86_64-linux-gnu" export CXX="$PWD/.build/CR_Clang/bin/clang++ --gcc-toolchain=$VSCODE_CLIENT_SYSROOT_DIR/x86_64-linux-gnu" export CXXFLAGS="-nostdinc++ -D__NO_INLINE__ -DSPDLOG_USE_STD_FORMAT -I$PWD/.build/libcxx_headers -isystem$PWD/.build/libcxx_headers/include -isystem$PWD/.build/libcxxabi_headers/include -fPIC -flto=thin -fsplit-lto-unit -D_LIBCPP_ABI_NAMESPACE=Cr -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE --sysroot=$VSCODE_CLIENT_SYSROOT_DIR/x86_64-linux-gnu/x86_64-linux-gnu/sysroot" diff --git a/build/azure-pipelines/linux/steps/product-build-linux-compile.yml b/build/azure-pipelines/linux/steps/product-build-linux-compile.yml index 73f3a9de3ed..c0d65917d33 100644 --- a/build/azure-pipelines/linux/steps/product-build-linux-compile.yml +++ b/build/azure-pipelines/linux/steps/product-build-linux-compile.yml @@ -26,6 +26,9 @@ steps: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../../common/bump-insiders-version.yml@self + - template: ../../distro/download-distro.yml@self - task: AzureKeyVault@2 @@ -132,6 +135,10 @@ steps: source ./build/azure-pipelines/linux/setup-env.sh + # Run preinstall script before root dependencies are installed + # so that v8 headers are patched correctly for native modules. + node build/npm/preinstall.js + for i in {1..5}; do # try 5 times npm ci && break if [ $i -eq 5 ]; then @@ -166,6 +173,11 @@ steps: - template: ../../common/install-builtin-extensions.yml@self + - ${{ if ne(parameters.VSCODE_CIBUILD, true) }}: + - script: node build/lib/policies/policyGenerator build/lib/policies/policyData.jsonc linux + displayName: Generate policy definitions + retryCountOnTaskFailure: 3 + - script: | set -e npm run gulp vscode-linux-$(VSCODE_ARCH)-min-ci @@ -396,4 +408,11 @@ steps: mkdir -p $(Build.ArtifactStagingDirectory)/out/snap mv $(SNAP_PATH) $(Build.ArtifactStagingDirectory)/out/snap/$(SNAP_PACKAGE_NAME) fi + + # SBOM generation uses hard links which are not supported by the Linux kernel + # for files that have the SUID bit set, so we need to remove the SUID bit from + # the chrome-sandbox file. + sudo ls -l $(Agent.BuildDirectory)/VSCode-linux-$(VSCODE_ARCH)/chrome-sandbox + sudo chmod u-s $(Agent.BuildDirectory)/VSCode-linux-$(VSCODE_ARCH)/chrome-sandbox + sudo ls -l $(Agent.BuildDirectory)/VSCode-linux-$(VSCODE_ARCH)/chrome-sandbox displayName: Move artifacts to out directory diff --git a/build/azure-pipelines/product-build.yml b/build/azure-pipelines/product-build.yml index e9c8f74e659..02acdef21e8 100644 --- a/build/azure-pipelines/product-build.yml +++ b/build/azure-pipelines/product-build.yml @@ -192,6 +192,8 @@ extends: - stage: Compile jobs: - template: build/azure-pipelines/product-compile.yml@self + parameters: + VSCODE_QUALITY: ${{ parameters.VSCODE_QUALITY }} - ${{ if or(eq(parameters.VSCODE_BUILD_LINUX, true),eq(parameters.VSCODE_BUILD_LINUX_ARMHF, true),eq(parameters.VSCODE_BUILD_LINUX_ARM64, true),eq(parameters.VSCODE_BUILD_ALPINE, true),eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true),eq(parameters.VSCODE_BUILD_MACOS, true),eq(parameters.VSCODE_BUILD_MACOS_ARM64, true),eq(parameters.VSCODE_BUILD_WIN32, true),eq(parameters.VSCODE_BUILD_WIN32_ARM64, true)) }}: - stage: CompileCLI @@ -409,10 +411,12 @@ extends: - ${{ if eq(parameters.VSCODE_BUILD_ALPINE, true) }}: - template: build/azure-pipelines/alpine/product-build-alpine.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_ARCH: x64 - ${{ if eq(parameters.VSCODE_BUILD_ALPINE_ARM64, true) }}: - template: build/azure-pipelines/alpine/product-build-alpine.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_ARCH: arm64 - ${{ if and(eq(parameters.VSCODE_COMPILE_ONLY, false), eq(variables['VSCODE_BUILD_STAGE_MACOS'], true)) }}: @@ -430,26 +434,31 @@ extends: - ${{ if eq(variables['VSCODE_CIBUILD'], true) }}: - template: build/azure-pipelines/darwin/product-build-darwin-ci.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }} VSCODE_TEST_SUITE: Electron - template: build/azure-pipelines/darwin/product-build-darwin-ci.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }} VSCODE_TEST_SUITE: Browser - template: build/azure-pipelines/darwin/product-build-darwin-ci.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }} VSCODE_TEST_SUITE: Remote - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS, true)) }}: - template: build/azure-pipelines/darwin/product-build-darwin.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_ARCH: x64 VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }} - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true)) }}: - template: build/azure-pipelines/darwin/product-build-darwin.yml@self parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} VSCODE_ARCH: arm64 VSCODE_CIBUILD: ${{ variables.VSCODE_CIBUILD }} VSCODE_RUN_ELECTRON_TESTS: ${{ eq(parameters.VSCODE_STEP_ON_IT, false) }} @@ -458,6 +467,8 @@ extends: - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), eq(variables['VSCODE_BUILD_MACOS_UNIVERSAL'], true)) }}: - template: build/azure-pipelines/darwin/product-build-darwin-universal.yml@self + parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} - ${{ if and(eq(variables['VSCODE_CIBUILD'], false), or(eq(parameters.VSCODE_BUILD_MACOS, true), eq(parameters.VSCODE_BUILD_MACOS_ARM64, true))) }}: - template: build/azure-pipelines/darwin/product-build-darwin-cli-sign.yml@self @@ -471,6 +482,8 @@ extends: - Compile jobs: - template: build/azure-pipelines/web/product-build-web.yml@self + parameters: + VSCODE_QUALITY: ${{ variables.VSCODE_QUALITY }} - ${{ if eq(variables['VSCODE_PUBLISH'], 'true') }}: - stage: Publish diff --git a/build/azure-pipelines/product-compile.yml b/build/azure-pipelines/product-compile.yml index c02c4d20dbd..c3d705fc077 100644 --- a/build/azure-pipelines/product-compile.yml +++ b/build/azure-pipelines/product-compile.yml @@ -1,3 +1,7 @@ +parameters: + - name: VSCODE_QUALITY + type: string + jobs: - job: Compile timeoutInMinutes: 60 @@ -20,6 +24,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ./common/bump-insiders-version.yml@self + - template: ./distro/download-distro.yml@self - task: AzureKeyVault@2 @@ -98,7 +105,7 @@ jobs: - template: common/install-builtin-extensions.yml@self - - script: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check define-class-fields-check vscode-dts-compile-check tsec-compile-check + - script: npm exec -- npm-run-all -lp core-ci extensions-ci hygiene eslint valid-layers-check define-class-fields-check vscode-dts-compile-check tsec-compile-check test-build-scripts env: GITHUB_TOKEN: "$(github-distro-mixin-password)" displayName: Compile & Hygiene diff --git a/build/azure-pipelines/product-publish.yml b/build/azure-pipelines/product-publish.yml index aa0727a1988..89cf3fabc0d 100644 --- a/build/azure-pipelines/product-publish.yml +++ b/build/azure-pipelines/product-publish.yml @@ -31,6 +31,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ./common/bump-insiders-version.yml@self + - task: AzureKeyVault@2 displayName: "Azure Key Vault: Get Secrets" inputs: diff --git a/build/azure-pipelines/publish-types/check-version.js b/build/azure-pipelines/publish-types/check-version.js index e9564a469d1..5bd80a69bbf 100644 --- a/build/azure-pipelines/publish-types/check-version.js +++ b/build/azure-pipelines/publish-types/check-version.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const child_process_1 = __importDefault(require("child_process")); let tag = ''; try { diff --git a/build/azure-pipelines/publish-types/update-types.js b/build/azure-pipelines/publish-types/update-types.js index a528a6027d9..29f9bfcf66e 100644 --- a/build/azure-pipelines/publish-types/update-types.js +++ b/build/azure-pipelines/publish-types/update-types.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const child_process_1 = __importDefault(require("child_process")); const path_1 = __importDefault(require("path")); diff --git a/build/azure-pipelines/upload-cdn.js b/build/azure-pipelines/upload-cdn.js index 603fbdbf95f..14108297ed4 100644 --- a/build/azure-pipelines/upload-cdn.js +++ b/build/azure-pipelines/upload-cdn.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const event_stream_1 = __importDefault(require("event-stream")); const vinyl_1 = __importDefault(require("vinyl")); const vinyl_fs_1 = __importDefault(require("vinyl-fs")); @@ -15,7 +15,7 @@ const gulp_gzip_1 = __importDefault(require("gulp-gzip")); const mime_1 = __importDefault(require("mime")); const identity_1 = require("@azure/identity"); const util_1 = require("../lib/util"); -const azure = require('gulp-azure-storage'); +const gulp_azure_storage_1 = __importDefault(require("gulp-azure-storage")); const commit = process.env['BUILD_SOURCEVERSION']; const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); mime_1.default.define({ @@ -91,10 +91,10 @@ async function main() { const compressed = all .pipe((0, gulp_filter_1.default)(f => MimeTypesToCompress.has(mime_1.default.lookup(f.path)))) .pipe((0, gulp_gzip_1.default)({ append: false })) - .pipe(azure.upload(options(true))); + .pipe(gulp_azure_storage_1.default.upload(options(true))); const uncompressed = all .pipe((0, gulp_filter_1.default)(f => !MimeTypesToCompress.has(mime_1.default.lookup(f.path)))) - .pipe(azure.upload(options(false))); + .pipe(gulp_azure_storage_1.default.upload(options(false))); const out = event_stream_1.default.merge(compressed, uncompressed) .pipe(event_stream_1.default.through(function (f) { console.log('Uploaded:', f.relative); @@ -110,7 +110,7 @@ async function main() { }); const filesOut = event_stream_1.default.readArray([listing]) .pipe((0, gulp_gzip_1.default)({ append: false })) - .pipe(azure.upload(options(true))); + .pipe(gulp_azure_storage_1.default.upload(options(true))); console.log(`Uploading: files.txt (${files.length} files)`); // debug await wait(filesOut); } diff --git a/build/azure-pipelines/upload-cdn.ts b/build/azure-pipelines/upload-cdn.ts index ead60d4b6cc..d589c423522 100644 --- a/build/azure-pipelines/upload-cdn.ts +++ b/build/azure-pipelines/upload-cdn.ts @@ -11,7 +11,7 @@ import gzip from 'gulp-gzip'; import mime from 'mime'; import { ClientAssertionCredential } from '@azure/identity'; import { VinylStat } from '../lib/util'; -const azure = require('gulp-azure-storage'); +import azure from 'gulp-azure-storage'; const commit = process.env['BUILD_SOURCEVERSION']; const credential = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); diff --git a/build/azure-pipelines/upload-nlsmetadata.js b/build/azure-pipelines/upload-nlsmetadata.js index 18ff71b7191..65386797fc9 100644 --- a/build/azure-pipelines/upload-nlsmetadata.js +++ b/build/azure-pipelines/upload-nlsmetadata.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const event_stream_1 = __importDefault(require("event-stream")); const vinyl_fs_1 = __importDefault(require("vinyl-fs")); const gulp_merge_json_1 = __importDefault(require("gulp-merge-json")); @@ -14,7 +14,7 @@ const gulp_gzip_1 = __importDefault(require("gulp-gzip")); const identity_1 = require("@azure/identity"); const path = require("path"); const fs_1 = require("fs"); -const azure = require('gulp-azure-storage'); +const gulp_azure_storage_1 = __importDefault(require("gulp-azure-storage")); const commit = process.env['BUILD_SOURCEVERSION']; const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); function main() { @@ -106,7 +106,7 @@ function main() { console.log(`##vso[artifact.upload containerfolder=nlsmetadata;artifactname=${data.basename}]${data.path}`); this.emit('data', data); })) - .pipe(azure.upload({ + .pipe(gulp_azure_storage_1.default.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, container: '$web', diff --git a/build/azure-pipelines/upload-nlsmetadata.ts b/build/azure-pipelines/upload-nlsmetadata.ts index 468a9341a7b..f1388556249 100644 --- a/build/azure-pipelines/upload-nlsmetadata.ts +++ b/build/azure-pipelines/upload-nlsmetadata.ts @@ -11,7 +11,7 @@ import gzip from 'gulp-gzip'; import { ClientAssertionCredential } from '@azure/identity'; import path = require('path'); import { readFileSync } from 'fs'; -const azure = require('gulp-azure-storage'); +import azure from 'gulp-azure-storage'; const commit = process.env['BUILD_SOURCEVERSION']; const credential = new ClientAssertionCredential(process.env['AZURE_TENANT_ID']!, process.env['AZURE_CLIENT_ID']!, () => Promise.resolve(process.env['AZURE_ID_TOKEN']!)); diff --git a/build/azure-pipelines/upload-sourcemaps.js b/build/azure-pipelines/upload-sourcemaps.js index ecb8679d684..525943c2c3d 100644 --- a/build/azure-pipelines/upload-sourcemaps.js +++ b/build/azure-pipelines/upload-sourcemaps.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -36,17 +40,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const path_1 = __importDefault(require("path")); const event_stream_1 = __importDefault(require("event-stream")); const vinyl_fs_1 = __importDefault(require("vinyl-fs")); const util = __importStar(require("../lib/util")); const dependencies_1 = require("../lib/dependencies"); const identity_1 = require("@azure/identity"); -const azure = require('gulp-azure-storage'); +const gulp_azure_storage_1 = __importDefault(require("gulp-azure-storage")); const root = path_1.default.dirname(path_1.default.dirname(__dirname)); const commit = process.env['BUILD_SOURCEVERSION']; const credential = new identity_1.ClientAssertionCredential(process.env['AZURE_TENANT_ID'], process.env['AZURE_CLIENT_ID'], () => Promise.resolve(process.env['AZURE_ID_TOKEN'])); @@ -84,7 +84,7 @@ function main() { console.log('Uploading Sourcemap', data.relative); // debug this.emit('data', data); })) - .pipe(azure.upload({ + .pipe(gulp_azure_storage_1.default.upload({ account: process.env.AZURE_STORAGE_ACCOUNT, credential, container: '$web', diff --git a/build/azure-pipelines/upload-sourcemaps.ts b/build/azure-pipelines/upload-sourcemaps.ts index 612a57c9da2..b63d213d559 100644 --- a/build/azure-pipelines/upload-sourcemaps.ts +++ b/build/azure-pipelines/upload-sourcemaps.ts @@ -11,7 +11,7 @@ import * as util from '../lib/util'; import { getProductionDependencies } from '../lib/dependencies'; import { ClientAssertionCredential } from '@azure/identity'; import Stream from 'stream'; -const azure = require('gulp-azure-storage'); +import azure from 'gulp-azure-storage'; const root = path.dirname(path.dirname(__dirname)); const commit = process.env['BUILD_SOURCEVERSION']; diff --git a/build/azure-pipelines/web/product-build-web.yml b/build/azure-pipelines/web/product-build-web.yml index b223a63f9c6..61ba3263107 100644 --- a/build/azure-pipelines/web/product-build-web.yml +++ b/build/azure-pipelines/web/product-build-web.yml @@ -1,3 +1,7 @@ +parameters: + - name: VSCODE_QUALITY + type: string + jobs: - job: Web displayName: Web @@ -14,7 +18,7 @@ jobs: artifactName: vscode_web_linux_standalone_archive-unsigned displayName: Publish web archive sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-web - sbomPackageName: "VS Code Web" + sbomPackageName: "VS Code Linux x64 Web (Standalone)" sbomPackageVersion: $(Build.SourceVersion) steps: - template: ../common/checkout.yml@self @@ -24,6 +28,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../distro/download-distro.yml@self - task: AzureKeyVault@2 diff --git a/build/azure-pipelines/win32/codesign.js b/build/azure-pipelines/win32/codesign.js index cee33ae3208..630f9a64ba1 100644 --- a/build/azure-pipelines/win32/codesign.js +++ b/build/azure-pipelines/win32/codesign.js @@ -1,9 +1,9 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); const zx_1 = require("zx"); const codesign_1 = require("../common/codesign"); const publish_1 = require("../common/publish"); diff --git a/build/azure-pipelines/win32/product-build-win32-cli.yml b/build/azure-pipelines/win32/product-build-win32-cli.yml index 5dd69c3b50d..26ab6ee247b 100644 --- a/build/azure-pipelines/win32/product-build-win32-cli.yml +++ b/build/azure-pipelines/win32/product-build-win32-cli.yml @@ -34,6 +34,9 @@ jobs: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../common/bump-insiders-version.yml@self + - template: ../cli/cli-apply-patches.yml@self - task: Npm@1 diff --git a/build/azure-pipelines/win32/product-build-win32.yml b/build/azure-pipelines/win32/product-build-win32.yml index b60e66eaae4..3a91d3cdd97 100644 --- a/build/azure-pipelines/win32/product-build-win32.yml +++ b/build/azure-pipelines/win32/product-build-win32.yml @@ -81,6 +81,9 @@ jobs: sbomBuildDropPath: $(Agent.BuildDirectory)/vscode-server-win32-$(VSCODE_ARCH)-web sbomPackageName: "VS Code Windows $(VSCODE_ARCH) Web" sbomPackageVersion: $(Build.SourceVersion) + sdl: + suppression: + suppressionFile: $(Build.SourcesDirectory)\.config\guardian\.gdnsuppress steps: - template: ./steps/product-build-win32-compile.yml@self parameters: diff --git a/build/azure-pipelines/win32/steps/product-build-win32-compile.yml b/build/azure-pipelines/win32/steps/product-build-win32-compile.yml index 072d64ec2d9..44a1f060aaa 100644 --- a/build/azure-pipelines/win32/steps/product-build-win32-compile.yml +++ b/build/azure-pipelines/win32/steps/product-build-win32-compile.yml @@ -23,6 +23,9 @@ steps: versionSource: fromFile versionFilePath: .nvmrc + - ${{ if eq(parameters.VSCODE_QUALITY, 'insider') }}: + - template: ../../common/bump-insiders-version.yml@self + - task: UsePythonVersion@0 inputs: versionSpec: "3.x" @@ -120,7 +123,7 @@ steps: - template: ../../common/install-builtin-extensions.yml@self - ${{ if ne(parameters.VSCODE_CIBUILD, true) }}: - - powershell: node build\lib\policies win32 + - powershell: node build\lib\policies\policyGenerator build\lib\policies\policyData.jsonc win32 displayName: Generate Group Policy definitions retryCountOnTaskFailure: 3 diff --git a/build/checker/layersChecker.js b/build/checker/layersChecker.js index a59901d8a57..ae84e8ffeb9 100644 --- a/build/checker/layersChecker.js +++ b/build/checker/layersChecker.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const typescript_1 = __importDefault(require("typescript")); const fs_1 = require("fs"); const path_1 = require("path"); diff --git a/build/checker/tsconfig.browser.json b/build/checker/tsconfig.browser.json index 67868ef7575..91cb9fe0e70 100644 --- a/build/checker/tsconfig.browser.json +++ b/build/checker/tsconfig.browser.json @@ -2,7 +2,7 @@ "extends": "../../src/tsconfig.base.json", "compilerOptions": { "lib": [ - "ES2022", + "ES2024", "DOM", "DOM.Iterable" ], diff --git a/build/checker/tsconfig.node.json b/build/checker/tsconfig.node.json index 2e483136e08..4fe5c10623d 100644 --- a/build/checker/tsconfig.node.json +++ b/build/checker/tsconfig.node.json @@ -2,7 +2,7 @@ "extends": "../../src/tsconfig.base.json", "compilerOptions": { "lib": [ - "ES2022" + "ES2024" ], "types": [ "node" diff --git a/build/checker/tsconfig.worker.json b/build/checker/tsconfig.worker.json index ebb919bf0f2..39d3a584532 100644 --- a/build/checker/tsconfig.worker.json +++ b/build/checker/tsconfig.worker.json @@ -2,7 +2,7 @@ "extends": "../../src/tsconfig.base.json", "compilerOptions": { "lib": [ - "ES2022", + "ES2024", "WebWorker", "Webworker.Iterable", "WebWorker.AsyncIterable" diff --git a/build/checksums/electron.txt b/build/checksums/electron.txt index a65112f108e..ebd0384846c 100644 --- a/build/checksums/electron.txt +++ b/build/checksums/electron.txt @@ -1,75 +1,75 @@ -ea1b52ec0af04037b419897585ebb2e81f65ccd79dd8f331e26578d042c01a2f *chromedriver-v37.6.0-darwin-arm64.zip -667a9067a774a5ada82a44bc310a23657dc2942067732b6c2879ae0042e2faf2 *chromedriver-v37.6.0-darwin-x64.zip -5c588569bbbca2bcef0881ea877d70dafcf7955e0d19765797f60e2c4d228c8a *chromedriver-v37.6.0-linux-arm64.zip -87a781e82f4fc530820311edc059eafe30e9cec673704c8e73ebf452c5382bc6 *chromedriver-v37.6.0-linux-armv7l.zip -e1c04c3826e506765e90d95738d1cf0ecbb3a798f2f3a7bf17d0cc03fe0be1fe *chromedriver-v37.6.0-linux-x64.zip -53e9d63c01eb018f5be1ebf6d2cba92c25b3097f1500f3d7fe1703447f7f3452 *chromedriver-v37.6.0-mas-arm64.zip -d556851da7ba16ae4b0a39e0c74a1295dfc42875a485d01483babd8e180e2f82 *chromedriver-v37.6.0-mas-x64.zip -0687f18325df7ce6845491fda61b8b4c40d0cc268c8fa54448591461cfd7f7b8 *chromedriver-v37.6.0-win32-arm64.zip -e7a5e4ce6bd6f6d34bcf773ac0796924582ec0c3b37c9442d874b5617b38be69 *chromedriver-v37.6.0-win32-ia32.zip -a1491a67dd7b2a1300283ac862e9ff97adc9db279c3dad0e843e441758fd7e2a *chromedriver-v37.6.0-win32-x64.zip -56e01ec4745a98b0cec8fb9aad00396072127883e76781d912bf3410c1da4cfc *electron-api.json -2f71423b81668b01a1e823593696800f22c262170e89372a3a00388f288cc914 *electron-v37.6.0-darwin-arm64-dsym-snapshot.zip -d632b133b742b7a9c94baa6577cbf528e6cd3a92afbf21245b56d37c580b062b *electron-v37.6.0-darwin-arm64-dsym.zip -a4f47ecea85e134d1b305b7286ef0ada0de714e2874c267169d9d3eafb2c51d2 *electron-v37.6.0-darwin-arm64-symbols.zip -82869e916e74cb763c03fefb5fcee1fc99536e597716d4f3a9c716f9c37effab *electron-v37.6.0-darwin-arm64.zip -5314570f28ca70a6aead23b1902da9a0cb120abb364e3bed12605f36571a4ce2 *electron-v37.6.0-darwin-x64-dsym-snapshot.zip -5689342a29ab4b9fa1b3f5b153d3eb9e7dbe12a10c07a7877b368b3ffbe82004 *electron-v37.6.0-darwin-x64-dsym.zip -978cf0fd18f2b2518e44c35cfd63d6268d28aadeff759212fe4d9b2bf3efa3b9 *electron-v37.6.0-darwin-x64-symbols.zip -258a104f781c50939ec6b45177a6f810da646ade15567a09cf9d14ec81b82cb2 *electron-v37.6.0-darwin-x64.zip -f2053132ca60ec546fccfbf0265d54b1405ad28156fda17c621a461b0c1be2e0 *electron-v37.6.0-linux-arm64-debug.zip -11c2461e956e525ab36784db0e2817fe35ff53a1154285f7ea2827df6f2954d8 *electron-v37.6.0-linux-arm64-symbols.zip -7c76a5147a9870b8bcbd859278148e1e326f98ea6a5dcb3ac2707d39bd22b2d5 *electron-v37.6.0-linux-arm64.zip -92f444a60f677a41d30afaadc0c8e754888ca4829a859b14459c9109b68e1fb0 *electron-v37.6.0-linux-armv7l-debug.zip -2ef9ee6afd566654950f06f8c8f32186133eadd015d74f0074d4c5a7d93b8be2 *electron-v37.6.0-linux-armv7l-symbols.zip -0d4a49b5f462972173daf6e919664cc04cad7a7d2a96b074cb181ea07bb0cd74 *electron-v37.6.0-linux-armv7l.zip -4b9dee173eddf90b2969b74ed86c6a81cd97c208e35b3db115da1f6534e31308 *electron-v37.6.0-linux-x64-debug.zip -cefdb0e96f980fed3ae22c62a204ccb6754311959ba2867a759887c27cbf7f09 *electron-v37.6.0-linux-x64-symbols.zip -02e644d75392a1ea8991106bc77e1db243ee1fc0c23107dc3b253ed545dd4c66 *electron-v37.6.0-linux-x64.zip -3fbfb12b83eb678a84a102808a338dc7d828362a012be0f315ccbfee098aeb1c *electron-v37.6.0-mas-arm64-dsym-snapshot.zip -ce6f18733a966fc9f2ab8e3ca0c9ee15f8ca1abd7f219990fe4795ff9e4946d7 *electron-v37.6.0-mas-arm64-dsym.zip -293ac1f466ec8d6888df1702e2ba2d2f1414068259af5ece7a0170044b2d2de3 *electron-v37.6.0-mas-arm64-symbols.zip -ecc1efd59bd23ae508cf0595594c8dda225d0e6eeb2df7f90b56cdb763aeb2c1 *electron-v37.6.0-mas-arm64.zip -c378220d65f5cf4b8ecd8823a4d8499111c77d2377b6bcb7d0727c567254ec06 *electron-v37.6.0-mas-x64-dsym-snapshot.zip -22c718ab643ff134262a3308104814f9789307f43ec045e6a132dfb57d7bc364 *electron-v37.6.0-mas-x64-dsym.zip -022d38652a15f44b13c3ee6a0691650f3dc7d0fd6827f79877de3f8bbd3bd68c *electron-v37.6.0-mas-x64-symbols.zip -258c44b8bae66e714cb26b11451f97e2678e9d0b6536cac19d74d49544f5805f *electron-v37.6.0-mas-x64.zip -c4927ece20680a6d2940ce5acee0c051abb96c8ca09c071bced548fbbfa9b3b1 *electron-v37.6.0-win32-arm64-pdb.zip -469335cb89bca0fcaefd33922f9db39f283b8a6009e84dadb8bb98de94e4c67c *electron-v37.6.0-win32-arm64-symbols.zip -74e88ea46bb62f4d8698b1058963568b8ccd9debbdd5d755dfdf4303874446d5 *electron-v37.6.0-win32-arm64-toolchain-profile.zip -1d09e49e246fc36052e4eb55013a907af6d1754521924c8113ad621eca2e8bd3 *electron-v37.6.0-win32-arm64.zip -bce61cf19e53390654bd2a57706462d40ba7da4c83750cfe2242279961bffbf7 *electron-v37.6.0-win32-ia32-pdb.zip -9c85d0eff9eb1bfbb3ef7479fbe709204f594cbdefa745df68e7491013f20c6f *electron-v37.6.0-win32-ia32-symbols.zip -74e88ea46bb62f4d8698b1058963568b8ccd9debbdd5d755dfdf4303874446d5 *electron-v37.6.0-win32-ia32-toolchain-profile.zip -62ba4c8ba5734fbd0371ec5d04481f498d5b202024a3083fe428d0df55f88ff4 *electron-v37.6.0-win32-ia32.zip -6fe8d1e8f40a46b84ecac8e53e0607e9b43e2afe24cac37a7912a3413b210847 *electron-v37.6.0-win32-x64-pdb.zip -f3fe1e92a4f6977d24848be13d15eafc1558f21230387c66c0b5f41051ba2049 *electron-v37.6.0-win32-x64-symbols.zip -74e88ea46bb62f4d8698b1058963568b8ccd9debbdd5d755dfdf4303874446d5 *electron-v37.6.0-win32-x64-toolchain-profile.zip -4412a99d07f32a79de16e5a44739062f5fe27efd68cd9ad95122c560f33704b8 *electron-v37.6.0-win32-x64.zip -0bcd0d5f201de6d8903d2860ede68911c834be99d24fb6482aeee492d2b5265a *electron.d.ts -39d5a5663e491f4e5e4a60ded8d6361a8f4d905a220aa681adfabac1fa90d06f *ffmpeg-v37.6.0-darwin-arm64.zip -210e095fc7c629b411caf90f00958aa004ac33f2f6dd1291780a670c46f028cf *ffmpeg-v37.6.0-darwin-x64.zip -f0792bdd28ac2231e2d10bdb89da0221e9b15149a4761448e6bfd50ba8e76895 *ffmpeg-v37.6.0-linux-arm64.zip -5bd4adf23596c09bbb671952b73427f6701a7e9aee647979925e9cc4ff973045 *ffmpeg-v37.6.0-linux-armv7l.zip -561a7685536c133d2072e2e2b5a64ca3897bb8c71624158a6fe8e07cae9116c9 *ffmpeg-v37.6.0-linux-x64.zip -39d5a5663e491f4e5e4a60ded8d6361a8f4d905a220aa681adfabac1fa90d06f *ffmpeg-v37.6.0-mas-arm64.zip -210e095fc7c629b411caf90f00958aa004ac33f2f6dd1291780a670c46f028cf *ffmpeg-v37.6.0-mas-x64.zip -e6e0b42b1afd3bed31fdeda0d5e9e3ae71c7a5dd950ef7f137ec22b8eb53f372 *ffmpeg-v37.6.0-win32-arm64.zip -dc5509c12b30983c200a1a7059673ce093a9bdf38197e3ddcd9a2c33591e1811 *ffmpeg-v37.6.0-win32-ia32.zip -b60372e7431ad40292a77ffc75f011e06c528589f20e6596de9c9090356d1699 *ffmpeg-v37.6.0-win32-x64.zip -4b80ff3d9e48d7b00cdf8265a6a8d7b1a14ed403ca2c7266c1e755fbbbbf4671 *hunspell_dictionaries.zip -00c3f8aff441d6a4b12d076055760895760dbc4f42708358d71f0a2e6937a509 *libcxx-objects-v37.6.0-linux-arm64.zip -71cd9bc71ef32d25aa50ed2aec8859ae6213b4e10c2e7d9cd6174b4221bd023b *libcxx-objects-v37.6.0-linux-armv7l.zip -95bf4671c353ea80e6c6d579e2513200329ba449761ba02dfe3f93ee213cced2 *libcxx-objects-v37.6.0-linux-x64.zip -421b28d575bc966cb17cd3747d9c6a62050648792ec15e5bf8f1eb46f0931e19 *libcxx_headers.zip -006ccb83761a3bf5791d165bc9795e4de3308c65df646b4cbcaa61025fe7a6c5 *libcxxabi_headers.zip -9a50ca41df5b99d2c0557ee5b1db6657baca398f557109955f54433ed64aa7e1 *mksnapshot-v37.6.0-darwin-arm64.zip -6544c9c5007fc9dd5ee3480aa1b5b71a8a5797e492c4f6ef69c7f59b0ee3fc00 *mksnapshot-v37.6.0-darwin-x64.zip -ff7c115df6caf20383765ec4b236c5220e7a32d842ddaabd209cbe063b018b0f *mksnapshot-v37.6.0-linux-arm64-x64.zip -3a4b458aaed19854ff69151bdadd542a398ac670fed4be0e59402e24a461faf4 *mksnapshot-v37.6.0-linux-armv7l-x64.zip -c46f5fe87bc799a5661c0926d4572ad488805210be85a7e1cb4c6e2068697628 *mksnapshot-v37.6.0-linux-x64.zip -5d5e202f46f9654429b8e175bcba4ef4174dd2c3ab8a27a63ea9b0bcaec0c486 *mksnapshot-v37.6.0-mas-arm64.zip -31a5dd8f72d8910335e266eea2cd478e4d45fe16de2118368466401db8eca6f1 *mksnapshot-v37.6.0-mas-x64.zip -a4ea3aa43b1c0efbf27c3a4a2ea9269f12d855fd290d3834c0f7de34e18c4ab1 *mksnapshot-v37.6.0-win32-arm64-x64.zip -ab0f8bcd2af4fbe461c23fa06cbcd9f62187ba080a9f3c56f24c40f3f5ba1f59 *mksnapshot-v37.6.0-win32-ia32.zip -4dc1c6dbf2c2568f0221ec06ca4029919e406b7a466ec4b722f704b579b3e3fa *mksnapshot-v37.6.0-win32-x64.zip +98c036b4be864a3b6518142bb82ec329651d74bb3d38c6e8693058e8cb0a22f3 *chromedriver-v39.2.0-darwin-arm64.zip +daae3a502e68195a30700040d428a4edb9e243d9673dcd10c3f01a5cae0474d5 *chromedriver-v39.2.0-darwin-x64.zip +ee24ebef991438cb8d3be0ec97c06cd63201e7fdbeb85b57b133a0a0fe32519d *chromedriver-v39.2.0-linux-arm64.zip +82b4855a5dcc17548da7826fbb6cc2f98cef515ad09aa5c24fad52bb076161cc *chromedriver-v39.2.0-linux-armv7l.zip +d11ae58e17f8f3759d67dc03096e979743825a5a4ea793357b550c50c1881b35 *chromedriver-v39.2.0-linux-x64.zip +a89043dc974a78eb97d53a52fdb0f8263f5ec6b4a2111c83b8bd610188e599e4 *chromedriver-v39.2.0-mas-arm64.zip +fc140fc34d596cadfc4d63e15453d9b9c3dfba1e2d5a7e20b488fe3ba681ed56 *chromedriver-v39.2.0-mas-x64.zip +185c9e3947be5fbacadd11d7e85ef645d28a583f46bafb6320144439bf53b358 *chromedriver-v39.2.0-win32-arm64.zip +f0e3a7eac00b6edd0c341900a43481b9b7a10d6548bfb4900c052e70f6679933 *chromedriver-v39.2.0-win32-ia32.zip +81176a1986839f6e74da0884c55a5558ce6a80d0315aade7d219e0491bb6041e *chromedriver-v39.2.0-win32-x64.zip +24eb9f86f0228f040b8bceacca3ae14ac047ba60770220cd7ad78a3f3c0e1e74 *electron-api.json +c924efc3a77f65d42ecb8d37ea8ab86502a6299ca6add57d71ac68173aae5f41 *electron-v39.2.0-darwin-arm64-dsym-snapshot.zip +c04607d1aab68122a70eb0cdd839efab030ab743f5859d622fe6239cf564ffb5 *electron-v39.2.0-darwin-arm64-dsym.zip +25ca06afc6780e5b875e61591bf9ae7dee6f2b379c68a02bd21ed47dbffae1c5 *electron-v39.2.0-darwin-arm64-symbols.zip +3ecbe543ebc728d813ea21f16cedebd6b7af812d716b0ede37f1227179a66c3e *electron-v39.2.0-darwin-arm64.zip +a64b47558d2fd5d1d577573bc907f41217219d867741d98b03ce45f82cdc9c83 *electron-v39.2.0-darwin-x64-dsym-snapshot.zip +52144710c0b92f7a68776a216ef0740eb71d1ed9d6312ee3a2e6eacfdf0f6a5a *electron-v39.2.0-darwin-x64-dsym.zip +7ed57186500a1903ad9a9161c22fab9ef9bed9c376a9ead72e92791fa330bff0 *electron-v39.2.0-darwin-x64-symbols.zip +721ec50aac1c2c4ce0930b4f14eb4e5b92ce58ac41f965825dc986eb5f511fee *electron-v39.2.0-darwin-x64.zip +baba1f8d9887e86ba83e2cebb2326dbb0c94d55a390000fd4f4448c3edc22074 *electron-v39.2.0-linux-arm64-debug.zip +6eaca18ade571625329f6d6b5741a64955ee19c0d630e8e813f916965d757ed3 *electron-v39.2.0-linux-arm64-symbols.zip +da7db0ead43e1f560fc1ade4aa50d773d75a5c5339d995f08db49b6fb7267c23 *electron-v39.2.0-linux-arm64.zip +eb316428a148086ecec75a5d1341aa593c136cc8b23b8ad0446436cb6dbe0394 *electron-v39.2.0-linux-armv7l-debug.zip +05b078c16197695911570b283fe3555471cfd2c6e916e12de1c30d953642e8a9 *electron-v39.2.0-linux-armv7l-symbols.zip +87fc8b6903559deab6c2aada4e03dddba06a0071b10ecdc6a116da0baaeb639d *electron-v39.2.0-linux-armv7l.zip +c2946adbaf2fc68830e4302913807381e766f6a330575d55b9c477ec92bf2055 *electron-v39.2.0-linux-x64-debug.zip +f177419295697784b6a039436f21b6ef7fce67c3fefb2d56412fafef37165996 *electron-v39.2.0-linux-x64-symbols.zip +c1f2f123dee6896ff09e4b3e504dfbfe42356c0e6b41b33fd849aa19fd50253d *electron-v39.2.0-linux-x64.zip +604636912f87eb17c15cad19ad9c7db790d666099c499c2389b1ec99b8e7d80b *electron-v39.2.0-mas-arm64-dsym-snapshot.zip +135ed03bf04e7b4e85a654faaabcb62c08222a3d2f70c3b5e779d3ef7ab124f9 *electron-v39.2.0-mas-arm64-dsym.zip +06187fc2d1e686ca70cdec425dcf77f4854928bde4a4ea5007970a82ee676775 *electron-v39.2.0-mas-arm64-symbols.zip +e94e87364182d85fb11c1d146101260349d3472f87441d1972e68aac3c7976b7 *electron-v39.2.0-mas-arm64.zip +cebfb2dfa2244b40a95fa99ce5d54ec26ef5ab290e54451c5bcb502e2ea07c71 *electron-v39.2.0-mas-x64-dsym-snapshot.zip +f7b9694b9fbe3143f653eb8fafc682612cac3f67d998716d41607530723d7b13 *electron-v39.2.0-mas-x64-dsym.zip +095daa622f621b73698ff6a047d415100b9d5d30c27265004545a5f2ec7b252f *electron-v39.2.0-mas-x64-symbols.zip +db7b84377c16e12e8d92f732bee72ed742fa4b3d3c01730f1628509e3f1094cb *electron-v39.2.0-mas-x64.zip +7619f7f4c045903f553f1e4f173264dd9eef43c82f0de09daaa63fd0f57003f8 *electron-v39.2.0-win32-arm64-pdb.zip +e9f73eaaec76e4f585f7210de85bfbb5a4b8e0890f7cec1f5c1a7344cb160cd8 *electron-v39.2.0-win32-arm64-symbols.zip +4aae37230f86b1590f102aa038268299bfb55ce2bf3b76ac4d6159e7b6a69f8e *electron-v39.2.0-win32-arm64-toolchain-profile.zip +d95bc39add0b7040f3cb03a357362dc7472bc86f405e4a0feae3641694537ef1 *electron-v39.2.0-win32-arm64.zip +d94e041143d494b3f98cb7356412d7f4fe4dd527b78aa52010b7898bb02d57ea *electron-v39.2.0-win32-ia32-pdb.zip +d34c31ec4ffad0aadcc7f04c2fbe0620a603900831733fc575b901cae07678d9 *electron-v39.2.0-win32-ia32-symbols.zip +4aae37230f86b1590f102aa038268299bfb55ce2bf3b76ac4d6159e7b6a69f8e *electron-v39.2.0-win32-ia32-toolchain-profile.zip +ec26e39186d03e21a16067652083db2bbf41d31900a5d6e38f2bbdf9f99f7e5f *electron-v39.2.0-win32-ia32.zip +da4d65231e774ecdfb058d96f29f08daeccfd3f9cdf021c432d18695bed90cb7 *electron-v39.2.0-win32-x64-pdb.zip +a5677f8211b2dea4ed0f93bb2fa3370a84fa328c7474c34b07b4f9a011a0b666 *electron-v39.2.0-win32-x64-symbols.zip +4aae37230f86b1590f102aa038268299bfb55ce2bf3b76ac4d6159e7b6a69f8e *electron-v39.2.0-win32-x64-toolchain-profile.zip +8d483a77100dda798af0becdda1a037e4079ad9ec1e49d768bfb671f95122ce2 *electron-v39.2.0-win32-x64.zip +ca520c194f5908145653e47c39524b8bfc1e50d076799612667de39ad2ae338d *electron.d.ts +59a4fdf1a2b9032adb02c09a663761749a5f42d812dd9ae1e05cf13cafa2d829 *ffmpeg-v39.2.0-darwin-arm64.zip +ff7709b1b3f94931439b21e506adfffdfc2a9e5cea5cd59fab5658f9285546d6 *ffmpeg-v39.2.0-darwin-x64.zip +2b83422b70e47c03f3b12a5f77547c434adce65b5a06375faa89701523c972a2 *ffmpeg-v39.2.0-linux-arm64.zip +13eaed8fbb76fde55044261ff50931597e425a3366bd1a8ae7ab1f03e20fda6d *ffmpeg-v39.2.0-linux-armv7l.zip +9b6271eaf27800b9061c3a4049c4e5097f62b33cb4718cf6bb6e75e80cc0460d *ffmpeg-v39.2.0-linux-x64.zip +59a4fdf1a2b9032adb02c09a663761749a5f42d812dd9ae1e05cf13cafa2d829 *ffmpeg-v39.2.0-mas-arm64.zip +ff7709b1b3f94931439b21e506adfffdfc2a9e5cea5cd59fab5658f9285546d6 *ffmpeg-v39.2.0-mas-x64.zip +dedfc2f532c4ae480e59fd607b705d36cc4100d4df1a15e9c14e123a7a49f12f *ffmpeg-v39.2.0-win32-arm64.zip +46239f051df5430ef7965644165145d27f6d91b405f13825d78394dd74d1e9dc *ffmpeg-v39.2.0-win32-ia32.zip +a5d81da6ddfd4c80914938ee3c7de8d237b2ac2c89fab242cb3ff6dc425023a3 *ffmpeg-v39.2.0-win32-x64.zip +81e834aed3ff0932b02199594c8547ed06f7792beb4c20ebf3acccb92043f2d2 *hunspell_dictionaries.zip +8474e9f9ecdf93ccca0abbc3eaeb0e86fad1aae666e2404e8140a01d32fffd2c *libcxx-objects-v39.2.0-linux-arm64.zip +2c6ae26ed989ca4d03f30e5a544189a38c0c1e71f0e32d37fda7e8436bfc7efe *libcxx-objects-v39.2.0-linux-armv7l.zip +7802c21d9801a74b74d1e381164e3f54cadccc114945ec162066be3fd62c7251 *libcxx-objects-v39.2.0-linux-x64.zip +5478f7921f76f8d9fb1d21b5d802cbc77d7898e97e98e60173be5ddc11218edc *libcxx_headers.zip +e990e7b60ecdba8d984b47ed4340f124789d07dde989cced71521b3428da47d9 *libcxxabi_headers.zip +db4818d702a160cf6708726544b25ccaae1faacae73dca435472c0307235da62 *mksnapshot-v39.2.0-darwin-arm64.zip +e48a88334f81940c30ba8246be19538f909c18d25834a5c15d05dfc418dd61be *mksnapshot-v39.2.0-darwin-x64.zip +4e5cfd17d60dac583dd18219cd9a84fe504de7c975abdac2b35bf8f60de9e4dd *mksnapshot-v39.2.0-linux-arm64-x64.zip +be0c4caec2bc02e3bfb8172a7799ae6fe55822b49bcfc8ac939c5933dc5dce3a *mksnapshot-v39.2.0-linux-armv7l-x64.zip +b56d77d467227973438bd3c5c7018494facb1b44a19ccc3ec9057f6f087e1c0d *mksnapshot-v39.2.0-linux-x64.zip +c05e95f7004571f15f615314b12a06e084b76fe0cf92ef0ad633d0d78b4f29a9 *mksnapshot-v39.2.0-mas-arm64.zip +bfa8780e04ef29e310c3eab0980325ccf09d709514af9ca7ef070fc74585135a *mksnapshot-v39.2.0-mas-x64.zip +bfb2e5562666c438c06bfd8606053e7abf39988bc79ced280fba99071338119a *mksnapshot-v39.2.0-win32-arm64-x64.zip +cf7e36d42ea75b84f49fb543b3bb9783cee81da9442e080c52bf0b5e68e06ea1 *mksnapshot-v39.2.0-win32-ia32.zip +fdc79d3a05389122afc684a0bacf266fca7e54544c8889f3aed105b90ba9b1d8 *mksnapshot-v39.2.0-win32-x64.zip diff --git a/build/checksums/nodejs.txt b/build/checksums/nodejs.txt index 982e92d5e5f..43aace217e9 100644 --- a/build/checksums/nodejs.txt +++ b/build/checksums/nodejs.txt @@ -1,7 +1,7 @@ -c59006db713c770d6ec63ae16cb3edc11f49ee093b5c415d667bb4f436c6526d node-v22.19.0-darwin-arm64.tar.gz -3cfed4795cd97277559763c5f56e711852d2cc2420bda1cea30c8aa9ac77ce0c node-v22.19.0-darwin-x64.tar.gz -d32817b937219b8f131a28546035183d79e7fd17a86e38ccb8772901a7cd9009 node-v22.19.0-linux-arm64.tar.gz -969037e6da2a710904d121dcb998510bc0d5d4d61d70ce5eb578096cf36c60e8 node-v22.19.0-linux-armv7l.tar.gz -d36e56998220085782c0ca965f9d51b7726335aed2f5fc7321c6c0ad233aa96d node-v22.19.0-linux-x64.tar.gz -e22d8ae9e47ff62ae4a9a21ecd52feb229c32c1a1d3024ec60c100abb940df30 win-arm64/node.exe -995a3fb3cefad590cd3f4b321532a4b9582fb9c6575320ed2e3e894caac3e362 win-x64/node.exe +c170d6554fba83d41d25a76cdbad85487c077e51fa73519e41ac885aa429d8af node-v22.21.1-darwin-arm64.tar.gz +8e3dc89614debe66c2a6ad2313a1adb06eb37db6cd6c40d7de6f7d987f7d1afd node-v22.21.1-darwin-x64.tar.gz +c86830dedf77f8941faa6c5a9c863bdfdd1927a336a46943decc06a38f80bfb2 node-v22.21.1-linux-arm64.tar.gz +40d3d09aee556abc297dd782864fcc6b9e60acd438ff0660ba9ddcd569c00920 node-v22.21.1-linux-armv7l.tar.gz +219a152ea859861d75adea578bdec3dce8143853c13c5187f40c40e77b0143b2 node-v22.21.1-linux-x64.tar.gz +707bbc8a9e615299ecdbff9040f88f59f20033ff1af923beee749b885cbd565d win-arm64/node.exe +471961cb355311c9a9dd8ba417eca8269ead32a2231653084112554cda52e8b3 win-x64/node.exe diff --git a/build/darwin/create-universal-app.js b/build/darwin/create-universal-app.js index b5ae1a86745..98e14ef2160 100644 --- a/build/darwin/create-universal-app.js +++ b/build/darwin/create-universal-app.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const minimatch_1 = __importDefault(require("minimatch")); diff --git a/build/darwin/sign.js b/build/darwin/sign.js index af8dad69b34..d640e94fbf5 100644 --- a/build/darwin/sign.js +++ b/build/darwin/sign.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const osx_sign_1 = require("@electron/osx-sign"); diff --git a/build/darwin/verify-macho.js b/build/darwin/verify-macho.js index 6a5b4a0895d..8202e8d7b76 100644 --- a/build/darwin/verify-macho.js +++ b/build/darwin/verify-macho.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const assert_1 = __importDefault(require("assert")); const path_1 = __importDefault(require("path")); const promises_1 = require("fs/promises"); diff --git a/build/eslint.js b/build/eslint.mjs similarity index 56% rename from build/eslint.js rename to build/eslint.mjs index 22e976555a5..ca1c987a111 100644 --- a/build/eslint.js +++ b/build/eslint.mjs @@ -3,24 +3,24 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // @ts-check -const es = require('event-stream'); -const vfs = require('vinyl-fs'); -const { eslintFilter } = require('./filters'); +import eventStream from 'event-stream'; +import { src } from 'vinyl-fs'; +import { eslintFilter } from './filters.js'; +import gulpEslint from './gulp-eslint.js'; function eslint() { - const eslint = require('./gulp-eslint'); - return vfs - .src(eslintFilter, { base: '.', follow: true, allowEmpty: true }) + return src(eslintFilter, { base: '.', follow: true, allowEmpty: true }) .pipe( - eslint((results) => { + gulpEslint((results) => { if (results.warningCount > 0 || results.errorCount > 0) { throw new Error(`eslint failed with ${results.warningCount + results.errorCount} warnings and/or errors`); } }) - ).pipe(es.through(function () { /* noop, important for the stream to end */ })); + ).pipe(eventStream.through(function () { /* noop, important for the stream to end */ })); } -if (require.main === module) { +const normalizeScriptPath = (/** @type {string} */ p) => p.replace(/\.(js|ts)$/, ''); +if (normalizeScriptPath(import.meta.filename) === normalizeScriptPath(process.argv[1])) { eslint().on('error', (err) => { console.error(); console.error(err); diff --git a/build/filters.js b/build/filters.js index 9dd7d2fb2ed..0e485164892 100644 --- a/build/filters.js +++ b/build/filters.js @@ -49,6 +49,7 @@ module.exports.unicodeFilter = [ '!build/win32/**', '!extensions/markdown-language-features/notebook-out/*.js', '!extensions/markdown-math/notebook-out/**', + '!extensions/mermaid-chat-features/chat-webview-out/**', '!extensions/ipynb/notebook-out/**', '!extensions/notebook-renderers/renderer-out/**', '!extensions/php-language-features/src/features/phpGlobalFunctions.ts', @@ -134,12 +135,14 @@ module.exports.indentationFilter = [ '!build/**/*.sh', '!build/azure-pipelines/**/*.js', '!build/azure-pipelines/**/*.config', + '!build/npm/gyp/custom-headers/*.patch', '!**/Dockerfile', '!**/Dockerfile.*', '!**/*.Dockerfile', '!**/*.dockerfile', // except for built files + '!extensions/mermaid-chat-features/chat-webview-out/*.js', '!extensions/markdown-language-features/media/*.js', '!extensions/markdown-language-features/notebook-out/*.js', '!extensions/markdown-math/notebook-out/*.js', @@ -174,6 +177,7 @@ module.exports.copyrightFilter = [ '!**/*.wasm', '!build/**/*.init', '!build/linux/libcxx-fetcher.*', + '!build/npm/gyp/custom-headers/*.patch', '!resources/linux/snap/snapcraft.yaml', '!resources/win32/bin/code.js', '!resources/completions/**', diff --git a/build/gulpfile.cli.js b/build/gulpfile.cli.mjs similarity index 83% rename from build/gulpfile.cli.js rename to build/gulpfile.cli.mjs index 63e0ae0b847..2d54cc024fd 100644 --- a/build/gulpfile.cli.js +++ b/build/gulpfile.cli.mjs @@ -3,21 +3,25 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import es from 'event-stream'; +import gulp from 'gulp'; +import * as path from 'path'; +import fancyLog from 'fancy-log'; +import ansiColors from 'ansi-colors'; +import * as cp from 'child_process'; +import { tmpdir } from 'os'; +import { existsSync, mkdirSync, rmSync } from 'fs'; +import task from './lib/task.js'; +import watcher from './lib/watch/index.js'; +import utilModule from './lib/util.js'; +import reporterModule from './lib/reporter.js'; +import untar from 'gulp-untar'; +import gunzip from 'gulp-gunzip'; +import { fileURLToPath } from 'url'; -const es = require('event-stream'); -const gulp = require('gulp'); -const path = require('path'); -const fancyLog = require('fancy-log'); -const ansiColors = require('ansi-colors'); -const cp = require('child_process'); -const { tmpdir } = require('os'); -const { existsSync, mkdirSync, rmSync } = require('fs'); - -const task = require('./lib/task'); -const watcher = require('./lib/watch'); -const { debounce } = require('./lib/util'); -const createReporter = require('./lib/reporter').createReporter; +const { debounce } = utilModule; +const { createReporter } = reporterModule; +const __dirname = import.meta.dirname; const root = 'cli'; const rootAbs = path.resolve(__dirname, '..', root); @@ -80,8 +84,6 @@ const compileFromSources = (callback) => { }; const acquireBuiltOpenSSL = (callback) => { - const untar = require('gulp-untar'); - const gunzip = require('gulp-gunzip'); const dir = path.join(tmpdir(), 'vscode-openssl-download'); mkdirSync(dir, { recursive: true }); @@ -146,7 +148,7 @@ const compileCliTask = task.define('compile-cli', () => { const watchCliTask = task.define('watch-cli', () => { warnIfRustNotInstalled(); - return watcher(`${src}/**`, { read: false }) + return watcher.default(`${src}/**`, { read: false }) .pipe(debounce(compileCliTask)); }); diff --git a/build/gulpfile.compile.js b/build/gulpfile.compile.mjs similarity index 62% rename from build/gulpfile.compile.js rename to build/gulpfile.compile.mjs index 0c0a024c8fc..0a55cd26d13 100644 --- a/build/gulpfile.compile.js +++ b/build/gulpfile.compile.mjs @@ -2,15 +2,12 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - //@ts-check -'use strict'; - -const gulp = require('gulp'); -const util = require('./lib/util'); -const date = require('./lib/date'); -const task = require('./lib/task'); -const compilation = require('./lib/compilation'); +import gulp from 'gulp'; +import util from './lib/util.js'; +import date from './lib/date.js'; +import task from './lib/task.js'; +import compilation from './lib/compilation.js'; /** * @param {boolean} disableMangle @@ -25,11 +22,9 @@ function makeCompileBuildTask(disableMangle) { } // Local/PR compile, including nls and inline sources in sourcemaps, minification, no mangling -const compileBuildWithoutManglingTask = task.define('compile-build-without-mangling', makeCompileBuildTask(true)); +export const compileBuildWithoutManglingTask = task.define('compile-build-without-mangling', makeCompileBuildTask(true)); gulp.task(compileBuildWithoutManglingTask); -exports.compileBuildWithoutManglingTask = compileBuildWithoutManglingTask; // CI compile, including nls and inline sources in sourcemaps, mangling, minification, for build -const compileBuildWithManglingTask = task.define('compile-build-with-mangling', makeCompileBuildTask(false)); +export const compileBuildWithManglingTask = task.define('compile-build-with-mangling', makeCompileBuildTask(false)); gulp.task(compileBuildWithManglingTask); -exports.compileBuildWithManglingTask = compileBuildWithManglingTask; diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.mjs similarity index 88% rename from build/gulpfile.editor.js rename to build/gulpfile.editor.mjs index 1136430dd99..bbd67316333 100644 --- a/build/gulpfile.editor.js +++ b/build/gulpfile.editor.mjs @@ -2,27 +2,30 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - //@ts-check +import gulp from 'gulp'; +import * as path from 'path'; +import util from './lib/util.js'; +import getVersionModule from './lib/getVersion.js'; +import task from './lib/task.js'; +import es from 'event-stream'; +import File from 'vinyl'; +import i18n from './lib/i18n.js'; +import standalone from './lib/standalone.js'; +import * as cp from 'child_process'; +import compilation from './lib/compilation.js'; +import monacoapi from './lib/monaco-api.js'; +import * as fs from 'fs'; +import filter from 'gulp-filter'; +import reporterModule from './lib/reporter.js'; +import monacoPackage from './monaco/package.json' with { type: 'json' }; -const gulp = require('gulp'); -const path = require('path'); -const util = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const task = require('./lib/task'); -const es = require('event-stream'); -const File = require('vinyl'); -const i18n = require('./lib/i18n'); -const standalone = require('./lib/standalone'); -const cp = require('child_process'); -const compilation = require('./lib/compilation'); -const monacoapi = require('./lib/monaco-api'); -const fs = require('fs'); -const filter = require('gulp-filter'); - +const __dirname = import.meta.dirname; +const { getVersion } = getVersionModule; +const { createReporter } = reporterModule; const root = path.dirname(__dirname); const sha1 = getVersion(root); -const semver = require('./monaco/package.json').version; +const semver = monacoPackage.version; const headerVersion = semver + '(' + sha1 + ')'; const BUNDLED_FILE_HEADER = [ @@ -75,7 +78,7 @@ const compileEditorESMTask = task.define('compile-editor-esm', () => { .pipe(i18n.processNlsFiles({ out, fileHeader: BUNDLED_FILE_HEADER, - languages: i18n.defaultLanguages, + languages: [...i18n.defaultLanguages, ...i18n.extraLanguages], })) .pipe(filter(['**', '!**/inlineEntryPoint*', '!**/tsconfig.json', '!**/loader.js'])) .pipe(gulp.dest(out)) @@ -233,8 +236,6 @@ gulp.task('monacodts', task.define('monacodts', () => { */ function createTscCompileTask(watch) { return () => { - const createReporter = require('./lib/reporter').createReporter; - return new Promise((resolve, reject) => { const args = ['./node_modules/.bin/tsc', '-p', './src/tsconfig.monaco.json', '--noEmit']; if (watch) { @@ -281,11 +282,9 @@ function createTscCompileTask(watch) { }; } -const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true)); -exports.monacoTypecheckWatchTask = monacoTypecheckWatchTask; +export const monacoTypecheckWatchTask = task.define('monaco-typecheck-watch', createTscCompileTask(true)); -const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false)); -exports.monacoTypecheckTask = monacoTypecheckTask; +export const monacoTypecheckTask = task.define('monaco-typecheck', createTscCompileTask(false)); //#endregion diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.mjs similarity index 73% rename from build/gulpfile.extensions.js rename to build/gulpfile.extensions.mjs index 7826f48490b..c77c1275ea6 100644 --- a/build/gulpfile.extensions.js +++ b/build/gulpfile.extensions.mjs @@ -4,23 +4,31 @@ *--------------------------------------------------------------------------------------------*/ // Increase max listeners for event emitters -require('events').EventEmitter.defaultMaxListeners = 100; +import { EventEmitter } from 'events'; +EventEmitter.defaultMaxListeners = 100; -const gulp = require('gulp'); -const path = require('path'); -const nodeUtil = require('util'); -const es = require('event-stream'); -const filter = require('gulp-filter'); -const util = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const task = require('./lib/task'); -const watcher = require('./lib/watch'); -const createReporter = require('./lib/reporter').createReporter; -const glob = require('glob'); +import gulp from 'gulp'; +import * as path from 'path'; +import * as nodeUtil from 'util'; +import es from 'event-stream'; +import filter from 'gulp-filter'; +import util from './lib/util.js'; +import getVersionModule from './lib/getVersion.js'; +import task from './lib/task.js'; +import watcher from './lib/watch/index.js'; +import reporterModule from './lib/reporter.js'; +import glob from 'glob'; +import plumber from 'gulp-plumber'; +import ext from './lib/extensions.js'; +import tsb from './lib/tsb/index.js'; +import sourcemaps from 'gulp-sourcemaps'; +import { fileURLToPath } from 'url'; + +const __dirname = import.meta.dirname; +const { getVersion } = getVersionModule; +const { createReporter } = reporterModule; const root = path.dirname(__dirname); const commit = getVersion(root); -const plumber = require('gulp-plumber'); -const ext = require('./lib/extensions'); // To save 250ms for each gulp startup, we are caching the result here // const compilations = glob.sync('**/tsconfig.json', { @@ -92,9 +100,6 @@ const tasks = compilations.map(function (tsconfigFile) { const baseUrl = getBaseUrl(out); function createPipeline(build, emitError, transpileOnly) { - const tsb = require('./lib/tsb'); - const sourcemaps = require('gulp-sourcemaps'); - const reporter = createReporter('extensions'); overrideOptions.inlineSources = Boolean(build); @@ -163,58 +168,40 @@ const tasks = compilations.map(function (tsconfigFile) { const pipeline = createPipeline(false); const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts'])); const input = es.merge(nonts, pipeline.tsProjectSrc()); - const watchInput = watcher(src, { ...srcOpts, ...{ readDelay: 200 } }); + const watchInput = watcher.default(src, { ...srcOpts, ...{ readDelay: 200 } }); return watchInput .pipe(util.incremental(pipeline, input)) .pipe(gulp.dest(out)); })); - const compileBuildTask = task.define(`compile-build-extension-${name}`, task.series(cleanTask, () => { - const pipeline = createPipeline(true, true); - const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts'])); - const input = es.merge(nonts, pipeline.tsProjectSrc()); - - return input - .pipe(pipeline()) - .pipe(gulp.dest(out)); - })); - // Tasks gulp.task(transpileTask); gulp.task(compileTask); gulp.task(watchTask); - return { transpileTask, compileTask, watchTask, compileBuildTask }; + return { transpileTask, compileTask, watchTask }; }); const transpileExtensionsTask = task.define('transpile-extensions', task.parallel(...tasks.map(t => t.transpileTask))); gulp.task(transpileExtensionsTask); -const compileExtensionsTask = task.define('compile-extensions', task.parallel(...tasks.map(t => t.compileTask))); +export const compileExtensionsTask = task.define('compile-extensions', task.parallel(...tasks.map(t => t.compileTask))); gulp.task(compileExtensionsTask); -exports.compileExtensionsTask = compileExtensionsTask; -const watchExtensionsTask = task.define('watch-extensions', task.parallel(...tasks.map(t => t.watchTask))); +export const watchExtensionsTask = task.define('watch-extensions', task.parallel(...tasks.map(t => t.watchTask))); gulp.task(watchExtensionsTask); -exports.watchExtensionsTask = watchExtensionsTask; - -const compileExtensionsBuildLegacyTask = task.define('compile-extensions-build-legacy', task.parallel(...tasks.map(t => t.compileBuildTask))); -gulp.task(compileExtensionsBuildLegacyTask); //#region Extension media -const compileExtensionMediaTask = task.define('compile-extension-media', () => ext.buildExtensionMedia(false)); +export const compileExtensionMediaTask = task.define('compile-extension-media', () => ext.buildExtensionMedia(false)); gulp.task(compileExtensionMediaTask); -exports.compileExtensionMediaTask = compileExtensionMediaTask; -const watchExtensionMedia = task.define('watch-extension-media', () => ext.buildExtensionMedia(true)); +export const watchExtensionMedia = task.define('watch-extension-media', () => ext.buildExtensionMedia(true)); gulp.task(watchExtensionMedia); -exports.watchExtensionMedia = watchExtensionMedia; -const compileExtensionMediaBuildTask = task.define('compile-extension-media-build', () => ext.buildExtensionMedia(false, '.build/extensions')); +export const compileExtensionMediaBuildTask = task.define('compile-extension-media-build', () => ext.buildExtensionMedia(false, '.build/extensions')); gulp.task(compileExtensionMediaBuildTask); -exports.compileExtensionMediaBuildTask = compileExtensionMediaBuildTask; //#endregion @@ -223,8 +210,7 @@ exports.compileExtensionMediaBuildTask = compileExtensionMediaBuildTask; /** * Cleans the build directory for extensions */ -const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions')); -exports.cleanExtensionsBuildTask = cleanExtensionsBuildTask; +export const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions')); /** * brings in the marketplace extensions for the build @@ -235,32 +221,29 @@ const bundleMarketplaceExtensionsBuildTask = task.define('bundle-marketplace-ext * Compiles the non-native extensions for the build * @note this does not clean the directory ahead of it. See {@link cleanExtensionsBuildTask} for that. */ -const compileNonNativeExtensionsBuildTask = task.define('compile-non-native-extensions-build', task.series( +export const compileNonNativeExtensionsBuildTask = task.define('compile-non-native-extensions-build', task.series( bundleMarketplaceExtensionsBuildTask, task.define('bundle-non-native-extensions-build', () => ext.packageNonNativeLocalExtensionsStream(false, false).pipe(gulp.dest('.build'))) )); gulp.task(compileNonNativeExtensionsBuildTask); -exports.compileNonNativeExtensionsBuildTask = compileNonNativeExtensionsBuildTask; /** * Compiles the native extensions for the build * @note this does not clean the directory ahead of it. See {@link cleanExtensionsBuildTask} for that. */ -const compileNativeExtensionsBuildTask = task.define('compile-native-extensions-build', () => ext.packageNativeLocalExtensionsStream(false, false).pipe(gulp.dest('.build'))); +export const compileNativeExtensionsBuildTask = task.define('compile-native-extensions-build', () => ext.packageNativeLocalExtensionsStream(false, false).pipe(gulp.dest('.build'))); gulp.task(compileNativeExtensionsBuildTask); -exports.compileNativeExtensionsBuildTask = compileNativeExtensionsBuildTask; /** * Compiles the extensions for the build. * This is essentially a helper task that combines {@link cleanExtensionsBuildTask}, {@link compileNonNativeExtensionsBuildTask} and {@link compileNativeExtensionsBuildTask} */ -const compileAllExtensionsBuildTask = task.define('compile-extensions-build', task.series( +export const compileAllExtensionsBuildTask = task.define('compile-extensions-build', task.series( cleanExtensionsBuildTask, bundleMarketplaceExtensionsBuildTask, task.define('bundle-extensions-build', () => ext.packageAllLocalExtensionsStream(false, false).pipe(gulp.dest('.build'))), )); gulp.task(compileAllExtensionsBuildTask); -exports.compileAllExtensionsBuildTask = compileAllExtensionsBuildTask; // This task is run in the compilation stage of the CI pipeline. We only compile the non-native extensions since those can be fully built regardless of platform. // This defers the native extensions to the platform specific stage of the CI pipeline. @@ -278,13 +261,11 @@ gulp.task(task.define('extensions-ci-pr', task.series(compileExtensionsBuildPull //#endregion -const compileWebExtensionsTask = task.define('compile-web', () => buildWebExtensions(false)); +export const compileWebExtensionsTask = task.define('compile-web', () => buildWebExtensions(false)); gulp.task(compileWebExtensionsTask); -exports.compileWebExtensionsTask = compileWebExtensionsTask; -const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true)); +export const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true)); gulp.task(watchWebExtensionsTask); -exports.watchWebExtensionsTask = watchWebExtensionsTask; /** * @param {boolean} isWatch diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.mjs similarity index 77% rename from build/gulpfile.hygiene.js rename to build/gulpfile.hygiene.mjs index c76fab7abc6..fb0a7408118 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.mjs @@ -2,19 +2,21 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import gulp from 'gulp'; +import es from 'event-stream'; +import path from 'path'; +import fs from 'fs'; +import task from './lib/task.js'; +import { hygiene } from './hygiene.mjs'; -const gulp = require('gulp'); -const es = require('event-stream'); -const path = require('path'); -const task = require('./lib/task'); -const { hygiene } = require('./hygiene'); +const dirName = path.dirname(new URL(import.meta.url).pathname); /** * @param {string} actualPath */ function checkPackageJSON(actualPath) { - const actual = require(path.join(__dirname, '..', actualPath)); - const rootPackageJSON = require('../package.json'); + const actual = JSON.parse(fs.readFileSync(path.join(dirName, '..', actualPath), 'utf8')); + const rootPackageJSON = JSON.parse(fs.readFileSync(path.join(dirName, '..', 'package.json'), 'utf8')); const checkIncluded = (set1, set2) => { for (const depName in set1) { const depVersion = set1[depName]; diff --git a/build/gulpfile.js b/build/gulpfile.mjs similarity index 72% rename from build/gulpfile.js rename to build/gulpfile.mjs index 97971eec63e..1b14c7edd5f 100644 --- a/build/gulpfile.js +++ b/build/gulpfile.mjs @@ -3,17 +3,23 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import { EventEmitter } from 'events'; +import glob from 'glob'; +import gulp from 'gulp'; +import { createRequire } from 'node:module'; +import { fileURLToPath } from 'url'; +import { monacoTypecheckTask /* , monacoTypecheckWatchTask */ } from './gulpfile.editor.mjs'; +import { compileExtensionMediaTask, compileExtensionsTask, watchExtensionsTask } from './gulpfile.extensions.mjs'; +import compilation from './lib/compilation.js'; +import task from './lib/task.js'; +import util from './lib/util.js'; -// Increase max listeners for event emitters -require('events').EventEmitter.defaultMaxListeners = 100; +EventEmitter.defaultMaxListeners = 100; -const gulp = require('gulp'); -const util = require('./lib/util'); -const task = require('./lib/task'); -const { transpileTask, compileTask, watchTask, compileApiProposalNamesTask, watchApiProposalNamesTask } = require('./lib/compilation'); -const { monacoTypecheckTask/* , monacoTypecheckWatchTask */ } = require('./gulpfile.editor'); -const { compileExtensionsTask, watchExtensionsTask, compileExtensionMediaTask } = require('./gulpfile.extensions'); +const require = createRequire(import.meta.url); +const __dirname = import.meta.dirname; + +const { transpileTask, compileTask, watchTask, compileApiProposalNamesTask, watchApiProposalNamesTask } = compilation; // API proposal names gulp.task(compileApiProposalNamesTask); @@ -49,5 +55,5 @@ process.on('unhandledRejection', (reason, p) => { }); // Load all the gulpfiles only if running tasks other than the editor tasks -require('glob').sync('gulpfile.*.js', { cwd: __dirname }) +glob.sync('gulpfile.*.{mjs,js}', { cwd: __dirname }) .forEach(f => require(`./${f}`)); diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.mjs similarity index 89% rename from build/gulpfile.reh.js rename to build/gulpfile.reh.mjs index 10b7b44b5ec..837bcd3d5ee 100644 --- a/build/gulpfile.reh.js +++ b/build/gulpfile.reh.mjs @@ -3,35 +3,44 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import gulp from 'gulp'; +import * as path from 'path'; +import es from 'event-stream'; +import * as util from './lib/util.js'; +import * as getVersionModule from './lib/getVersion.js'; +import * as task from './lib/task.js'; +import optimize from './lib/optimize.js'; +import * as inlineMetaModule from './lib/inlineMeta.js'; +import product from '../product.json' with { type: 'json' }; +import rename from 'gulp-rename'; +import replace from 'gulp-replace'; +import filter from 'gulp-filter'; +import * as dependenciesModule from './lib/dependencies.js'; +import * as dateModule from './lib/date.js'; +import vfs from 'vinyl-fs'; +import packageJson from '../package.json' with { type: 'json' }; +import flatmap from 'gulp-flatmap'; +import gunzip from 'gulp-gunzip'; +import untar from 'gulp-untar'; +import File from 'vinyl'; +import * as fs from 'fs'; +import glob from 'glob'; +import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; +import { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } from './gulpfile.extensions.mjs'; +import { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } from './gulpfile.vscode.web.mjs'; +import * as cp from 'child_process'; +import log from 'fancy-log'; +import buildfile from './buildfile.js'; +import { fileURLToPath } from 'url'; +import * as fetchModule from './lib/fetch.js'; +import jsonEditor from 'gulp-json-editor'; -const gulp = require('gulp'); -const path = require('path'); -const es = require('event-stream'); -const util = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const task = require('./lib/task'); -const optimize = require('./lib/optimize'); -const { inlineMeta } = require('./lib/inlineMeta'); -const product = require('../product.json'); -const rename = require('gulp-rename'); -const replace = require('gulp-replace'); -const filter = require('gulp-filter'); -const { getProductionDependencies } = require('./lib/dependencies'); -const { readISODate } = require('./lib/date'); -const vfs = require('vinyl-fs'); -const packageJson = require('../package.json'); -const flatmap = require('gulp-flatmap'); -const gunzip = require('gulp-gunzip'); -const File = require('vinyl'); -const fs = require('fs'); -const glob = require('glob'); -const { compileBuildWithManglingTask } = require('./gulpfile.compile'); -const { cleanExtensionsBuildTask, compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileExtensionMediaBuildTask } = require('./gulpfile.extensions'); -const { vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } = require('./gulpfile.vscode.web'); -const cp = require('child_process'); -const log = require('fancy-log'); -const buildfile = require('./buildfile'); +const { inlineMeta } = inlineMetaModule; +const { getVersion } = getVersionModule; +const { getProductionDependencies } = dependenciesModule; +const { readISODate } = dateModule; +const { fetchUrls, fetchGithub } = fetchModule; +const __dirname = import.meta.dirname; const REPO_ROOT = path.dirname(__dirname); const commit = getVersion(REPO_ROOT); @@ -185,8 +194,6 @@ if (defaultNodeTask) { } function nodejs(platform, arch) { - const { fetchUrls, fetchGithub } = require('./lib/fetch'); - const untar = require('gulp-untar'); if (arch === 'armhf') { arch = 'armv7l'; @@ -253,8 +260,6 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa const destination = path.join(BUILD_ROOT, destinationFolderName); return () => { - const json = require('gulp-json-editor'); - const src = gulp.src(sourceFolderName + '/**', { base: '.' }) .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) .pipe(util.setExecutableBit(['**/*.sh'])) @@ -312,7 +317,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa let packageJsonContents; const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' }) - .pipe(json({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' })) + .pipe(jsonEditor({ name, version, dependencies: undefined, optionalDependencies: undefined, type: 'module' })) .pipe(es.through(function (file) { packageJsonContents = file.contents.toString(); this.emit('data', file); @@ -320,7 +325,7 @@ function packageTask(type, platform, arch, sourceFolderName, destinationFolderNa let productJsonContents; const productJsonStream = gulp.src(['product.json'], { base: '.' }) - .pipe(json({ commit, date: readISODate('out-build'), version })) + .pipe(jsonEditor({ commit, date: readISODate('out-build'), version })) .pipe(es.through(function (file) { productJsonContents = file.contents.toString(); this.emit('data', file); diff --git a/build/gulpfile.scan.js b/build/gulpfile.scan.mjs similarity index 86% rename from build/gulpfile.scan.js rename to build/gulpfile.scan.mjs index aafc64e81c2..af6aa0b150b 100644 --- a/build/gulpfile.scan.js +++ b/build/gulpfile.scan.mjs @@ -3,18 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import gulp from 'gulp'; +import * as path from 'path'; +import task from './lib/task.js'; +import util from './lib/util.js'; +import electron from '@vscode/gulp-electron'; +import electronConfigModule from './lib/electron.js'; +import filter from 'gulp-filter'; +import deps from './lib/dependencies.js'; +import { existsSync, readdirSync } from 'fs'; +import { fileURLToPath } from 'url'; -const gulp = require('gulp'); -const path = require('path'); -const task = require('./lib/task'); -const util = require('./lib/util'); -const electron = require('@vscode/gulp-electron'); -const { config } = require('./lib/electron'); -const filter = require('gulp-filter'); -const deps = require('./lib/dependencies'); -const { existsSync, readdirSync } = require('fs'); +const { config } = electronConfigModule; +const __dirname = import.meta.dirname; const root = path.dirname(__dirname); const BUILD_TARGETS = [ @@ -27,7 +29,11 @@ const BUILD_TARGETS = [ ]; // The following files do not have PDBs downloaded for them during the download symbols process. -const excludedCheckList = ['d3dcompiler_47.dll']; +const excludedCheckList = [ + 'd3dcompiler_47.dll', + 'dxil.dll', + 'dxcompiler.dll', +]; BUILD_TARGETS.forEach(buildTarget => { const dashed = (/** @type {string | null} */ str) => (str ? `-${str}` : ``); diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.mjs similarity index 92% rename from build/gulpfile.vscode.linux.js rename to build/gulpfile.vscode.linux.mjs index 9cf6411e46a..315c29091a0 100644 --- a/build/gulpfile.vscode.linux.js +++ b/build/gulpfile.vscode.linux.mjs @@ -3,25 +3,28 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import gulp from 'gulp'; +import replace from 'gulp-replace'; +import rename from 'gulp-rename'; +import es from 'event-stream'; +import vfs from 'vinyl-fs'; +import * as utilModule from './lib/util.js'; +import * as getVersionModule from './lib/getVersion.js'; +import * as task from './lib/task.js'; +import packageJson from '../package.json' with { type: 'json' }; +import product from '../product.json' with { type: 'json' }; +import { getDependencies } from './linux/dependencies-generator.js'; +import * as depLists from './linux/debian/dep-lists.js'; +import * as path from 'path'; +import * as cp from 'child_process'; +import { promisify } from 'util'; +import { fileURLToPath } from 'url'; -const gulp = require('gulp'); -const replace = require('gulp-replace'); -const rename = require('gulp-rename'); -const es = require('event-stream'); -const vfs = require('vinyl-fs'); -const { rimraf } = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const task = require('./lib/task'); -const packageJson = require('../package.json'); -const product = require('../product.json'); -const dependenciesGenerator = require('./linux/dependencies-generator'); -const debianRecommendedDependencies = require('./linux/debian/dep-lists').recommendedDeps; -const path = require('path'); -const cp = require('child_process'); -const util = require('util'); - -const exec = util.promisify(cp.exec); +const { rimraf } = utilModule; +const { getVersion } = getVersionModule; +const { recommendedDeps: debianRecommendedDependencies } = depLists; +const __dirname = import.meta.dirname; +const exec = promisify(cp.exec); const root = path.dirname(__dirname); const commit = getVersion(root); @@ -40,7 +43,7 @@ function prepareDebPackage(arch) { const destination = '.build/linux/deb/' + debArch + '/' + product.applicationName + '-' + debArch; return async function () { - const dependencies = await dependenciesGenerator.getDependencies('deb', binaryDir, product.applicationName, debArch); + const dependencies = await getDependencies('deb', binaryDir, product.applicationName, debArch); const desktop = gulp.src('resources/linux/code.desktop', { base: '.' }) .pipe(rename('usr/share/applications/' + product.applicationName + '.desktop')); @@ -157,7 +160,7 @@ function prepareRpmPackage(arch) { const stripBinary = process.env['STRIP'] ?? '/usr/bin/strip'; return async function () { - const dependencies = await dependenciesGenerator.getDependencies('rpm', binaryDir, product.applicationName, rpmArch); + const dependencies = await getDependencies('rpm', binaryDir, product.applicationName, rpmArch); const desktop = gulp.src('resources/linux/code.desktop', { base: '.' }) .pipe(rename('BUILD/usr/share/applications/' + product.applicationName + '.desktop')); diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.mjs similarity index 89% rename from build/gulpfile.vscode.js rename to build/gulpfile.vscode.mjs index ed06b6a5aa8..89e9ec08dd4 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.mjs @@ -3,38 +3,49 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import gulp from 'gulp'; +import * as fs from 'fs'; +import * as path from 'path'; +import es from 'event-stream'; +import vfs from 'vinyl-fs'; +import rename from 'gulp-rename'; +import replace from 'gulp-replace'; +import filter from 'gulp-filter'; +import electron from '@vscode/gulp-electron'; +import jsonEditor from 'gulp-json-editor'; +import * as util from './lib/util.js'; +import * as getVersionModule from './lib/getVersion.js'; +import * as dateModule from './lib/date.js'; +import * as task from './lib/task.js'; +import buildfile from './buildfile.js'; +import optimize from './lib/optimize.js'; +import * as inlineMetaModule from './lib/inlineMeta.js'; +import packageJson from '../package.json' with { type: 'json' }; +import product from '../product.json' with { type: 'json' }; +import * as crypto from 'crypto'; +import i18n from './lib/i18n.js'; +import * as dependenciesModule from './lib/dependencies.js'; +import electronModule from './lib/electron.js'; +import asarModule from './lib/asar.js'; +import minimist from 'minimist'; +import { compileBuildWithoutManglingTask, compileBuildWithManglingTask } from './gulpfile.compile.mjs'; +import { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } from './gulpfile.extensions.mjs'; +import { promisify } from 'util'; +import globCallback from 'glob'; +import rceditCallback from 'rcedit'; +import { fileURLToPath } from 'url'; -const gulp = require('gulp'); -const fs = require('fs'); -const path = require('path'); -const es = require('event-stream'); -const vfs = require('vinyl-fs'); -const rename = require('gulp-rename'); -const replace = require('gulp-replace'); -const filter = require('gulp-filter'); -const util = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const { readISODate } = require('./lib/date'); -const task = require('./lib/task'); -const buildfile = require('./buildfile'); -const optimize = require('./lib/optimize'); -const { inlineMeta } = require('./lib/inlineMeta'); +const { getVersion } = getVersionModule; +const { readISODate } = dateModule; +const { inlineMeta } = inlineMetaModule; +const { getProductionDependencies } = dependenciesModule; +const { config } = electronModule; +const { createAsar } = asarModule; +const glob = promisify(globCallback); +const rcedit = promisify(rceditCallback); +const __dirname = import.meta.dirname; const root = path.dirname(__dirname); const commit = getVersion(root); -const packageJson = require('../package.json'); -const product = require('../product.json'); -const crypto = require('crypto'); -const i18n = require('./lib/i18n'); -const { getProductionDependencies } = require('./lib/dependencies'); -const { config } = require('./lib/electron'); -const createAsar = require('./lib/asar').createAsar; -const minimist = require('minimist'); -const { compileBuildWithoutManglingTask, compileBuildWithManglingTask } = require('./gulpfile.compile'); -const { compileNonNativeExtensionsBuildTask, compileNativeExtensionsBuildTask, compileAllExtensionsBuildTask, compileExtensionMediaBuildTask, cleanExtensionsBuildTask } = require('./gulpfile.extensions'); -const { promisify } = require('util'); -const glob = promisify(require('glob')); -const rcedit = promisify(require('rcedit')); // Build const vscodeEntryPoints = [ @@ -214,9 +225,6 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op platform = platform || process.platform; const task = () => { - const electron = require('@vscode/gulp-electron'); - const json = require('gulp-json-editor'); - const out = sourceFolderName; const checksums = computeChecksums(out, [ @@ -262,7 +270,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op let packageJsonContents; const packageJsonStream = gulp.src(['package.json'], { base: '.' }) - .pipe(json(packageJsonUpdates)) + .pipe(jsonEditor(packageJsonUpdates)) .pipe(es.through(function (file) { packageJsonContents = file.contents.toString(); this.emit('data', file); @@ -270,7 +278,7 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op let productJsonContents; const productJsonStream = gulp.src(['product.json'], { base: '.' }) - .pipe(json({ commit, date: readISODate('out-build'), checksums, version })) + .pipe(jsonEditor({ commit, date: readISODate('out-build'), checksums, version })) .pipe(es.through(function (file) { productJsonContents = file.contents.toString(); this.emit('data', file); @@ -354,7 +362,9 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op 'resources/win32/code_150x150.png' ], { base: '.' })); } else if (platform === 'linux') { - all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' })); + const policyDest = gulp.src('.build/policies/linux/**', { base: '.build/policies/linux' }) + .pipe(rename(f => f.dirname = `policies/${f.dirname}`)); + all = es.merge(all, gulp.src('resources/linux/code.png', { base: '.' }), policyDest); } else if (platform === 'darwin') { const shortcut = gulp.src('resources/darwin/bin/code.sh') .pipe(replace('@@APPNAME@@', product.applicationName)) @@ -407,7 +417,9 @@ function packageTask(platform, arch, sourceFolderName, destinationFolderName, op if (quality === 'stable' || quality === 'insider') { result = es.merge(result, gulp.src('.build/win32/appx/**', { base: '.build/win32' })); const rawVersion = version.replace(/-\w+$/, '').split('.'); - const appxVersion = `${rawVersion[0]}.0.${rawVersion[1]}.${rawVersion[2]}`; + + // AppX doesn't support versions like `1.0.107.20251114039`, so we bring it back down to zero + const appxVersion = `${rawVersion[0]}.0.${rawVersion[1]}.${quality === 'insider' ? '0' : rawVersion[2]}`; result = es.merge(result, gulp.src('resources/win32/appx/AppxManifest.xml', { base: '.' }) .pipe(replace('@@AppxPackageName@@', product.win32AppUserModelId)) .pipe(replace('@@AppxPackageVersion@@', appxVersion)) diff --git a/build/gulpfile.vscode.web.js b/build/gulpfile.vscode.web.mjs similarity index 86% rename from build/gulpfile.vscode.web.js rename to build/gulpfile.vscode.web.mjs index 295a9778d52..e976ed77a61 100644 --- a/build/gulpfile.vscode.web.js +++ b/build/gulpfile.vscode.web.mjs @@ -3,25 +3,31 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; +import gulp from 'gulp'; +import * as path from 'path'; +import es from 'event-stream'; +import * as util from './lib/util.js'; +import * as getVersionModule from './lib/getVersion.js'; +import * as task from './lib/task.js'; +import optimize from './lib/optimize.js'; +import * as dateModule from './lib/date.js'; +import product from '../product.json' with { type: 'json' }; +import rename from 'gulp-rename'; +import filter from 'gulp-filter'; +import * as dependenciesModule from './lib/dependencies.js'; +import vfs from 'vinyl-fs'; +import packageJson from '../package.json' with { type: 'json' }; +import { compileBuildWithManglingTask } from './gulpfile.compile.mjs'; +import extensions from './lib/extensions.js'; +import VinylFile from 'vinyl'; +import jsonEditor from 'gulp-json-editor'; +import buildfile from './buildfile.js'; +import { fileURLToPath } from 'url'; -const gulp = require('gulp'); -const path = require('path'); -const es = require('event-stream'); -const util = require('./lib/util'); -const { getVersion } = require('./lib/getVersion'); -const task = require('./lib/task'); -const optimize = require('./lib/optimize'); -const { readISODate } = require('./lib/date'); -const product = require('../product.json'); -const rename = require('gulp-rename'); -const filter = require('gulp-filter'); -const { getProductionDependencies } = require('./lib/dependencies'); -const vfs = require('vinyl-fs'); -const packageJson = require('../package.json'); -const { compileBuildWithManglingTask } = require('./gulpfile.compile'); -const extensions = require('./lib/extensions'); -const VinylFile = require('vinyl'); +const { getVersion } = getVersionModule; +const { readISODate } = dateModule; +const { getProductionDependencies } = dependenciesModule; +const __dirname = import.meta.dirname; const REPO_ROOT = path.dirname(__dirname); const BUILD_ROOT = path.dirname(REPO_ROOT); @@ -31,7 +37,7 @@ const commit = getVersion(REPO_ROOT); const quality = product.quality; const version = (quality && quality !== 'stable') ? `${packageJson.version}-${quality}` : packageJson.version; -const vscodeWebResourceIncludes = [ +export const vscodeWebResourceIncludes = [ // NLS 'out-build/nls.messages.js', @@ -58,7 +64,6 @@ const vscodeWebResourceIncludes = [ // Extension Host Worker 'out-build/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html' ]; -exports.vscodeWebResourceIncludes = vscodeWebResourceIncludes; const vscodeWebResources = [ @@ -73,8 +78,6 @@ const vscodeWebResources = [ '!**/test/**' ]; -const buildfile = require('./buildfile'); - const vscodeWebEntryPoints = [ buildfile.workerEditor, buildfile.workerExtensionHost, @@ -92,7 +95,7 @@ const vscodeWebEntryPoints = [ * @param extensionsRoot {string} The location where extension will be read from * @param {object} product The parsed product.json file contents */ -const createVSCodeWebFileContentMapper = (extensionsRoot, product) => { +export const createVSCodeWebFileContentMapper = (extensionsRoot, product) => { /** * @param {string} path * @returns {((content: string) => string) | undefined} @@ -118,7 +121,6 @@ const createVSCodeWebFileContentMapper = (extensionsRoot, product) => { return undefined; }; }; -exports.createVSCodeWebFileContentMapper = createVSCodeWebFileContentMapper; const bundleVSCodeWebTask = task.define('bundle-vscode-web', task.series( util.rimraf('out-vscode-web'), @@ -150,8 +152,6 @@ function packageTask(sourceFolderName, destinationFolderName) { const destination = path.join(BUILD_ROOT, destinationFolderName); return () => { - const json = require('gulp-json-editor'); - const src = gulp.src(sourceFolderName + '/**', { base: '.' }) .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })); @@ -175,7 +175,7 @@ function packageTask(sourceFolderName, destinationFolderName) { const name = product.nameShort; const packageJsonStream = gulp.src(['remote/web/package.json'], { base: 'remote/web' }) - .pipe(json({ name, version, type: 'module' })); + .pipe(jsonEditor({ name, version, type: 'module' })); const license = gulp.src(['remote/LICENSE'], { base: 'remote', allowEmpty: true }); diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.mjs similarity index 87% rename from build/gulpfile.vscode.win32.js rename to build/gulpfile.vscode.win32.mjs index 9207df5a44b..cc32aa2564f 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.mjs @@ -2,20 +2,21 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -'use strict'; - -const gulp = require('gulp'); -const path = require('path'); -const fs = require('fs'); -const assert = require('assert'); -const cp = require('child_process'); -const util = require('./lib/util'); -const task = require('./lib/task'); -const pkg = require('../package.json'); -const product = require('../product.json'); -const vfs = require('vinyl-fs'); -const rcedit = require('rcedit'); +import gulp from 'gulp'; +import * as path from 'path'; +import * as fs from 'fs'; +import assert from 'assert'; +import * as cp from 'child_process'; +import * as util from './lib/util.js'; +import * as task from './lib/task.js'; +import pkg from '../package.json' with { type: 'json' }; +import product from '../product.json' with { type: 'json' }; +import vfs from 'vinyl-fs'; +import rcedit from 'rcedit'; +import { createRequire } from 'module'; +const require = createRequire(import.meta.url); +const __dirname = import.meta.dirname; const repoPath = path.dirname(__dirname); const buildPath = (/** @type {string} */ arch) => path.join(path.dirname(repoPath), `VSCode-win32-${arch}`); const setupDir = (/** @type {string} */ arch, /** @type {string} */ target) => path.join(repoPath, '.build', `win32-${arch}`, `${target}-setup`); @@ -82,12 +83,19 @@ function buildWin32Setup(arch, target) { fs.writeFileSync(productJsonPath, JSON.stringify(productJson, undefined, '\t')); const quality = product.quality || 'dev'; + let RawVersion = pkg.version.replace(/-\w+$/, ''); + + // InnoSetup doesn't support versions like `1.0.107.20251114039`, so we bring it back down to zero + if (quality === 'insider') { + RawVersion = RawVersion.replace(/(\d+)$/, '0'); + } + const definitions = { NameLong: product.nameLong, NameShort: product.nameShort, DirName: product.win32DirName, Version: pkg.version, - RawVersion: pkg.version.replace(/-\w+$/, ''), + RawVersion, NameVersion: product.win32NameVersion + (target === 'user' ? ' (User)' : ''), ExeBasename: product.nameShort, RegValueName: product.win32RegValueName, diff --git a/build/hygiene.js b/build/hygiene.mjs similarity index 91% rename from build/hygiene.js rename to build/hygiene.mjs index 0a1cc94278c..3497cafdcc8 100644 --- a/build/hygiene.js +++ b/build/hygiene.mjs @@ -3,16 +3,18 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // @ts-check - -const filter = require('gulp-filter'); -const es = require('event-stream'); -const VinylFile = require('vinyl'); -const vfs = require('vinyl-fs'); -const path = require('path'); -const fs = require('fs'); -const pall = require('p-all'); - -const { all, copyrightFilter, unicodeFilter, indentationFilter, tsFormattingFilter, eslintFilter, stylelintFilter } = require('./filters'); +import cp from 'child_process'; +import es from 'event-stream'; +import fs from 'fs'; +import filter from 'gulp-filter'; +import pall from 'p-all'; +import path from 'path'; +import VinylFile from 'vinyl'; +import vfs from 'vinyl-fs'; +import { all, copyrightFilter, eslintFilter, indentationFilter, stylelintFilter, tsFormattingFilter, unicodeFilter } from './filters.js'; +import eslint from './gulp-eslint.js'; +import formatter from './lib/formatter.js'; +import gulpstylelint from './stylelint.mjs'; const copyrightHeaderLines = [ '/*---------------------------------------------------------------------------------------------', @@ -25,11 +27,8 @@ const copyrightHeaderLines = [ * @param {string[] | NodeJS.ReadWriteStream} some * @param {boolean} runEslint */ -function hygiene(some, runEslint = true) { - const eslint = require('./gulp-eslint'); - const gulpstylelint = require('./stylelint'); - const formatter = require('./lib/formatter'); - +export function hygiene(some, runEslint = true) { + console.log('Starting hygiene...'); let errorCount = 0; const productJson = es.through(function (file) { @@ -226,13 +225,10 @@ function hygiene(some, runEslint = true) { ); } -module.exports.hygiene = hygiene; - /** * @param {string[]} paths */ function createGitIndexVinyls(paths) { - const cp = require('child_process'); const repositoryPath = process.cwd(); const fns = paths.map((relativePath) => () => @@ -273,9 +269,7 @@ function createGitIndexVinyls(paths) { } // this allows us to run hygiene as a git pre-commit hook -if (require.main === module) { - const cp = require('child_process'); - +if (import.meta.filename === process.argv[1]) { process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); process.exit(1); @@ -311,7 +305,7 @@ if (require.main === module) { hygiene(es.readArray(vinyls).pipe(filter(all))) .on('end', () => c()) .on('error', e) - )) + )); } ) .catch((err) => { diff --git a/build/lib/asar.js b/build/lib/asar.js index 2da31a93904..d08070a4fdc 100644 --- a/build/lib/asar.js +++ b/build/lib/asar.js @@ -1,17 +1,17 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAsar = createAsar; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const path_1 = __importDefault(require("path")); const event_stream_1 = __importDefault(require("event-stream")); -const pickle = require('chromium-pickle-js'); -const Filesystem = require('asar/lib/filesystem'); +const chromium_pickle_js_1 = __importDefault(require("chromium-pickle-js")); +const filesystem_js_1 = __importDefault(require("asar/lib/filesystem.js")); const vinyl_1 = __importDefault(require("vinyl")); const minimatch_1 = __importDefault(require("minimatch")); function createAsar(folderPath, unpackGlobs, skipGlobs, duplicateGlobs, destFilename) { @@ -41,7 +41,7 @@ function createAsar(folderPath, unpackGlobs, skipGlobs, duplicateGlobs, destFile } return false; }; - const filesystem = new Filesystem(folderPath); + const filesystem = new filesystem_js_1.default(folderPath); const out = []; // Keep track of pending inserts let pendingInserts = 0; @@ -121,10 +121,10 @@ function createAsar(folderPath, unpackGlobs, skipGlobs, duplicateGlobs, destFile }, function () { const finish = () => { { - const headerPickle = pickle.createEmpty(); + const headerPickle = chromium_pickle_js_1.default.createEmpty(); headerPickle.writeString(JSON.stringify(filesystem.header)); const headerBuf = headerPickle.toBuffer(); - const sizePickle = pickle.createEmpty(); + const sizePickle = chromium_pickle_js_1.default.createEmpty(); sizePickle.writeUInt32(headerBuf.length); const sizeBuf = sizePickle.toBuffer(); out.unshift(headerBuf); diff --git a/build/lib/asar.ts b/build/lib/asar.ts index 5f2df925bde..873b3f946fd 100644 --- a/build/lib/asar.ts +++ b/build/lib/asar.ts @@ -5,18 +5,11 @@ import path from 'path'; import es from 'event-stream'; -const pickle = require('chromium-pickle-js'); -const Filesystem = require('asar/lib/filesystem'); +import pickle from 'chromium-pickle-js'; +import Filesystem from 'asar/lib/filesystem.js'; import VinylFile from 'vinyl'; import minimatch from 'minimatch'; -declare class AsarFilesystem { - readonly header: unknown; - constructor(src: string); - insertDirectory(path: string, shouldUnpack?: boolean): unknown; - insertFile(path: string, shouldUnpack: boolean, file: { stat: { size: number; mode: number } }, options: {}): Promise; -} - export function createAsar(folderPath: string, unpackGlobs: string[], skipGlobs: string[], duplicateGlobs: string[], destFilename: string): NodeJS.ReadWriteStream { const shouldUnpackFile = (file: VinylFile): boolean => { diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js index 95fe7a09bac..249777c4458 100644 --- a/build/lib/builtInExtensions.js +++ b/build/lib/builtInExtensions.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -38,10 +42,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.getExtensionStream = getExtensionStream; exports.getBuiltInExtensions = getBuiltInExtensions; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const os_1 = __importDefault(require("os")); diff --git a/build/lib/builtInExtensionsCG.js b/build/lib/builtInExtensionsCG.js index 70546237ba4..3dc0ae27f0a 100644 --- a/build/lib/builtInExtensionsCG.js +++ b/build/lib/builtInExtensionsCG.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const url_1 = __importDefault(require("url")); diff --git a/build/lib/bundle.js b/build/lib/bundle.js index 08f29d10847..382b648defb 100644 --- a/build/lib/bundle.js +++ b/build/lib/bundle.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.removeAllTSBoilerplate = removeAllTSBoilerplate; function removeAllTSBoilerplate(source) { diff --git a/build/lib/compilation.js b/build/lib/compilation.js index fb326dfd2b1..5d4fd4a90b2 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -41,10 +45,6 @@ exports.createCompile = createCompile; exports.transpileTask = transpileTask; exports.compileTask = compileTask; exports.watchTask = watchTask; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const fs_1 = __importDefault(require("fs")); const gulp_1 = __importDefault(require("gulp")); @@ -59,8 +59,9 @@ const os_1 = __importDefault(require("os")); const vinyl_1 = __importDefault(require("vinyl")); const task = __importStar(require("./task")); const index_1 = require("./mangle/index"); -const ts = require("typescript"); -const watch = require('./watch'); +const typescript_1 = __importDefault(require("typescript")); +const watch_1 = __importDefault(require("./watch")); +const gulp_bom_1 = __importDefault(require("gulp-bom")); // --- gulp-tsb: compile and transpile -------------------------------- const reporter = (0, reporter_1.createReporter)(); function getTypeScriptCompilerOptions(src) { @@ -91,14 +92,13 @@ function createCompile(src, { build, emitError, transpileOnly, preserveEnglish } transpileWithEsbuild: typeof transpileOnly !== 'boolean' && transpileOnly.esbuild }, err => reporter(err)); function pipeline(token) { - const bom = require('gulp-bom'); const tsFilter = util.filter(data => /\.ts$/.test(data.path)); const isUtf8Test = (f) => /(\/|\\)test(\/|\\).*utf8/.test(f.path); const isRuntimeJs = (f) => f.path.endsWith('.js') && !f.path.includes('fixtures'); const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path))); const input = event_stream_1.default.through(); const output = input - .pipe(util.$if(isUtf8Test, bom())) // this is required to preserve BOM in test files that loose it otherwise + .pipe(util.$if(isUtf8Test, (0, gulp_bom_1.default)())) // this is required to preserve BOM in test files that loose it otherwise .pipe(util.$if(!build && isRuntimeJs, util.appendOwnPathSourceURL())) .pipe(tsFilter) .pipe(util.loadSourcemaps()) @@ -149,7 +149,7 @@ function compileTask(src, out, build, options = {}) { let ts2tsMangler = new index_1.Mangler(compile.projectPath, (...data) => (0, fancy_log_1.default)(ansi_colors_1.default.blue('[mangler]'), ...data), { mangleExports: true, manglePrivateFields: true }); const newContentsByFileName = ts2tsMangler.computeNewFileContents(new Set(['saveState'])); mangleStream = event_stream_1.default.through(async function write(data) { - const tsNormalPath = ts.normalizePath(data.path); + const tsNormalPath = typescript_1.default.normalizePath(data.path); const newContents = (await newContentsByFileName).get(tsNormalPath); if (newContents !== undefined) { data.contents = Buffer.from(newContents.out); @@ -176,7 +176,7 @@ function watchTask(out, build, srcPath = 'src') { const task = () => { const compile = createCompile(srcPath, { build, emitError: false, transpileOnly: false, preserveEnglish: false }); const src = gulp_1.default.src(`${srcPath}/**`, { base: srcPath }); - const watchSrc = watch(`${srcPath}/**`, { base: srcPath, readDelay: 200 }); + const watchSrc = (0, watch_1.default)(`${srcPath}/**`, { base: srcPath, readDelay: 200 }); const generator = new MonacoGenerator(true); generator.execute(); return watchSrc @@ -333,7 +333,7 @@ exports.watchApiProposalNamesTask = task.define('watch-api-proposal-names', () = const task = () => gulp_1.default.src('src/vscode-dts/**') .pipe(generateApiProposalNames()) .pipe(apiProposalNamesReporter.end(true)); - return watch('src/vscode-dts/**', { readDelay: 200 }) + return (0, watch_1.default)('src/vscode-dts/**', { readDelay: 200 }) .pipe(util.debounce(task)) .pipe(gulp_1.default.dest('src')); }); diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index a8b72914925..53e37d82aa4 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -18,8 +18,9 @@ import File from 'vinyl'; import * as task from './task'; import { Mangler } from './mangle/index'; import { RawSourceMap } from 'source-map'; -import ts = require('typescript'); -const watch = require('./watch'); +import ts from 'typescript'; +import watch from './watch'; +import bom from 'gulp-bom'; // --- gulp-tsb: compile and transpile -------------------------------- @@ -66,7 +67,6 @@ export function createCompile(src: string, { build, emitError, transpileOnly, pr }, err => reporter(err)); function pipeline(token?: util.ICancellationToken) { - const bom = require('gulp-bom') as typeof import('gulp-bom'); const tsFilter = util.filter(data => /\.ts$/.test(data.path)); const isUtf8Test = (f: File) => /(\/|\\)test(\/|\\).*utf8/.test(f.path); diff --git a/build/lib/date.js b/build/lib/date.js index d189815ab06..1ed884fb7ee 100644 --- a/build/lib/date.js +++ b/build/lib/date.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.writeISODate = writeISODate; exports.readISODate = readISODate; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const root = path_1.default.join(__dirname, '..', '..'); diff --git a/build/lib/dependencies.js b/build/lib/dependencies.js index c6baaafa070..04a09f98708 100644 --- a/build/lib/dependencies.js +++ b/build/lib/dependencies.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getProductionDependencies = getProductionDependencies; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const child_process_1 = __importDefault(require("child_process")); diff --git a/build/lib/electron.js b/build/lib/electron.js index 0602307f4c3..79f6d515636 100644 --- a/build/lib/electron.js +++ b/build/lib/electron.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -37,10 +41,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.config = void 0; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const vinyl_fs_1 = __importDefault(require("vinyl-fs")); @@ -123,7 +123,7 @@ exports.config = { tag: product.electronRepository ? `v${electronVersion}-${msBuildId}` : undefined, productAppName: product.nameLong, companyName: 'Microsoft Corporation', - copyright: 'Copyright (C) 2024 Microsoft. All rights reserved', + copyright: 'Copyright (C) 2025 Microsoft. All rights reserved', darwinIcon: 'resources/darwin/code.icns', darwinBundleIdentifier: product.darwinBundleIdentifier, darwinApplicationCategoryType: 'public.app-category.developer-tools', diff --git a/build/lib/electron.ts b/build/lib/electron.ts index 3bb047dfcee..08ba68e1b89 100644 --- a/build/lib/electron.ts +++ b/build/lib/electron.ts @@ -104,7 +104,7 @@ export const config = { tag: product.electronRepository ? `v${electronVersion}-${msBuildId}` : undefined, productAppName: product.nameLong, companyName: 'Microsoft Corporation', - copyright: 'Copyright (C) 2024 Microsoft. All rights reserved', + copyright: 'Copyright (C) 2025 Microsoft. All rights reserved', darwinIcon: 'resources/darwin/code.icns', darwinBundleIdentifier: product.darwinBundleIdentifier, darwinApplicationCategoryType: 'public.app-category.developer-tools', diff --git a/build/lib/extensions.js b/build/lib/extensions.js index c80a1be1a84..e3736888924 100644 --- a/build/lib/extensions.js +++ b/build/lib/extensions.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -47,10 +51,6 @@ exports.scanBuiltinExtensions = scanBuiltinExtensions; exports.translatePackageJSON = translatePackageJSON; exports.webpackExtensions = webpackExtensions; exports.buildExtensionMedia = buildExtensionMedia; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const fs_1 = __importDefault(require("fs")); const child_process_1 = __importDefault(require("child_process")); diff --git a/build/lib/fetch.js b/build/lib/fetch.js index e4705101569..b0876cda75a 100644 --- a/build/lib/fetch.js +++ b/build/lib/fetch.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -6,10 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchUrls = fetchUrls; exports.fetchUrl = fetchUrl; exports.fetchGithub = fetchGithub; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const vinyl_1 = __importDefault(require("vinyl")); const fancy_log_1 = __importDefault(require("fancy-log")); diff --git a/build/lib/getVersion.js b/build/lib/getVersion.js index 94744415d60..7606c17ab14 100644 --- a/build/lib/getVersion.js +++ b/build/lib/getVersion.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -34,10 +38,6 @@ var __importStar = (this && this.__importStar) || (function () { })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.getVersion = getVersion; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const git = __importStar(require("./git")); function getVersion(root) { let version = process.env['BUILD_SOURCEVERSION']; diff --git a/build/lib/i18n.js b/build/lib/i18n.js index a2d7e8720fd..0b371c8b812 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -11,10 +15,6 @@ exports.createXlfFilesForExtensions = createXlfFilesForExtensions; exports.createXlfFilesForIsl = createXlfFilesForIsl; exports.prepareI18nPackFiles = prepareI18nPackFiles; exports.prepareIslFiles = prepareIslFiles; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const event_stream_1 = require("event-stream"); @@ -41,11 +41,12 @@ exports.defaultLanguages = [ { id: 'ru', folderName: 'rus' }, { id: 'it', folderName: 'ita' } ]; -// languages requested by the community to non-stable builds +// languages requested by the community exports.extraLanguages = [ { id: 'pt-br', folderName: 'ptb' }, - { id: 'hu', folderName: 'hun' }, - { id: 'tr', folderName: 'trk' } + { id: 'tr', folderName: 'trk' }, + { id: 'cs' }, + { id: 'pl' } ]; var LocalizeInfo; (function (LocalizeInfo) { diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index b4766f725b7..4506b2e3cd0 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -44,11 +44,12 @@ export const defaultLanguages: Language[] = [ { id: 'it', folderName: 'ita' } ]; -// languages requested by the community to non-stable builds +// languages requested by the community export const extraLanguages: Language[] = [ { id: 'pt-br', folderName: 'ptb' }, - { id: 'hu', folderName: 'hun' }, - { id: 'tr', folderName: 'trk' } + { id: 'tr', folderName: 'trk' }, + { id: 'cs' }, + { id: 'pl' } ]; interface Item { diff --git a/build/lib/inlineMeta.js b/build/lib/inlineMeta.js index b997f5e9a78..3b473ae091e 100644 --- a/build/lib/inlineMeta.js +++ b/build/lib/inlineMeta.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.inlineMeta = inlineMeta; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const path_1 = require("path"); const packageJsonMarkerId = 'BUILD_INSERT_PACKAGE_CONFIGURATION'; diff --git a/build/lib/mangle/index.js b/build/lib/mangle/index.js index 40a9f7bbe66..fa729052f7c 100644 --- a/build/lib/mangle/index.js +++ b/build/lib/mangle/index.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Mangler = void 0; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const node_v8_1 = __importDefault(require("node:v8")); const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); @@ -63,10 +63,10 @@ class ClassData { parent; children; constructor(fileName, node) { - this.fileName = fileName; - this.node = node; // analyse all fields (properties and methods). Find usages of all protected and // private ones and keep track of all public ones (to prevent naming collisions) + this.fileName = fileName; + this.node = node; const candidates = []; for (const member of node.members) { if (typescript_1.default.isMethodDeclaration(member)) { diff --git a/build/lib/mangle/renameWorker.js b/build/lib/mangle/renameWorker.js index d34e0a2346f..8bd59a4e2d5 100644 --- a/build/lib/mangle/renameWorker.js +++ b/build/lib/mangle/renameWorker.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const typescript_1 = __importDefault(require("typescript")); const workerpool_1 = __importDefault(require("workerpool")); const staticLanguageServiceHost_1 = require("./staticLanguageServiceHost"); diff --git a/build/lib/mangle/staticLanguageServiceHost.js b/build/lib/mangle/staticLanguageServiceHost.js index e17846f717f..7777888dd06 100644 --- a/build/lib/mangle/staticLanguageServiceHost.js +++ b/build/lib/mangle/staticLanguageServiceHost.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StaticLanguageServiceHost = void 0; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const typescript_1 = __importDefault(require("typescript")); const path_1 = __importDefault(require("path")); class StaticLanguageServiceHost { diff --git a/build/lib/monaco-api.js b/build/lib/monaco-api.js index 3d9a4c7ca10..1112b47370d 100644 --- a/build/lib/monaco-api.js +++ b/build/lib/monaco-api.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -6,10 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0; exports.run3 = run3; exports.execute = execute; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const fancy_log_1 = __importDefault(require("fancy-log")); diff --git a/build/lib/nls.js b/build/lib/nls.js index 492dbdae8ce..55984151ddb 100644 --- a/build/lib/nls.js +++ b/build/lib/nls.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; diff --git a/build/lib/node.js b/build/lib/node.js index 62533fbe6ca..01a381183ff 100644 --- a/build/lib/node.js +++ b/build/lib/node.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const fs_1 = __importDefault(require("fs")); const root = path_1.default.dirname(path_1.default.dirname(__dirname)); diff --git a/build/lib/optimize.js b/build/lib/optimize.js index fbc455b1cd1..2ba72a97159 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -38,10 +42,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.bundleTask = bundleTask; exports.minifyTask = minifyTask; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const gulp_1 = __importDefault(require("gulp")); const gulp_filter_1 = __importDefault(require("gulp-filter")); @@ -54,6 +54,7 @@ const esbuild_1 = __importDefault(require("esbuild")); const gulp_sourcemaps_1 = __importDefault(require("gulp-sourcemaps")); const fancy_log_1 = __importDefault(require("fancy-log")); const ansi_colors_1 = __importDefault(require("ansi-colors")); +const tsconfigUtils_1 = require("./tsconfigUtils"); const REPO_ROOT_PATH = path_1.default.join(__dirname, '../..'); const DEFAULT_FILE_HEADER = [ '/*!--------------------------------------------------------', @@ -63,6 +64,7 @@ const DEFAULT_FILE_HEADER = [ function bundleESMTask(opts) { const resourcesStream = event_stream_1.default.through(); // this stream will contain the resources const bundlesStream = event_stream_1.default.through(); // this stream will contain the bundled files + const target = getBuildTarget(); const entryPoints = opts.entryPoints.map(entryPoint => { if (typeof entryPoint === 'string') { return { name: path_1.default.parse(entryPoint).name }; @@ -125,7 +127,7 @@ function bundleESMTask(opts) { format: 'esm', sourcemap: 'external', plugins: [contentsMapper, externalOverride], - target: ['es2022'], + target: [target], loader: { '.ttf': 'file', '.svg': 'file', @@ -185,6 +187,7 @@ function bundleTask(opts) { } function minifyTask(src, sourceMapBaseUrl) { const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined; + const target = getBuildTarget(); return cb => { const svgmin = require('gulp-svgmin'); const esbuildFilter = (0, gulp_filter_1.default)('**/*.{js,css}', { restore: true }); @@ -197,7 +200,7 @@ function minifyTask(src, sourceMapBaseUrl) { outdir: '.', packages: 'external', // "external all the things", see https://esbuild.github.io/api/#packages platform: 'neutral', // makes esm - target: ['es2022'], + target: [target], write: false, }).then(res => { const jsOrCSSFile = res.outputFiles.find(f => /\.(js|css)$/.test(f.path)); @@ -221,4 +224,8 @@ function minifyTask(src, sourceMapBaseUrl) { }), gulp_1.default.dest(src + '-min'), (err) => cb(err)); }; } +function getBuildTarget() { + const tsconfigPath = path_1.default.join(REPO_ROOT_PATH, 'src', 'tsconfig.base.json'); + return (0, tsconfigUtils_1.getTargetStringFromTsConfig)(tsconfigPath); +} //# sourceMappingURL=optimize.js.map \ No newline at end of file diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index 7dde3204703..1e824a54106 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -15,6 +15,7 @@ import esbuild from 'esbuild'; import sourcemaps from 'gulp-sourcemaps'; import fancyLog from 'fancy-log'; import ansiColors from 'ansi-colors'; +import { getTargetStringFromTsConfig } from './tsconfigUtils'; declare module 'gulp-sourcemaps' { interface WriteOptions { @@ -64,6 +65,8 @@ function bundleESMTask(opts: IBundleESMTaskOpts): NodeJS.ReadWriteStream { const resourcesStream = es.through(); // this stream will contain the resources const bundlesStream = es.through(); // this stream will contain the bundled files + const target = getBuildTarget(); + const entryPoints = opts.entryPoints.map(entryPoint => { if (typeof entryPoint === 'string') { return { name: path.parse(entryPoint).name }; @@ -137,7 +140,7 @@ function bundleESMTask(opts: IBundleESMTaskOpts): NodeJS.ReadWriteStream { format: 'esm', sourcemap: 'external', plugins: [contentsMapper, externalOverride], - target: ['es2022'], + target: [target], loader: { '.ttf': 'file', '.svg': 'file', @@ -221,6 +224,7 @@ export function bundleTask(opts: IBundleESMTaskOpts): () => NodeJS.ReadWriteStre export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void { const sourceMappingURL = sourceMapBaseUrl ? ((f: any) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined; + const target = getBuildTarget(); return cb => { const svgmin = require('gulp-svgmin') as typeof import('gulp-svgmin'); @@ -240,7 +244,7 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => outdir: '.', packages: 'external', // "external all the things", see https://esbuild.github.io/api/#packages platform: 'neutral', // makes esm - target: ['es2022'], + target: [target], write: false, }).then(res => { const jsOrCSSFile = res.outputFiles.find(f => /\.(js|css)$/.test(f.path))!; @@ -272,3 +276,9 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => (err: any) => cb(err)); }; } + +function getBuildTarget() { + const tsconfigPath = path.join(REPO_ROOT_PATH, 'src', 'tsconfig.base.json'); + return getTargetStringFromTsConfig(tsconfigPath); +} + diff --git a/build/lib/policies.js b/build/lib/policies.js deleted file mode 100644 index d2ef760870d..00000000000 --- a/build/lib/policies.js +++ /dev/null @@ -1,887 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -const child_process_1 = require("child_process"); -const fs_1 = require("fs"); -const path_1 = __importDefault(require("path")); -const byline_1 = __importDefault(require("byline")); -const ripgrep_1 = require("@vscode/ripgrep"); -const tree_sitter_1 = __importDefault(require("tree-sitter")); -const { typescript } = require('tree-sitter-typescript'); -const product = require('../../product.json'); -const packageJson = require('../../package.json'); -function isNlsString(value) { - return value ? typeof value !== 'string' : false; -} -function isStringArray(value) { - return !value.some(s => isNlsString(s)); -} -function isNlsStringArray(value) { - return value.every(s => isNlsString(s)); -} -var PolicyType; -(function (PolicyType) { - PolicyType["Boolean"] = "boolean"; - PolicyType["Number"] = "number"; - PolicyType["Object"] = "object"; - PolicyType["String"] = "string"; - PolicyType["StringEnum"] = "stringEnum"; -})(PolicyType || (PolicyType = {})); -function renderADMLString(prefix, moduleName, nlsString, translations) { - let value; - if (translations) { - const moduleTranslations = translations[moduleName]; - if (moduleTranslations) { - value = moduleTranslations[nlsString.nlsKey]; - } - } - if (!value) { - value = nlsString.value; - } - return `${value}`; -} -function renderProfileString(_prefix, moduleName, nlsString, translations) { - let value; - if (translations) { - const moduleTranslations = translations[moduleName]; - if (moduleTranslations) { - value = moduleTranslations[nlsString.nlsKey]; - } - } - if (!value) { - value = nlsString.value; - } - return value; -} -class BasePolicy { - type; - name; - category; - minimumVersion; - description; - moduleName; - constructor(type, name, category, minimumVersion, description, moduleName) { - this.type = type; - this.name = name; - this.category = category; - this.minimumVersion = minimumVersion; - this.description = description; - this.moduleName = moduleName; - } - renderADMLString(nlsString, translations) { - return renderADMLString(this.name, this.moduleName, nlsString, translations); - } - renderADMX(regKey) { - return [ - ``, - ` `, - ` `, - ` `, - ...this.renderADMXElements(), - ` `, - `` - ]; - } - renderADMLStrings(translations) { - return [ - `${this.name}`, - this.renderADMLString(this.description, translations) - ]; - } - renderADMLPresentation() { - return `${this.renderADMLPresentationContents()}`; - } - renderProfile() { - return [`${this.name}`, this.renderProfileValue()]; - } - renderProfileManifest(translations) { - return ` -${this.renderProfileManifestValue(translations)} -`; - } -} -class BooleanPolicy extends BasePolicy { - static from(name, category, minimumVersion, description, moduleName, settingNode) { - const type = getStringProperty(moduleName, settingNode, 'type'); - if (type !== 'boolean') { - return undefined; - } - return new BooleanPolicy(name, category, minimumVersion, description, moduleName); - } - constructor(name, category, minimumVersion, description, moduleName) { - super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName); - } - renderADMXElements() { - return [ - ``, - ` `, - `` - ]; - } - renderADMLPresentationContents() { - return `${this.name}`; - } - renderProfileValue() { - return ``; - } - renderProfileManifestValue(translations) { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -boolean`; - } -} -class ParseError extends Error { - constructor(message, moduleName, node) { - super(`${message}. ${moduleName}.ts:${node.startPosition.row + 1}`); - } -} -class NumberPolicy extends BasePolicy { - defaultValue; - static from(name, category, minimumVersion, description, moduleName, settingNode) { - const type = getStringProperty(moduleName, settingNode, 'type'); - if (type !== 'number') { - return undefined; - } - const defaultValue = getNumberProperty(moduleName, settingNode, 'default'); - if (typeof defaultValue === 'undefined') { - throw new ParseError(`Missing required 'default' property.`, moduleName, settingNode); - } - return new NumberPolicy(name, category, minimumVersion, description, moduleName, defaultValue); - } - constructor(name, category, minimumVersion, description, moduleName, defaultValue) { - super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); - this.defaultValue = defaultValue; - } - renderADMXElements() { - return [ - `` - // `` - ]; - } - renderADMLPresentationContents() { - return `${this.name}`; - } - renderProfileValue() { - return `${this.defaultValue}`; - } - renderProfileManifestValue(translations) { - return `pfm_default -${this.defaultValue} -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -integer`; - } -} -class StringPolicy extends BasePolicy { - static from(name, category, minimumVersion, description, moduleName, settingNode) { - const type = getStringProperty(moduleName, settingNode, 'type'); - if (type !== 'string') { - return undefined; - } - return new StringPolicy(name, category, minimumVersion, description, moduleName); - } - constructor(name, category, minimumVersion, description, moduleName) { - super(PolicyType.String, name, category, minimumVersion, description, moduleName); - } - renderADMXElements() { - return [``]; - } - renderADMLPresentationContents() { - return ``; - } - renderProfileValue() { - return ``; - } - renderProfileManifestValue(translations) { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string`; - } -} -class ObjectPolicy extends BasePolicy { - static from(name, category, minimumVersion, description, moduleName, settingNode) { - const type = getStringProperty(moduleName, settingNode, 'type'); - if (type !== 'object' && type !== 'array') { - return undefined; - } - return new ObjectPolicy(name, category, minimumVersion, description, moduleName); - } - constructor(name, category, minimumVersion, description, moduleName) { - super(PolicyType.Object, name, category, minimumVersion, description, moduleName); - } - renderADMXElements() { - return [``]; - } - renderADMLPresentationContents() { - return ``; - } - renderProfileValue() { - return ``; - } - renderProfileManifestValue(translations) { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string -`; - } -} -class StringEnumPolicy extends BasePolicy { - enum_; - enumDescriptions; - static from(name, category, minimumVersion, description, moduleName, settingNode) { - const type = getStringProperty(moduleName, settingNode, 'type'); - if (type !== 'string') { - return undefined; - } - const enum_ = getStringArrayProperty(moduleName, settingNode, 'enum'); - if (!enum_) { - return undefined; - } - if (!isStringArray(enum_)) { - throw new ParseError(`Property 'enum' should not be localized.`, moduleName, settingNode); - } - const enumDescriptions = getStringArrayProperty(moduleName, settingNode, 'enumDescriptions'); - if (!enumDescriptions) { - throw new ParseError(`Missing required 'enumDescriptions' property.`, moduleName, settingNode); - } - else if (!isNlsStringArray(enumDescriptions)) { - throw new ParseError(`Property 'enumDescriptions' should be localized.`, moduleName, settingNode); - } - return new StringEnumPolicy(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions); - } - constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) { - super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); - this.enum_ = enum_; - this.enumDescriptions = enumDescriptions; - } - renderADMXElements() { - return [ - ``, - ...this.enum_.map((value, index) => ` ${value}`), - `` - ]; - } - renderADMLStrings(translations) { - return [ - ...super.renderADMLStrings(translations), - ...this.enumDescriptions.map(e => this.renderADMLString(e, translations)) - ]; - } - renderADMLPresentationContents() { - return ``; - } - renderProfileValue() { - return `${this.enum_[0]}`; - } - renderProfileManifestValue(translations) { - return `pfm_default -${this.enum_[0]} -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string -pfm_range_list - - ${this.enum_.map(e => `${e}`).join('\n ')} -`; - } -} -const NumberQ = { - Q: `(number) @value`, - value(matches) { - const match = matches[0]; - if (!match) { - return undefined; - } - const value = match.captures.filter(c => c.name === 'value')[0]?.node.text; - if (!value) { - throw new Error(`Missing required 'value' property.`); - } - return parseInt(value); - } -}; -const StringQ = { - Q: `[ - (string (string_fragment) @value) - (call_expression - function: [ - (identifier) @localizeFn (#eq? @localizeFn localize) - (member_expression - object: (identifier) @nlsObj (#eq? @nlsObj nls) - property: (property_identifier) @localizeFn (#eq? @localizeFn localize) - ) - ] - arguments: (arguments (string (string_fragment) @nlsKey) (string (string_fragment) @value)) - ) - ]`, - value(matches) { - const match = matches[0]; - if (!match) { - return undefined; - } - const value = match.captures.filter(c => c.name === 'value')[0]?.node.text; - if (!value) { - throw new Error(`Missing required 'value' property.`); - } - const nlsKey = match.captures.filter(c => c.name === 'nlsKey')[0]?.node.text; - if (nlsKey) { - return { value, nlsKey }; - } - else { - return value; - } - } -}; -const StringArrayQ = { - Q: `(array ${StringQ.Q})`, - value(matches) { - if (matches.length === 0) { - return undefined; - } - return matches.map(match => { - return StringQ.value([match]); - }); - } -}; -function getProperty(qtype, moduleName, node, key) { - const query = new tree_sitter_1.default.Query(typescript, `( - (pair - key: [(property_identifier)(string)] @key - value: ${qtype.Q} - ) - (#any-of? @key "${key}" "'${key}'") - )`); - try { - const matches = query.matches(node).filter(m => m.captures[0].node.parent?.parent === node); - return qtype.value(matches); - } - catch (e) { - throw new ParseError(e.message, moduleName, node); - } -} -function getNumberProperty(moduleName, node, key) { - return getProperty(NumberQ, moduleName, node, key); -} -function getStringProperty(moduleName, node, key) { - return getProperty(StringQ, moduleName, node, key); -} -function getStringArrayProperty(moduleName, node, key) { - return getProperty(StringArrayQ, moduleName, node, key); -} -// TODO: add more policy types -const PolicyTypes = [ - BooleanPolicy, - NumberPolicy, - StringEnumPolicy, - StringPolicy, - ObjectPolicy -]; -function getPolicy(moduleName, configurationNode, settingNode, policyNode, categories) { - const name = getStringProperty(moduleName, policyNode, 'name'); - if (!name) { - throw new ParseError(`Missing required 'name' property`, moduleName, policyNode); - } - else if (isNlsString(name)) { - throw new ParseError(`Property 'name' should be a literal string`, moduleName, policyNode); - } - const categoryName = getStringProperty(moduleName, configurationNode, 'title'); - if (!categoryName) { - throw new ParseError(`Missing required 'title' property`, moduleName, configurationNode); - } - else if (!isNlsString(categoryName)) { - throw new ParseError(`Property 'title' should be localized`, moduleName, configurationNode); - } - const categoryKey = `${categoryName.nlsKey}:${categoryName.value}`; - let category = categories.get(categoryKey); - if (!category) { - category = { moduleName, name: categoryName }; - categories.set(categoryKey, category); - } - const minimumVersion = getStringProperty(moduleName, policyNode, 'minimumVersion'); - if (!minimumVersion) { - throw new ParseError(`Missing required 'minimumVersion' property.`, moduleName, policyNode); - } - else if (isNlsString(minimumVersion)) { - throw new ParseError(`Property 'minimumVersion' should be a literal string.`, moduleName, policyNode); - } - const description = getStringProperty(moduleName, policyNode, 'description') ?? getStringProperty(moduleName, settingNode, 'description'); - if (!description) { - throw new ParseError(`Missing required 'description' property.`, moduleName, settingNode); - } - if (!isNlsString(description)) { - throw new ParseError(`Property 'description' should be localized.`, moduleName, settingNode); - } - let result; - for (const policyType of PolicyTypes) { - if (result = policyType.from(name, category, minimumVersion, description, moduleName, settingNode)) { - break; - } - } - if (!result) { - throw new ParseError(`Failed to parse policy '${name}'.`, moduleName, settingNode); - } - return result; -} -function getPolicies(moduleName, node) { - const query = new tree_sitter_1.default.Query(typescript, ` - ( - (call_expression - function: (member_expression property: (property_identifier) @registerConfigurationFn) (#eq? @registerConfigurationFn registerConfiguration) - arguments: (arguments (object (pair - key: [(property_identifier)(string)] @propertiesKey (#any-of? @propertiesKey "properties" "'properties'") - value: (object (pair - key: [(property_identifier)(string)(computed_property_name)] - value: (object (pair - key: [(property_identifier)(string)] @policyKey (#any-of? @policyKey "policy" "'policy'") - value: (object) @policy - )) @setting - )) - )) @configuration) - ) - ) - `); - const categories = new Map(); - return query.matches(node).map(m => { - const configurationNode = m.captures.filter(c => c.name === 'configuration')[0].node; - const settingNode = m.captures.filter(c => c.name === 'setting')[0].node; - const policyNode = m.captures.filter(c => c.name === 'policy')[0].node; - return getPolicy(moduleName, configurationNode, settingNode, policyNode, categories); - }); -} -async function getFiles(root) { - return new Promise((c, e) => { - const result = []; - const rg = (0, child_process_1.spawn)(ripgrep_1.rgPath, ['-l', 'registerConfiguration\\(', '-g', 'src/**/*.ts', '-g', '!src/**/test/**', root]); - const stream = (0, byline_1.default)(rg.stdout.setEncoding('utf8')); - stream.on('data', path => result.push(path)); - stream.on('error', err => e(err)); - stream.on('end', () => c(result)); - }); -} -function renderADMX(regKey, versions, categories, policies) { - versions = versions.map(v => v.replace(/\./g, '_')); - return ` - - - - - - - - ${versions.map(v => ``).join(`\n `)} - - - - - ${categories.map(c => ``).join(`\n `)} - - - ${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)} - - -`; -} -function renderADML(appName, versions, categories, policies, translations) { - return ` - - - - - - ${appName} - ${versions.map(v => `${appName} >= ${v}`).join(`\n `)} - ${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)} - ${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)} - - - ${policies.map(p => p.renderADMLPresentation()).join(`\n `)} - - - -`; -} -function renderProfileManifest(appName, bundleIdentifier, _versions, _categories, policies, translations) { - const requiredPayloadFields = ` - - pfm_default - Configure ${appName} - pfm_name - PayloadDescription - pfm_title - Payload Description - pfm_type - string - - - pfm_default - ${appName} - pfm_name - PayloadDisplayName - pfm_require - always - pfm_title - Payload Display Name - pfm_type - string - - - pfm_default - ${bundleIdentifier} - pfm_name - PayloadIdentifier - pfm_require - always - pfm_title - Payload Identifier - pfm_type - string - - - pfm_default - ${bundleIdentifier} - pfm_name - PayloadType - pfm_require - always - pfm_title - Payload Type - pfm_type - string - - - pfm_default - - pfm_name - PayloadUUID - pfm_require - always - pfm_title - Payload UUID - pfm_type - string - - - pfm_default - 1 - pfm_name - PayloadVersion - pfm_range_list - - 1 - - pfm_require - always - pfm_title - Payload Version - pfm_type - integer - - - pfm_default - Microsoft - pfm_name - PayloadOrganization - pfm_title - Payload Organization - pfm_type - string - `; - const profileManifestSubkeys = policies.map(policy => { - return policy.renderProfileManifest(translations); - }).join(''); - return ` - - - - pfm_app_url - https://code.visualstudio.com/ - pfm_description - ${appName} Managed Settings - pfm_documentation_url - https://code.visualstudio.com/docs/setup/enterprise - pfm_domain - ${bundleIdentifier} - pfm_format_version - 1 - pfm_interaction - combined - pfm_last_modified - ${new Date().toISOString().replace(/\.\d+Z$/, 'Z')} - pfm_platforms - - macOS - - pfm_subkeys - - ${requiredPayloadFields} - ${profileManifestSubkeys} - - pfm_title - ${appName} - pfm_unique - - pfm_version - 1 - -`; -} -function renderMacOSPolicy(policies, translations) { - const appName = product.nameLong; - const bundleIdentifier = product.darwinBundleIdentifier; - const payloadUUID = product.darwinProfilePayloadUUID; - const UUID = product.darwinProfileUUID; - const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); - const categories = [...new Set(policies.map(p => p.category))]; - const policyEntries = policies.map(policy => policy.renderProfile()) - .flat() - .map(entry => `\t\t\t\t${entry}`) - .join('\n'); - return { - profile: ` - - - - PayloadContent - - - PayloadDisplayName - ${appName} - PayloadIdentifier - ${bundleIdentifier}.${UUID} - PayloadType - ${bundleIdentifier} - PayloadUUID - ${UUID} - PayloadVersion - 1 -${policyEntries} - - - PayloadDescription - This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise - PayloadDisplayName - ${appName} - PayloadIdentifier - ${bundleIdentifier} - PayloadOrganization - Microsoft - PayloadType - Configuration - PayloadUUID - ${payloadUUID} - PayloadVersion - 1 - TargetDeviceType - 5 - -`, - manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) }, - ...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) })) - ] - }; -} -function renderGP(policies, translations) { - const appName = product.nameLong; - const regKey = product.win32RegValueName; - const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); - const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))]; - return { - admx: renderADMX(regKey, versions, categories, policies), - adml: [ - { languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) }, - ...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) })) - ] - }; -} -const Languages = { - 'fr': 'fr-fr', - 'it': 'it-it', - 'de': 'de-de', - 'es': 'es-es', - 'ru': 'ru-ru', - 'zh-hans': 'zh-cn', - 'zh-hant': 'zh-tw', - 'ja': 'ja-jp', - 'ko': 'ko-kr', - 'cs': 'cs-cz', - 'pt-br': 'pt-br', - 'tr': 'tr-tr', - 'pl': 'pl-pl', -}; -async function getSpecificNLS(resourceUrlTemplate, languageId, version) { - const resource = { - publisher: 'ms-ceintl', - name: `vscode-language-pack-${languageId}`, - version: `${version[0]}.${version[1]}.${version[2]}`, - path: 'extension/translations/main.i18n.json' - }; - const url = resourceUrlTemplate.replace(/\{([^}]+)\}/g, (_, key) => resource[key]); - const res = await fetch(url); - if (res.status !== 200) { - throw new Error(`[${res.status}] Error downloading language pack ${languageId}@${version}`); - } - const { contents: result } = await res.json(); - return result; -} -function parseVersion(version) { - const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)/.exec(version); - return [parseInt(major), parseInt(minor), parseInt(patch)]; -} -function compareVersions(a, b) { - if (a[0] !== b[0]) { - return a[0] - b[0]; - } - if (a[1] !== b[1]) { - return a[1] - b[1]; - } - return a[2] - b[2]; -} -async function queryVersions(serviceUrl, languageId) { - const res = await fetch(`${serviceUrl}/extensionquery`, { - method: 'POST', - headers: { - 'Accept': 'application/json;api-version=3.0-preview.1', - 'Content-Type': 'application/json', - 'User-Agent': 'VS Code Build', - }, - body: JSON.stringify({ - filters: [{ criteria: [{ filterType: 7, value: `ms-ceintl.vscode-language-pack-${languageId}` }] }], - flags: 0x1 - }) - }); - if (res.status !== 200) { - throw new Error(`[${res.status}] Error querying for extension: ${languageId}`); - } - const result = await res.json(); - return result.results[0].extensions[0].versions.map(v => parseVersion(v.version)).sort(compareVersions); -} -async function getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) { - const versions = await queryVersions(extensionGalleryServiceUrl, languageId); - const nextMinor = [version[0], version[1] + 1, 0]; - const compatibleVersions = versions.filter(v => compareVersions(v, nextMinor) < 0); - const latestCompatibleVersion = compatibleVersions.at(-1); // order is newest to oldest - if (!latestCompatibleVersion) { - throw new Error(`No compatible language pack found for ${languageId} for version ${version}`); - } - return await getSpecificNLS(resourceUrlTemplate, languageId, latestCompatibleVersion); -} -async function parsePolicies() { - const parser = new tree_sitter_1.default(); - parser.setLanguage(typescript); - const files = await getFiles(process.cwd()); - const base = path_1.default.join(process.cwd(), 'src'); - const policies = []; - for (const file of files) { - const moduleName = path_1.default.relative(base, file).replace(/\.ts$/i, '').replace(/\\/g, '/'); - const contents = await fs_1.promises.readFile(file, { encoding: 'utf8' }); - const tree = parser.parse(contents); - policies.push(...getPolicies(moduleName, tree.rootNode)); - } - return policies; -} -async function getTranslations() { - const extensionGalleryServiceUrl = product.extensionsGallery?.serviceUrl; - if (!extensionGalleryServiceUrl) { - console.warn(`Skipping policy localization: No 'extensionGallery.serviceUrl' found in 'product.json'.`); - return []; - } - const resourceUrlTemplate = product.extensionsGallery?.resourceUrlTemplate; - if (!resourceUrlTemplate) { - console.warn(`Skipping policy localization: No 'resourceUrlTemplate' found in 'product.json'.`); - return []; - } - const version = parseVersion(packageJson.version); - const languageIds = Object.keys(Languages); - return await Promise.all(languageIds.map(languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) - .then(languageTranslations => ({ languageId, languageTranslations })))); -} -async function windowsMain(policies, translations) { - const root = '.build/policies/win32'; - const { admx, adml } = await renderGP(policies, translations); - await fs_1.promises.rm(root, { recursive: true, force: true }); - await fs_1.promises.mkdir(root, { recursive: true }); - await fs_1.promises.writeFile(path_1.default.join(root, `${product.win32RegValueName}.admx`), admx.replace(/\r?\n/g, '\n')); - for (const { languageId, contents } of adml) { - const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId]); - await fs_1.promises.mkdir(languagePath, { recursive: true }); - await fs_1.promises.writeFile(path_1.default.join(languagePath, `${product.win32RegValueName}.adml`), contents.replace(/\r?\n/g, '\n')); - } -} -async function darwinMain(policies, translations) { - const bundleIdentifier = product.darwinBundleIdentifier; - if (!bundleIdentifier || !product.darwinProfilePayloadUUID || !product.darwinProfileUUID) { - throw new Error(`Missing required product information.`); - } - const root = '.build/policies/darwin'; - const { profile, manifests } = await renderMacOSPolicy(policies, translations); - await fs_1.promises.rm(root, { recursive: true, force: true }); - await fs_1.promises.mkdir(root, { recursive: true }); - await fs_1.promises.writeFile(path_1.default.join(root, `${bundleIdentifier}.mobileconfig`), profile.replace(/\r?\n/g, '\n')); - for (const { languageId, contents } of manifests) { - const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId]); - await fs_1.promises.mkdir(languagePath, { recursive: true }); - await fs_1.promises.writeFile(path_1.default.join(languagePath, `${bundleIdentifier}.plist`), contents.replace(/\r?\n/g, '\n')); - } -} -async function main() { - const [policies, translations] = await Promise.all([parsePolicies(), getTranslations()]); - const platform = process.argv[2]; - if (platform === 'darwin') { - await darwinMain(policies, translations); - } - else if (platform === 'win32') { - await windowsMain(policies, translations); - } - else { - console.error(`Usage: node build/lib/policies `); - process.exit(1); - } -} -if (require.main === module) { - main().catch(err => { - if (err instanceof ParseError) { - console.error(`Parse Error:`, err.message); - } - else { - console.error(err); - } - process.exit(1); - }); -} -//# sourceMappingURL=policies.js.map \ No newline at end of file diff --git a/build/lib/policies.ts b/build/lib/policies.ts deleted file mode 100644 index 381d2f4c1ac..00000000000 --- a/build/lib/policies.ts +++ /dev/null @@ -1,1137 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { spawn } from 'child_process'; -import { promises as fs } from 'fs'; -import path from 'path'; -import byline from 'byline'; -import { rgPath } from '@vscode/ripgrep'; -import Parser from 'tree-sitter'; -const { typescript } = require('tree-sitter-typescript'); -const product = require('../../product.json'); -const packageJson = require('../../package.json'); - -type NlsString = { value: string; nlsKey: string }; - -function isNlsString(value: string | NlsString | undefined): value is NlsString { - return value ? typeof value !== 'string' : false; -} - -function isStringArray(value: (string | NlsString)[]): value is string[] { - return !value.some(s => isNlsString(s)); -} - -function isNlsStringArray(value: (string | NlsString)[]): value is NlsString[] { - return value.every(s => isNlsString(s)); -} - -interface Category { - readonly moduleName: string; - readonly name: NlsString; -} - -enum PolicyType { - Boolean = 'boolean', - Number = 'number', - Object = 'object', - String = 'string', - StringEnum = 'stringEnum', -} - -interface Policy { - readonly name: string; - readonly type: PolicyType; - readonly category: Category; - readonly minimumVersion: string; - renderADMX(regKey: string): string[]; - renderADMLStrings(translations?: LanguageTranslations): string[]; - renderADMLPresentation(): string; - renderProfile(): string[]; - // https://github.com/ProfileManifests/ProfileManifests/wiki/Manifest-Format - renderProfileManifest(translations?: LanguageTranslations): string; -} - -function renderADMLString(prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string { - let value: string | undefined; - - if (translations) { - const moduleTranslations = translations[moduleName]; - - if (moduleTranslations) { - value = moduleTranslations[nlsString.nlsKey]; - } - } - - if (!value) { - value = nlsString.value; - } - - return `${value}`; -} - -function renderProfileString(_prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string { - let value: string | undefined; - - if (translations) { - const moduleTranslations = translations[moduleName]; - - if (moduleTranslations) { - value = moduleTranslations[nlsString.nlsKey]; - } - } - - if (!value) { - value = nlsString.value; - } - - return value; -} - -abstract class BasePolicy implements Policy { - constructor( - readonly type: PolicyType, - readonly name: string, - readonly category: Category, - readonly minimumVersion: string, - protected description: NlsString, - protected moduleName: string, - ) { } - - protected renderADMLString(nlsString: NlsString, translations?: LanguageTranslations): string { - return renderADMLString(this.name, this.moduleName, nlsString, translations); - } - - renderADMX(regKey: string) { - return [ - ``, - ` `, - ` `, - ` `, - ...this.renderADMXElements(), - ` `, - `` - ]; - } - - protected abstract renderADMXElements(): string[]; - - renderADMLStrings(translations?: LanguageTranslations) { - return [ - `${this.name}`, - this.renderADMLString(this.description, translations) - ]; - } - - renderADMLPresentation(): string { - return `${this.renderADMLPresentationContents()}`; - } - - protected abstract renderADMLPresentationContents(): string; - - renderProfile() { - return [`${this.name}`, this.renderProfileValue()]; - } - - renderProfileManifest(translations?: LanguageTranslations): string { - return ` -${this.renderProfileManifestValue(translations)} -`; - } - - abstract renderProfileValue(): string; - abstract renderProfileManifestValue(translations?: LanguageTranslations): string; -} - -class BooleanPolicy extends BasePolicy { - - static from( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - settingNode: Parser.SyntaxNode - ): BooleanPolicy | undefined { - const type = getStringProperty(moduleName, settingNode, 'type'); - - if (type !== 'boolean') { - return undefined; - } - - return new BooleanPolicy(name, category, minimumVersion, description, moduleName); - } - - private constructor( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - ) { - super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName); - } - - protected renderADMXElements(): string[] { - return [ - ``, - ` `, - `` - ]; - } - - renderADMLPresentationContents() { - return `${this.name}`; - } - - renderProfileValue(): string { - return ``; - } - - renderProfileManifestValue(translations?: LanguageTranslations): string { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -boolean`; - } -} - -class ParseError extends Error { - constructor(message: string, moduleName: string, node: Parser.SyntaxNode) { - super(`${message}. ${moduleName}.ts:${node.startPosition.row + 1}`); - } -} - -class NumberPolicy extends BasePolicy { - - static from( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - settingNode: Parser.SyntaxNode - ): NumberPolicy | undefined { - const type = getStringProperty(moduleName, settingNode, 'type'); - - if (type !== 'number') { - return undefined; - } - - const defaultValue = getNumberProperty(moduleName, settingNode, 'default'); - - if (typeof defaultValue === 'undefined') { - throw new ParseError(`Missing required 'default' property.`, moduleName, settingNode); - } - - return new NumberPolicy(name, category, minimumVersion, description, moduleName, defaultValue); - } - - private constructor( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - protected readonly defaultValue: number, - ) { - super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); - } - - protected renderADMXElements(): string[] { - return [ - `` - // `` - ]; - } - - renderADMLPresentationContents() { - return `${this.name}`; - } - - renderProfileValue() { - return `${this.defaultValue}`; - } - - renderProfileManifestValue(translations?: LanguageTranslations) { - return `pfm_default -${this.defaultValue} -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -integer`; - } -} - -class StringPolicy extends BasePolicy { - - static from( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - settingNode: Parser.SyntaxNode - ): StringPolicy | undefined { - const type = getStringProperty(moduleName, settingNode, 'type'); - - if (type !== 'string') { - return undefined; - } - - return new StringPolicy(name, category, minimumVersion, description, moduleName); - } - - private constructor( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - ) { - super(PolicyType.String, name, category, minimumVersion, description, moduleName); - } - - protected renderADMXElements(): string[] { - return [``]; - } - - renderADMLPresentationContents() { - return ``; - } - - renderProfileValue(): string { - return ``; - } - - renderProfileManifestValue(translations?: LanguageTranslations): string { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string`; - } -} - -class ObjectPolicy extends BasePolicy { - - static from( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - settingNode: Parser.SyntaxNode - ): ObjectPolicy | undefined { - const type = getStringProperty(moduleName, settingNode, 'type'); - - if (type !== 'object' && type !== 'array') { - return undefined; - } - - return new ObjectPolicy(name, category, minimumVersion, description, moduleName); - } - - private constructor( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - ) { - super(PolicyType.Object, name, category, minimumVersion, description, moduleName); - } - - protected renderADMXElements(): string[] { - return [``]; - } - - renderADMLPresentationContents() { - return ``; - } - - renderProfileValue(): string { - return ``; - } - - renderProfileManifestValue(translations?: LanguageTranslations): string { - return `pfm_default - -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string -`; - } -} - -class StringEnumPolicy extends BasePolicy { - - static from( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - settingNode: Parser.SyntaxNode - ): StringEnumPolicy | undefined { - const type = getStringProperty(moduleName, settingNode, 'type'); - - if (type !== 'string') { - return undefined; - } - - const enum_ = getStringArrayProperty(moduleName, settingNode, 'enum'); - - if (!enum_) { - return undefined; - } - - if (!isStringArray(enum_)) { - throw new ParseError(`Property 'enum' should not be localized.`, moduleName, settingNode); - } - - const enumDescriptions = getStringArrayProperty(moduleName, settingNode, 'enumDescriptions'); - - if (!enumDescriptions) { - throw new ParseError(`Missing required 'enumDescriptions' property.`, moduleName, settingNode); - } else if (!isNlsStringArray(enumDescriptions)) { - throw new ParseError(`Property 'enumDescriptions' should be localized.`, moduleName, settingNode); - } - - return new StringEnumPolicy(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions); - } - - private constructor( - name: string, - category: Category, - minimumVersion: string, - description: NlsString, - moduleName: string, - protected enum_: string[], - protected enumDescriptions: NlsString[], - ) { - super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); - } - - protected renderADMXElements(): string[] { - return [ - ``, - ...this.enum_.map((value, index) => ` ${value}`), - `` - ]; - } - - renderADMLStrings(translations?: LanguageTranslations) { - return [ - ...super.renderADMLStrings(translations), - ...this.enumDescriptions.map(e => this.renderADMLString(e, translations)) - ]; - } - - renderADMLPresentationContents() { - return ``; - } - - renderProfileValue() { - return `${this.enum_[0]}`; - } - - renderProfileManifestValue(translations?: LanguageTranslations): string { - return `pfm_default -${this.enum_[0]} -pfm_description -${renderProfileString(this.name, this.moduleName, this.description, translations)} -pfm_name -${this.name} -pfm_title -${this.name} -pfm_type -string -pfm_range_list - - ${this.enum_.map(e => `${e}`).join('\n ')} -`; - } -} - -interface QType { - Q: string; - value(matches: Parser.QueryMatch[]): T | undefined; -} - -const NumberQ: QType = { - Q: `(number) @value`, - - value(matches: Parser.QueryMatch[]): number | undefined { - const match = matches[0]; - - if (!match) { - return undefined; - } - - const value = match.captures.filter(c => c.name === 'value')[0]?.node.text; - - if (!value) { - throw new Error(`Missing required 'value' property.`); - } - - return parseInt(value); - } -}; - -const StringQ: QType = { - Q: `[ - (string (string_fragment) @value) - (call_expression - function: [ - (identifier) @localizeFn (#eq? @localizeFn localize) - (member_expression - object: (identifier) @nlsObj (#eq? @nlsObj nls) - property: (property_identifier) @localizeFn (#eq? @localizeFn localize) - ) - ] - arguments: (arguments (string (string_fragment) @nlsKey) (string (string_fragment) @value)) - ) - ]`, - - value(matches: Parser.QueryMatch[]): string | NlsString | undefined { - const match = matches[0]; - - if (!match) { - return undefined; - } - - const value = match.captures.filter(c => c.name === 'value')[0]?.node.text; - - if (!value) { - throw new Error(`Missing required 'value' property.`); - } - - const nlsKey = match.captures.filter(c => c.name === 'nlsKey')[0]?.node.text; - - if (nlsKey) { - return { value, nlsKey }; - } else { - return value; - } - } -}; - -const StringArrayQ: QType<(string | NlsString)[]> = { - Q: `(array ${StringQ.Q})`, - - value(matches: Parser.QueryMatch[]): (string | NlsString)[] | undefined { - if (matches.length === 0) { - return undefined; - } - - return matches.map(match => { - return StringQ.value([match]) as string | NlsString; - }); - } -}; - -function getProperty(qtype: QType, moduleName: string, node: Parser.SyntaxNode, key: string): T | undefined { - const query = new Parser.Query( - typescript, - `( - (pair - key: [(property_identifier)(string)] @key - value: ${qtype.Q} - ) - (#any-of? @key "${key}" "'${key}'") - )` - ); - - try { - const matches = query.matches(node).filter(m => m.captures[0].node.parent?.parent === node); - return qtype.value(matches); - } catch (e) { - throw new ParseError(e.message, moduleName, node); - } -} - -function getNumberProperty(moduleName: string, node: Parser.SyntaxNode, key: string): number | undefined { - return getProperty(NumberQ, moduleName, node, key); -} - -function getStringProperty(moduleName: string, node: Parser.SyntaxNode, key: string): string | NlsString | undefined { - return getProperty(StringQ, moduleName, node, key); -} - -function getStringArrayProperty(moduleName: string, node: Parser.SyntaxNode, key: string): (string | NlsString)[] | undefined { - return getProperty(StringArrayQ, moduleName, node, key); -} - -// TODO: add more policy types -const PolicyTypes = [ - BooleanPolicy, - NumberPolicy, - StringEnumPolicy, - StringPolicy, - ObjectPolicy -]; - -function getPolicy( - moduleName: string, - configurationNode: Parser.SyntaxNode, - settingNode: Parser.SyntaxNode, - policyNode: Parser.SyntaxNode, - categories: Map -): Policy { - const name = getStringProperty(moduleName, policyNode, 'name'); - - if (!name) { - throw new ParseError(`Missing required 'name' property`, moduleName, policyNode); - } else if (isNlsString(name)) { - throw new ParseError(`Property 'name' should be a literal string`, moduleName, policyNode); - } - - const categoryName = getStringProperty(moduleName, configurationNode, 'title'); - - if (!categoryName) { - throw new ParseError(`Missing required 'title' property`, moduleName, configurationNode); - } else if (!isNlsString(categoryName)) { - throw new ParseError(`Property 'title' should be localized`, moduleName, configurationNode); - } - - const categoryKey = `${categoryName.nlsKey}:${categoryName.value}`; - let category = categories.get(categoryKey); - - if (!category) { - category = { moduleName, name: categoryName }; - categories.set(categoryKey, category); - } - - const minimumVersion = getStringProperty(moduleName, policyNode, 'minimumVersion'); - - if (!minimumVersion) { - throw new ParseError(`Missing required 'minimumVersion' property.`, moduleName, policyNode); - } else if (isNlsString(minimumVersion)) { - throw new ParseError(`Property 'minimumVersion' should be a literal string.`, moduleName, policyNode); - } - - const description = getStringProperty(moduleName, policyNode, 'description') ?? getStringProperty(moduleName, settingNode, 'description'); - - if (!description) { - throw new ParseError(`Missing required 'description' property.`, moduleName, settingNode); - } if (!isNlsString(description)) { - throw new ParseError(`Property 'description' should be localized.`, moduleName, settingNode); - } - - let result: Policy | undefined; - - for (const policyType of PolicyTypes) { - if (result = policyType.from(name, category, minimumVersion, description, moduleName, settingNode)) { - break; - } - } - - if (!result) { - throw new ParseError(`Failed to parse policy '${name}'.`, moduleName, settingNode); - } - - return result; -} - -function getPolicies(moduleName: string, node: Parser.SyntaxNode): Policy[] { - const query = new Parser.Query(typescript, ` - ( - (call_expression - function: (member_expression property: (property_identifier) @registerConfigurationFn) (#eq? @registerConfigurationFn registerConfiguration) - arguments: (arguments (object (pair - key: [(property_identifier)(string)] @propertiesKey (#any-of? @propertiesKey "properties" "'properties'") - value: (object (pair - key: [(property_identifier)(string)(computed_property_name)] - value: (object (pair - key: [(property_identifier)(string)] @policyKey (#any-of? @policyKey "policy" "'policy'") - value: (object) @policy - )) @setting - )) - )) @configuration) - ) - ) - `); - - const categories = new Map(); - - return query.matches(node).map(m => { - const configurationNode = m.captures.filter(c => c.name === 'configuration')[0].node; - const settingNode = m.captures.filter(c => c.name === 'setting')[0].node; - const policyNode = m.captures.filter(c => c.name === 'policy')[0].node; - return getPolicy(moduleName, configurationNode, settingNode, policyNode, categories); - }); -} - -async function getFiles(root: string): Promise { - return new Promise((c, e) => { - const result: string[] = []; - const rg = spawn(rgPath, ['-l', 'registerConfiguration\\(', '-g', 'src/**/*.ts', '-g', '!src/**/test/**', root]); - const stream = byline(rg.stdout.setEncoding('utf8')); - stream.on('data', path => result.push(path)); - stream.on('error', err => e(err)); - stream.on('end', () => c(result)); - }); -} - -function renderADMX(regKey: string, versions: string[], categories: Category[], policies: Policy[]) { - versions = versions.map(v => v.replace(/\./g, '_')); - - return ` - - - - - - - - ${versions.map(v => ``).join(`\n `)} - - - - - ${categories.map(c => ``).join(`\n `)} - - - ${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)} - - -`; -} - -function renderADML(appName: string, versions: string[], categories: Category[], policies: Policy[], translations?: LanguageTranslations) { - return ` - - - - - - ${appName} - ${versions.map(v => `${appName} >= ${v}`).join(`\n `)} - ${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)} - ${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)} - - - ${policies.map(p => p.renderADMLPresentation()).join(`\n `)} - - - -`; -} - -function renderProfileManifest(appName: string, bundleIdentifier: string, _versions: string[], _categories: Category[], policies: Policy[], translations?: LanguageTranslations) { - - const requiredPayloadFields = ` - - pfm_default - Configure ${appName} - pfm_name - PayloadDescription - pfm_title - Payload Description - pfm_type - string - - - pfm_default - ${appName} - pfm_name - PayloadDisplayName - pfm_require - always - pfm_title - Payload Display Name - pfm_type - string - - - pfm_default - ${bundleIdentifier} - pfm_name - PayloadIdentifier - pfm_require - always - pfm_title - Payload Identifier - pfm_type - string - - - pfm_default - ${bundleIdentifier} - pfm_name - PayloadType - pfm_require - always - pfm_title - Payload Type - pfm_type - string - - - pfm_default - - pfm_name - PayloadUUID - pfm_require - always - pfm_title - Payload UUID - pfm_type - string - - - pfm_default - 1 - pfm_name - PayloadVersion - pfm_range_list - - 1 - - pfm_require - always - pfm_title - Payload Version - pfm_type - integer - - - pfm_default - Microsoft - pfm_name - PayloadOrganization - pfm_title - Payload Organization - pfm_type - string - `; - - const profileManifestSubkeys = policies.map(policy => { - return policy.renderProfileManifest(translations); - }).join(''); - - return ` - - - - pfm_app_url - https://code.visualstudio.com/ - pfm_description - ${appName} Managed Settings - pfm_documentation_url - https://code.visualstudio.com/docs/setup/enterprise - pfm_domain - ${bundleIdentifier} - pfm_format_version - 1 - pfm_interaction - combined - pfm_last_modified - ${new Date().toISOString().replace(/\.\d+Z$/, 'Z')} - pfm_platforms - - macOS - - pfm_subkeys - - ${requiredPayloadFields} - ${profileManifestSubkeys} - - pfm_title - ${appName} - pfm_unique - - pfm_version - 1 - -`; -} - -function renderMacOSPolicy(policies: Policy[], translations: Translations) { - const appName = product.nameLong; - const bundleIdentifier = product.darwinBundleIdentifier; - const payloadUUID = product.darwinProfilePayloadUUID; - const UUID = product.darwinProfileUUID; - - const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); - const categories = [...new Set(policies.map(p => p.category))]; - - const policyEntries = - policies.map(policy => policy.renderProfile()) - .flat() - .map(entry => `\t\t\t\t${entry}`) - .join('\n'); - - - return { - profile: ` - - - - PayloadContent - - - PayloadDisplayName - ${appName} - PayloadIdentifier - ${bundleIdentifier}.${UUID} - PayloadType - ${bundleIdentifier} - PayloadUUID - ${UUID} - PayloadVersion - 1 -${policyEntries} - - - PayloadDescription - This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise - PayloadDisplayName - ${appName} - PayloadIdentifier - ${bundleIdentifier} - PayloadOrganization - Microsoft - PayloadType - Configuration - PayloadUUID - ${payloadUUID} - PayloadVersion - 1 - TargetDeviceType - 5 - -`, - manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) }, - ...translations.map(({ languageId, languageTranslations }) => - ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) })) - ] - }; -} - -function renderGP(policies: Policy[], translations: Translations) { - const appName = product.nameLong; - const regKey = product.win32RegValueName; - - const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); - const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))] as Category[]; - - return { - admx: renderADMX(regKey, versions, categories, policies), - adml: [ - { languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) }, - ...translations.map(({ languageId, languageTranslations }) => - ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) })) - ] - }; -} - -const Languages = { - 'fr': 'fr-fr', - 'it': 'it-it', - 'de': 'de-de', - 'es': 'es-es', - 'ru': 'ru-ru', - 'zh-hans': 'zh-cn', - 'zh-hant': 'zh-tw', - 'ja': 'ja-jp', - 'ko': 'ko-kr', - 'cs': 'cs-cz', - 'pt-br': 'pt-br', - 'tr': 'tr-tr', - 'pl': 'pl-pl', -}; - -type LanguageTranslations = { [moduleName: string]: { [nlsKey: string]: string } }; -type Translations = { languageId: string; languageTranslations: LanguageTranslations }[]; - -type Version = [number, number, number]; - -async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, version: Version) { - const resource = { - publisher: 'ms-ceintl', - name: `vscode-language-pack-${languageId}`, - version: `${version[0]}.${version[1]}.${version[2]}`, - path: 'extension/translations/main.i18n.json' - }; - - const url = resourceUrlTemplate.replace(/\{([^}]+)\}/g, (_, key) => resource[key as keyof typeof resource]); - const res = await fetch(url); - - if (res.status !== 200) { - throw new Error(`[${res.status}] Error downloading language pack ${languageId}@${version}`); - } - - const { contents: result } = await res.json() as { contents: LanguageTranslations }; - return result; -} - -function parseVersion(version: string): Version { - const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)/.exec(version)!; - return [parseInt(major), parseInt(minor), parseInt(patch)]; -} - -function compareVersions(a: Version, b: Version): number { - if (a[0] !== b[0]) { return a[0] - b[0]; } - if (a[1] !== b[1]) { return a[1] - b[1]; } - return a[2] - b[2]; -} - -async function queryVersions(serviceUrl: string, languageId: string): Promise { - const res = await fetch(`${serviceUrl}/extensionquery`, { - method: 'POST', - headers: { - 'Accept': 'application/json;api-version=3.0-preview.1', - 'Content-Type': 'application/json', - 'User-Agent': 'VS Code Build', - }, - body: JSON.stringify({ - filters: [{ criteria: [{ filterType: 7, value: `ms-ceintl.vscode-language-pack-${languageId}` }] }], - flags: 0x1 - }) - }); - - if (res.status !== 200) { - throw new Error(`[${res.status}] Error querying for extension: ${languageId}`); - } - - const result = await res.json() as { results: [{ extensions: { versions: { version: string }[] }[] }] }; - return result.results[0].extensions[0].versions.map(v => parseVersion(v.version)).sort(compareVersions); -} - -async function getNLS(extensionGalleryServiceUrl: string, resourceUrlTemplate: string, languageId: string, version: Version) { - const versions = await queryVersions(extensionGalleryServiceUrl, languageId); - const nextMinor: Version = [version[0], version[1] + 1, 0]; - const compatibleVersions = versions.filter(v => compareVersions(v, nextMinor) < 0); - const latestCompatibleVersion = compatibleVersions.at(-1)!; // order is newest to oldest - - if (!latestCompatibleVersion) { - throw new Error(`No compatible language pack found for ${languageId} for version ${version}`); - } - - return await getSpecificNLS(resourceUrlTemplate, languageId, latestCompatibleVersion); -} - -async function parsePolicies(): Promise { - const parser = new Parser(); - parser.setLanguage(typescript); - - const files = await getFiles(process.cwd()); - const base = path.join(process.cwd(), 'src'); - const policies = []; - - for (const file of files) { - const moduleName = path.relative(base, file).replace(/\.ts$/i, '').replace(/\\/g, '/'); - const contents = await fs.readFile(file, { encoding: 'utf8' }); - const tree = parser.parse(contents); - policies.push(...getPolicies(moduleName, tree.rootNode)); - } - - return policies; -} - -async function getTranslations(): Promise { - const extensionGalleryServiceUrl = product.extensionsGallery?.serviceUrl; - - if (!extensionGalleryServiceUrl) { - console.warn(`Skipping policy localization: No 'extensionGallery.serviceUrl' found in 'product.json'.`); - return []; - } - - const resourceUrlTemplate = product.extensionsGallery?.resourceUrlTemplate; - - if (!resourceUrlTemplate) { - console.warn(`Skipping policy localization: No 'resourceUrlTemplate' found in 'product.json'.`); - return []; - } - - const version = parseVersion(packageJson.version); - const languageIds = Object.keys(Languages); - - return await Promise.all(languageIds.map( - languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) - .then(languageTranslations => ({ languageId, languageTranslations })) - )); -} - -async function windowsMain(policies: Policy[], translations: Translations) { - const root = '.build/policies/win32'; - const { admx, adml } = await renderGP(policies, translations); - - await fs.rm(root, { recursive: true, force: true }); - await fs.mkdir(root, { recursive: true }); - - await fs.writeFile(path.join(root, `${product.win32RegValueName}.admx`), admx.replace(/\r?\n/g, '\n')); - - for (const { languageId, contents } of adml) { - const languagePath = path.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId as keyof typeof Languages]); - await fs.mkdir(languagePath, { recursive: true }); - await fs.writeFile(path.join(languagePath, `${product.win32RegValueName}.adml`), contents.replace(/\r?\n/g, '\n')); - } -} - -async function darwinMain(policies: Policy[], translations: Translations) { - const bundleIdentifier = product.darwinBundleIdentifier; - if (!bundleIdentifier || !product.darwinProfilePayloadUUID || !product.darwinProfileUUID) { - throw new Error(`Missing required product information.`); - } - const root = '.build/policies/darwin'; - const { profile, manifests } = await renderMacOSPolicy(policies, translations); - - await fs.rm(root, { recursive: true, force: true }); - await fs.mkdir(root, { recursive: true }); - await fs.writeFile(path.join(root, `${bundleIdentifier}.mobileconfig`), profile.replace(/\r?\n/g, '\n')); - - for (const { languageId, contents } of manifests) { - const languagePath = path.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId as keyof typeof Languages]); - await fs.mkdir(languagePath, { recursive: true }); - await fs.writeFile(path.join(languagePath, `${bundleIdentifier}.plist`), contents.replace(/\r?\n/g, '\n')); - } -} - -async function main() { - const [policies, translations] = await Promise.all([parsePolicies(), getTranslations()]); - const platform = process.argv[2]; - - if (platform === 'darwin') { - await darwinMain(policies, translations); - } else if (platform === 'win32') { - await windowsMain(policies, translations); - } else { - console.error(`Usage: node build/lib/policies `); - process.exit(1); - } -} - -if (require.main === module) { - main().catch(err => { - if (err instanceof ParseError) { - console.error(`Parse Error:`, err.message); - } else { - console.error(err); - } - process.exit(1); - }); -} diff --git a/build/lib/policies/basePolicy.js b/build/lib/policies/basePolicy.js new file mode 100644 index 00000000000..5c1b919d428 --- /dev/null +++ b/build/lib/policies/basePolicy.js @@ -0,0 +1,57 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BasePolicy = void 0; +const render_1 = require("./render"); +class BasePolicy { + type; + name; + category; + minimumVersion; + description; + moduleName; + constructor(type, name, category, minimumVersion, description, moduleName) { + this.type = type; + this.name = name; + this.category = category; + this.minimumVersion = minimumVersion; + this.description = description; + this.moduleName = moduleName; + } + renderADMLString(nlsString, translations) { + return (0, render_1.renderADMLString)(this.name, this.moduleName, nlsString, translations); + } + renderADMX(regKey) { + return [ + ``, + ` `, + ` `, + ` `, + ...this.renderADMXElements(), + ` `, + `` + ]; + } + renderADMLStrings(translations) { + return [ + `${this.name}`, + this.renderADMLString(this.description, translations) + ]; + } + renderADMLPresentation() { + return `${this.renderADMLPresentationContents()}`; + } + renderProfile() { + return [`${this.name}`, this.renderProfileValue()]; + } + renderProfileManifest(translations) { + return ` +${this.renderProfileManifestValue(translations)} +`; + } +} +exports.BasePolicy = BasePolicy; +//# sourceMappingURL=basePolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/basePolicy.ts b/build/lib/policies/basePolicy.ts new file mode 100644 index 00000000000..f0477d244f0 --- /dev/null +++ b/build/lib/policies/basePolicy.ts @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { renderADMLString } from './render'; +import { Category, LanguageTranslations, NlsString, Policy, PolicyType } from './types'; + +export abstract class BasePolicy implements Policy { + constructor( + readonly type: PolicyType, + readonly name: string, + readonly category: Category, + readonly minimumVersion: string, + protected description: NlsString, + protected moduleName: string, + ) { } + + protected renderADMLString(nlsString: NlsString, translations?: LanguageTranslations): string { + return renderADMLString(this.name, this.moduleName, nlsString, translations); + } + + renderADMX(regKey: string) { + return [ + ``, + ` `, + ` `, + ` `, + ...this.renderADMXElements(), + ` `, + `` + ]; + } + + protected abstract renderADMXElements(): string[]; + + renderADMLStrings(translations?: LanguageTranslations) { + return [ + `${this.name}`, + this.renderADMLString(this.description, translations) + ]; + } + + renderADMLPresentation(): string { + return `${this.renderADMLPresentationContents()}`; + } + + protected abstract renderADMLPresentationContents(): string; + + renderProfile() { + return [`${this.name}`, this.renderProfileValue()]; + } + + renderProfileManifest(translations?: LanguageTranslations): string { + return ` +${this.renderProfileManifestValue(translations)} +`; + } + + abstract renderJsonValue(): string | number | boolean | object | null; + abstract renderProfileValue(): string; + abstract renderProfileManifestValue(translations?: LanguageTranslations): string; +} diff --git a/build/lib/policies/booleanPolicy.js b/build/lib/policies/booleanPolicy.js new file mode 100644 index 00000000000..77ea3d9a42e --- /dev/null +++ b/build/lib/policies/booleanPolicy.js @@ -0,0 +1,52 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BooleanPolicy = void 0; +const basePolicy_1 = require("./basePolicy"); +const render_1 = require("./render"); +const types_1 = require("./types"); +class BooleanPolicy extends basePolicy_1.BasePolicy { + static from(category, policy) { + const { name, minimumVersion, localization, type } = policy; + if (type !== 'boolean') { + return undefined; + } + return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + constructor(name, category, minimumVersion, description, moduleName) { + super(types_1.PolicyType.Boolean, name, category, minimumVersion, description, moduleName); + } + renderADMXElements() { + return [ + ``, + ` `, + `` + ]; + } + renderADMLPresentationContents() { + return `${this.name}`; + } + renderJsonValue() { + return false; + } + renderProfileValue() { + return ``; + } + renderProfileManifestValue(translations) { + return `pfm_default + +pfm_description +${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +boolean`; + } +} +exports.BooleanPolicy = BooleanPolicy; +//# sourceMappingURL=booleanPolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/booleanPolicy.ts b/build/lib/policies/booleanPolicy.ts new file mode 100644 index 00000000000..538140b3db2 --- /dev/null +++ b/build/lib/policies/booleanPolicy.ts @@ -0,0 +1,65 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BasePolicy } from './basePolicy'; +import { CategoryDto, PolicyDto } from './policyDto'; +import { renderProfileString } from './render'; +import { Category, NlsString, PolicyType, LanguageTranslations } from './types'; + +export class BooleanPolicy extends BasePolicy { + + static from(category: CategoryDto, policy: PolicyDto): BooleanPolicy | undefined { + const { name, minimumVersion, localization, type } = policy; + + if (type !== 'boolean') { + return undefined; + } + + return new BooleanPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + + private constructor( + name: string, + category: Category, + minimumVersion: string, + description: NlsString, + moduleName: string, + ) { + super(PolicyType.Boolean, name, category, minimumVersion, description, moduleName); + } + + protected renderADMXElements(): string[] { + return [ + ``, + ` `, + `` + ]; + } + + renderADMLPresentationContents() { + return `${this.name}`; + } + + renderJsonValue() { + return false; + } + + renderProfileValue(): string { + return ``; + } + + renderProfileManifestValue(translations?: LanguageTranslations): string { + return `pfm_default + +pfm_description +${renderProfileString(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +boolean`; + } +} diff --git a/build/lib/policies/copyPolicyDto.js b/build/lib/policies/copyPolicyDto.js new file mode 100644 index 00000000000..a223bb4c0ef --- /dev/null +++ b/build/lib/policies/copyPolicyDto.js @@ -0,0 +1,58 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = __importStar(require("fs")); +const path = __importStar(require("path")); +const sourceFile = path.join(__dirname, '../../../src/vs/workbench/contrib/policyExport/common/policyDto.ts'); +const destFile = path.join(__dirname, 'policyDto.ts'); +try { + // Check if source file exists + if (!fs.existsSync(sourceFile)) { + console.error(`Error: Source file not found: ${sourceFile}`); + console.error('Please ensure policyDto.ts exists in src/vs/workbench/contrib/policyExport/common/'); + process.exit(1); + } + // Copy the file + fs.copyFileSync(sourceFile, destFile); +} +catch (error) { + console.error(`Error copying policyDto.ts: ${error.message}`); + process.exit(1); +} +//# sourceMappingURL=copyPolicyDto.js.map \ No newline at end of file diff --git a/build/lib/policies/copyPolicyDto.ts b/build/lib/policies/copyPolicyDto.ts new file mode 100644 index 00000000000..4fb74456837 --- /dev/null +++ b/build/lib/policies/copyPolicyDto.ts @@ -0,0 +1,25 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'fs'; +import * as path from 'path'; + +const sourceFile = path.join(__dirname, '../../../src/vs/workbench/contrib/policyExport/common/policyDto.ts'); +const destFile = path.join(__dirname, 'policyDto.ts'); + +try { + // Check if source file exists + if (!fs.existsSync(sourceFile)) { + console.error(`Error: Source file not found: ${sourceFile}`); + console.error('Please ensure policyDto.ts exists in src/vs/workbench/contrib/policyExport/common/'); + process.exit(1); + } + + // Copy the file + fs.copyFileSync(sourceFile, destFile); +} catch (error) { + console.error(`Error copying policyDto.ts: ${(error as Error).message}`); + process.exit(1); +} diff --git a/build/lib/policies/numberPolicy.js b/build/lib/policies/numberPolicy.js new file mode 100644 index 00000000000..3bc0b98d19a --- /dev/null +++ b/build/lib/policies/numberPolicy.js @@ -0,0 +1,56 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NumberPolicy = void 0; +const basePolicy_1 = require("./basePolicy"); +const render_1 = require("./render"); +const types_1 = require("./types"); +class NumberPolicy extends basePolicy_1.BasePolicy { + defaultValue; + static from(category, policy) { + const { type, default: defaultValue, name, minimumVersion, localization } = policy; + if (type !== 'number') { + return undefined; + } + if (typeof defaultValue !== 'number') { + throw new Error(`Missing required 'default' property.`); + } + return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue); + } + constructor(name, category, minimumVersion, description, moduleName, defaultValue) { + super(types_1.PolicyType.Number, name, category, minimumVersion, description, moduleName); + this.defaultValue = defaultValue; + } + renderADMXElements() { + return [ + `` + // `` + ]; + } + renderADMLPresentationContents() { + return `${this.name}`; + } + renderJsonValue() { + return this.defaultValue; + } + renderProfileValue() { + return `${this.defaultValue}`; + } + renderProfileManifestValue(translations) { + return `pfm_default +${this.defaultValue} +pfm_description +${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +integer`; + } +} +exports.NumberPolicy = NumberPolicy; +//# sourceMappingURL=numberPolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/numberPolicy.ts b/build/lib/policies/numberPolicy.ts new file mode 100644 index 00000000000..db4143e1f7f --- /dev/null +++ b/build/lib/policies/numberPolicy.ts @@ -0,0 +1,69 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BasePolicy } from './basePolicy'; +import { CategoryDto, PolicyDto } from './policyDto'; +import { renderProfileString } from './render'; +import { Category, NlsString, PolicyType, LanguageTranslations } from './types'; + +export class NumberPolicy extends BasePolicy { + + static from(category: CategoryDto, policy: PolicyDto): NumberPolicy | undefined { + const { type, default: defaultValue, name, minimumVersion, localization } = policy; + + if (type !== 'number') { + return undefined; + } + + if (typeof defaultValue !== 'number') { + throw new Error(`Missing required 'default' property.`); + } + + return new NumberPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', defaultValue); + } + + private constructor( + name: string, + category: Category, + minimumVersion: string, + description: NlsString, + moduleName: string, + protected readonly defaultValue: number, + ) { + super(PolicyType.Number, name, category, minimumVersion, description, moduleName); + } + + protected renderADMXElements(): string[] { + return [ + `` + // `` + ]; + } + + renderADMLPresentationContents() { + return `${this.name}`; + } + + renderJsonValue() { + return this.defaultValue; + } + + renderProfileValue() { + return `${this.defaultValue}`; + } + + renderProfileManifestValue(translations?: LanguageTranslations) { + return `pfm_default +${this.defaultValue} +pfm_description +${renderProfileString(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +integer`; + } +} diff --git a/build/lib/policies/objectPolicy.js b/build/lib/policies/objectPolicy.js new file mode 100644 index 00000000000..43a7aaa3fc9 --- /dev/null +++ b/build/lib/policies/objectPolicy.js @@ -0,0 +1,49 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ObjectPolicy = void 0; +const basePolicy_1 = require("./basePolicy"); +const render_1 = require("./render"); +const types_1 = require("./types"); +class ObjectPolicy extends basePolicy_1.BasePolicy { + static from(category, policy) { + const { type, name, minimumVersion, localization } = policy; + if (type !== 'object' && type !== 'array') { + return undefined; + } + return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + constructor(name, category, minimumVersion, description, moduleName) { + super(types_1.PolicyType.Object, name, category, minimumVersion, description, moduleName); + } + renderADMXElements() { + return [``]; + } + renderADMLPresentationContents() { + return ``; + } + renderJsonValue() { + return ''; + } + renderProfileValue() { + return ``; + } + renderProfileManifestValue(translations) { + return `pfm_default + +pfm_description +${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string +`; + } +} +exports.ObjectPolicy = ObjectPolicy; +//# sourceMappingURL=objectPolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/objectPolicy.ts b/build/lib/policies/objectPolicy.ts new file mode 100644 index 00000000000..3bbc916636f --- /dev/null +++ b/build/lib/policies/objectPolicy.ts @@ -0,0 +1,62 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BasePolicy } from './basePolicy'; +import { CategoryDto, PolicyDto } from './policyDto'; +import { renderProfileString } from './render'; +import { Category, NlsString, PolicyType, LanguageTranslations } from './types'; + +export class ObjectPolicy extends BasePolicy { + + static from(category: CategoryDto, policy: PolicyDto): ObjectPolicy | undefined { + const { type, name, minimumVersion, localization } = policy; + + if (type !== 'object' && type !== 'array') { + return undefined; + } + + return new ObjectPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + + private constructor( + name: string, + category: Category, + minimumVersion: string, + description: NlsString, + moduleName: string, + ) { + super(PolicyType.Object, name, category, minimumVersion, description, moduleName); + } + + protected renderADMXElements(): string[] { + return [``]; + } + + renderADMLPresentationContents() { + return ``; + } + + renderJsonValue() { + return ''; + } + + renderProfileValue(): string { + return ``; + } + + renderProfileManifestValue(translations?: LanguageTranslations): string { + return `pfm_default + +pfm_description +${renderProfileString(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string +`; + } +} diff --git a/build/lib/policies/policyData.jsonc b/build/lib/policies/policyData.jsonc new file mode 100644 index 00000000000..252f57d854e --- /dev/null +++ b/build/lib/policies/policyData.jsonc @@ -0,0 +1,277 @@ +/** THIS FILE IS AUTOMATICALLY GENERATED USING `code --export-policy-data`. DO NOT MODIFY IT MANUALLY. **/ +{ + "categories": [ + { + "key": "Extensions", + "name": { + "key": "extensionsConfigurationTitle", + "value": "Extensions" + } + }, + { + "key": "IntegratedTerminal", + "name": { + "key": "terminalIntegratedConfigurationTitle", + "value": "Integrated Terminal" + } + }, + { + "key": "InteractiveSession", + "name": { + "key": "interactiveSessionConfigurationTitle", + "value": "Chat" + } + }, + { + "key": "Telemetry", + "name": { + "key": "telemetryConfigurationTitle", + "value": "Telemetry" + } + }, + { + "key": "Update", + "name": { + "key": "updateConfigurationTitle", + "value": "Update" + } + } + ], + "policies": [ + { + "key": "chat.mcp.gallery.serviceUrl", + "name": "McpGalleryServiceUrl", + "category": "InteractiveSession", + "minimumVersion": "1.101", + "localization": { + "description": { + "key": "mcp.gallery.serviceUrl", + "value": "Configure the MCP Gallery service URL to connect to" + } + }, + "type": "string", + "default": "" + }, + { + "key": "extensions.gallery.serviceUrl", + "name": "ExtensionGalleryServiceUrl", + "category": "Extensions", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "extensions.gallery.serviceUrl", + "value": "Configure the Marketplace service URL to connect to" + } + }, + "type": "string", + "default": "" + }, + { + "key": "extensions.allowed", + "name": "AllowedExtensions", + "category": "Extensions", + "minimumVersion": "1.96", + "localization": { + "description": { + "key": "extensions.allowed.policy", + "value": "Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions" + } + }, + "type": "object", + "default": "*" + }, + { + "key": "chat.tools.global.autoApprove", + "name": "ChatToolsAutoApprove", + "category": "InteractiveSession", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "autoApprove2.description", + "value": "Global auto approve also known as \"YOLO mode\" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.\n\nThis feature disables critical security protections and makes it much easier for an attacker to compromise the machine." + } + }, + "type": "boolean", + "default": false + }, + { + "key": "chat.tools.eligibleForAutoApproval", + "name": "ChatToolsEligibleForAutoApproval", + "category": "InteractiveSession", + "minimumVersion": "1.107", + "localization": { + "description": { + "key": "chat.tools.eligibleForAutoApproval", + "value": "Controls which tools are eligible for automatic approval. Tools set to 'false' will always present a confirmation and will never offer the option to auto-approve. The default behavior (or setting a tool to 'true') may result in the tool offering auto-approval options." + } + }, + "type": "object", + "default": {} + }, + { + "key": "chat.mcp.access", + "name": "ChatMCP", + "category": "InteractiveSession", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "chat.mcp.access", + "value": "Controls access to installed Model Context Protocol servers." + }, + "enumDescriptions": [ + { + "key": "chat.mcp.access.none", + "value": "No access to MCP servers." + }, + { + "key": "chat.mcp.access.registry", + "value": "Allows access to MCP servers installed from the registry that VS Code is connected to." + }, + { + "key": "chat.mcp.access.any", + "value": "Allow access to any installed MCP server." + } + ] + }, + "type": "string", + "default": "all", + "enum": [ + "none", + "registry", + "all" + ] + }, + { + "key": "chat.extensionTools.enabled", + "name": "ChatAgentExtensionTools", + "category": "InteractiveSession", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "chat.extensionToolsEnabled", + "value": "Enable using tools contributed by third-party extensions." + } + }, + "type": "boolean", + "default": true + }, + { + "key": "chat.agent.enabled", + "name": "ChatAgentMode", + "category": "InteractiveSession", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "chat.agent.enabled.description", + "value": "Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view." + } + }, + "type": "boolean", + "default": true + }, + { + "key": "chat.tools.terminal.enableAutoApprove", + "name": "ChatToolsTerminalEnableAutoApprove", + "category": "IntegratedTerminal", + "minimumVersion": "1.104", + "localization": { + "description": { + "key": "autoApproveMode.description", + "value": "Controls whether to allow auto approval in the run in terminal tool." + } + }, + "type": "boolean", + "default": true + }, + { + "key": "update.mode", + "name": "UpdateMode", + "category": "Update", + "minimumVersion": "1.67", + "localization": { + "description": { + "key": "updateMode", + "value": "Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service." + }, + "enumDescriptions": [ + { + "key": "none", + "value": "Disable updates." + }, + { + "key": "manual", + "value": "Disable automatic background update checks. Updates will be available if you manually check for updates." + }, + { + "key": "start", + "value": "Check for updates only on startup. Disable automatic background update checks." + }, + { + "key": "default", + "value": "Enable automatic update checks. Code will check for updates automatically and periodically." + } + ] + }, + "type": "string", + "default": "default", + "enum": [ + "none", + "manual", + "start", + "default" + ] + }, + { + "key": "telemetry.telemetryLevel", + "name": "TelemetryLevel", + "category": "Telemetry", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "telemetry.telemetryLevel.policyDescription", + "value": "Controls the level of telemetry." + }, + "enumDescriptions": [ + { + "key": "telemetry.telemetryLevel.default", + "value": "Sends usage data, errors, and crash reports." + }, + { + "key": "telemetry.telemetryLevel.error", + "value": "Sends general error telemetry and crash reports." + }, + { + "key": "telemetry.telemetryLevel.crash", + "value": "Sends OS level crash reports." + }, + { + "key": "telemetry.telemetryLevel.off", + "value": "Disables all product telemetry." + } + ] + }, + "type": "string", + "default": "all", + "enum": [ + "all", + "error", + "crash", + "off" + ] + }, + { + "key": "telemetry.feedback.enabled", + "name": "EnableFeedback", + "category": "Telemetry", + "minimumVersion": "1.99", + "localization": { + "description": { + "key": "telemetry.feedback.enabled", + "value": "Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options." + } + }, + "type": "boolean", + "default": true + } + ] +} diff --git a/build/lib/policies/policyGenerator.js b/build/lib/policies/policyGenerator.js new file mode 100644 index 00000000000..132e55873da --- /dev/null +++ b/build/lib/policies/policyGenerator.js @@ -0,0 +1,243 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || (function () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const minimist_1 = __importDefault(require("minimist")); +const fs_1 = require("fs"); +const path_1 = __importDefault(require("path")); +const JSONC = __importStar(require("jsonc-parser")); +const booleanPolicy_1 = require("./booleanPolicy"); +const numberPolicy_1 = require("./numberPolicy"); +const objectPolicy_1 = require("./objectPolicy"); +const stringEnumPolicy_1 = require("./stringEnumPolicy"); +const stringPolicy_1 = require("./stringPolicy"); +const types_1 = require("./types"); +const render_1 = require("./render"); +const product = require('../../../product.json'); +const packageJson = require('../../../package.json'); +async function getSpecificNLS(resourceUrlTemplate, languageId, version) { + const resource = { + publisher: 'ms-ceintl', + name: `vscode-language-pack-${languageId}`, + version: `${version[0]}.${version[1]}.${version[2]}`, + path: 'extension/translations/main.i18n.json' + }; + const url = resourceUrlTemplate.replace(/\{([^}]+)\}/g, (_, key) => resource[key]); + const res = await fetch(url); + if (res.status !== 200) { + throw new Error(`[${res.status}] Error downloading language pack ${languageId}@${version}`); + } + const { contents: result } = await res.json(); + // TODO: support module namespacing + // Flatten all moduleName keys to empty string + const flattened = { '': {} }; + for (const moduleName in result) { + for (const nlsKey in result[moduleName]) { + flattened[''][nlsKey] = result[moduleName][nlsKey]; + } + } + return flattened; +} +function parseVersion(version) { + const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)/.exec(version); + return [parseInt(major), parseInt(minor), parseInt(patch)]; +} +function compareVersions(a, b) { + if (a[0] !== b[0]) { + return a[0] - b[0]; + } + if (a[1] !== b[1]) { + return a[1] - b[1]; + } + return a[2] - b[2]; +} +async function queryVersions(serviceUrl, languageId) { + const res = await fetch(`${serviceUrl}/extensionquery`, { + method: 'POST', + headers: { + 'Accept': 'application/json;api-version=3.0-preview.1', + 'Content-Type': 'application/json', + 'User-Agent': 'VS Code Build', + }, + body: JSON.stringify({ + filters: [{ criteria: [{ filterType: 7, value: `ms-ceintl.vscode-language-pack-${languageId}` }] }], + flags: 0x1 + }) + }); + if (res.status !== 200) { + throw new Error(`[${res.status}] Error querying for extension: ${languageId}`); + } + const result = await res.json(); + return result.results[0].extensions[0].versions.map(v => parseVersion(v.version)).sort(compareVersions); +} +async function getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) { + const versions = await queryVersions(extensionGalleryServiceUrl, languageId); + const nextMinor = [version[0], version[1] + 1, 0]; + const compatibleVersions = versions.filter(v => compareVersions(v, nextMinor) < 0); + const latestCompatibleVersion = compatibleVersions.at(-1); // order is newest to oldest + if (!latestCompatibleVersion) { + throw new Error(`No compatible language pack found for ${languageId} for version ${version}`); + } + return await getSpecificNLS(resourceUrlTemplate, languageId, latestCompatibleVersion); +} +// TODO: add more policy types +const PolicyTypes = [ + booleanPolicy_1.BooleanPolicy, + numberPolicy_1.NumberPolicy, + stringEnumPolicy_1.StringEnumPolicy, + stringPolicy_1.StringPolicy, + objectPolicy_1.ObjectPolicy +]; +async function parsePolicies(policyDataFile) { + const contents = JSONC.parse(await fs_1.promises.readFile(policyDataFile, { encoding: 'utf8' })); + const categories = new Map(); + for (const category of contents.categories) { + categories.set(category.key, category); + } + const policies = []; + for (const policy of contents.policies) { + const category = categories.get(policy.category); + if (!category) { + throw new Error(`Unknown category: ${policy.category}`); + } + let result; + for (const policyType of PolicyTypes) { + if (result = policyType.from(category, policy)) { + break; + } + } + if (!result) { + throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`); + } + policies.push(result); + } + // Sort policies first by category name, then by policy name + policies.sort((a, b) => { + const categoryCompare = a.category.name.value.localeCompare(b.category.name.value); + if (categoryCompare !== 0) { + return categoryCompare; + } + return a.name.localeCompare(b.name); + }); + return policies; +} +async function getTranslations() { + const extensionGalleryServiceUrl = product.extensionsGallery?.serviceUrl; + if (!extensionGalleryServiceUrl) { + console.warn(`Skipping policy localization: No 'extensionGallery.serviceUrl' found in 'product.json'.`); + return []; + } + const resourceUrlTemplate = product.extensionsGallery?.resourceUrlTemplate; + if (!resourceUrlTemplate) { + console.warn(`Skipping policy localization: No 'resourceUrlTemplate' found in 'product.json'.`); + return []; + } + const version = parseVersion(packageJson.version); + const languageIds = Object.keys(types_1.Languages); + return await Promise.all(languageIds.map(languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) + .then(languageTranslations => ({ languageId, languageTranslations })))); +} +async function windowsMain(policies, translations) { + const root = '.build/policies/win32'; + const { admx, adml } = (0, render_1.renderGP)(product, policies, translations); + await fs_1.promises.rm(root, { recursive: true, force: true }); + await fs_1.promises.mkdir(root, { recursive: true }); + await fs_1.promises.writeFile(path_1.default.join(root, `${product.win32RegValueName}.admx`), admx.replace(/\r?\n/g, '\n')); + for (const { languageId, contents } of adml) { + const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : types_1.Languages[languageId]); + await fs_1.promises.mkdir(languagePath, { recursive: true }); + await fs_1.promises.writeFile(path_1.default.join(languagePath, `${product.win32RegValueName}.adml`), contents.replace(/\r?\n/g, '\n')); + } +} +async function darwinMain(policies, translations) { + const bundleIdentifier = product.darwinBundleIdentifier; + if (!bundleIdentifier || !product.darwinProfilePayloadUUID || !product.darwinProfileUUID) { + throw new Error(`Missing required product information.`); + } + const root = '.build/policies/darwin'; + const { profile, manifests } = (0, render_1.renderMacOSPolicy)(product, policies, translations); + await fs_1.promises.rm(root, { recursive: true, force: true }); + await fs_1.promises.mkdir(root, { recursive: true }); + await fs_1.promises.writeFile(path_1.default.join(root, `${bundleIdentifier}.mobileconfig`), profile.replace(/\r?\n/g, '\n')); + for (const { languageId, contents } of manifests) { + const languagePath = path_1.default.join(root, languageId === 'en-us' ? 'en-us' : types_1.Languages[languageId]); + await fs_1.promises.mkdir(languagePath, { recursive: true }); + await fs_1.promises.writeFile(path_1.default.join(languagePath, `${bundleIdentifier}.plist`), contents.replace(/\r?\n/g, '\n')); + } +} +async function linuxMain(policies) { + const root = '.build/policies/linux'; + const policyFileContents = JSON.stringify((0, render_1.renderJsonPolicies)(policies), undefined, 4); + await fs_1.promises.rm(root, { recursive: true, force: true }); + await fs_1.promises.mkdir(root, { recursive: true }); + const jsonPath = path_1.default.join(root, `policy.json`); + await fs_1.promises.writeFile(jsonPath, policyFileContents.replace(/\r?\n/g, '\n')); +} +async function main() { + const args = (0, minimist_1.default)(process.argv.slice(2)); + if (args._.length !== 2) { + console.error(`Usage: node build/lib/policies `); + process.exit(1); + } + const policyDataFile = args._[0]; + const platform = args._[1]; + const [policies, translations] = await Promise.all([parsePolicies(policyDataFile), getTranslations()]); + if (platform === 'darwin') { + await darwinMain(policies, translations); + } + else if (platform === 'win32') { + await windowsMain(policies, translations); + } + else if (platform === 'linux') { + await linuxMain(policies); + } + else { + console.error(`Usage: node build/lib/policies `); + process.exit(1); + } +} +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +} +//# sourceMappingURL=policyGenerator.js.map \ No newline at end of file diff --git a/build/lib/policies/policyGenerator.ts b/build/lib/policies/policyGenerator.ts new file mode 100644 index 00000000000..50ea96b1280 --- /dev/null +++ b/build/lib/policies/policyGenerator.ts @@ -0,0 +1,244 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import minimist from 'minimist'; +import { promises as fs } from 'fs'; +import path from 'path'; +import { CategoryDto, ExportedPolicyDataDto } from './policyDto'; +import * as JSONC from 'jsonc-parser'; +import { BooleanPolicy } from './booleanPolicy'; +import { NumberPolicy } from './numberPolicy'; +import { ObjectPolicy } from './objectPolicy'; +import { StringEnumPolicy } from './stringEnumPolicy'; +import { StringPolicy } from './stringPolicy'; +import { Version, LanguageTranslations, Policy, Translations, Languages, ProductJson } from './types'; +import { renderGP, renderJsonPolicies, renderMacOSPolicy } from './render'; + +const product = require('../../../product.json') as ProductJson; +const packageJson = require('../../../package.json'); + +async function getSpecificNLS(resourceUrlTemplate: string, languageId: string, version: Version): Promise { + const resource = { + publisher: 'ms-ceintl', + name: `vscode-language-pack-${languageId}`, + version: `${version[0]}.${version[1]}.${version[2]}`, + path: 'extension/translations/main.i18n.json' + }; + + const url = resourceUrlTemplate.replace(/\{([^}]+)\}/g, (_, key) => resource[key as keyof typeof resource]); + const res = await fetch(url); + + if (res.status !== 200) { + throw new Error(`[${res.status}] Error downloading language pack ${languageId}@${version}`); + } + + const { contents: result } = await res.json() as { contents: LanguageTranslations }; + + // TODO: support module namespacing + // Flatten all moduleName keys to empty string + const flattened: LanguageTranslations = { '': {} }; + for (const moduleName in result) { + for (const nlsKey in result[moduleName]) { + flattened[''][nlsKey] = result[moduleName][nlsKey]; + } + } + + return flattened; +} + +function parseVersion(version: string): Version { + const [, major, minor, patch] = /^(\d+)\.(\d+)\.(\d+)/.exec(version)!; + return [parseInt(major), parseInt(minor), parseInt(patch)]; +} + +function compareVersions(a: Version, b: Version): number { + if (a[0] !== b[0]) { return a[0] - b[0]; } + if (a[1] !== b[1]) { return a[1] - b[1]; } + return a[2] - b[2]; +} + +async function queryVersions(serviceUrl: string, languageId: string): Promise { + const res = await fetch(`${serviceUrl}/extensionquery`, { + method: 'POST', + headers: { + 'Accept': 'application/json;api-version=3.0-preview.1', + 'Content-Type': 'application/json', + 'User-Agent': 'VS Code Build', + }, + body: JSON.stringify({ + filters: [{ criteria: [{ filterType: 7, value: `ms-ceintl.vscode-language-pack-${languageId}` }] }], + flags: 0x1 + }) + }); + + if (res.status !== 200) { + throw new Error(`[${res.status}] Error querying for extension: ${languageId}`); + } + + const result = await res.json() as { results: [{ extensions: { versions: { version: string }[] }[] }] }; + return result.results[0].extensions[0].versions.map(v => parseVersion(v.version)).sort(compareVersions); +} + +async function getNLS(extensionGalleryServiceUrl: string, resourceUrlTemplate: string, languageId: string, version: Version) { + const versions = await queryVersions(extensionGalleryServiceUrl, languageId); + const nextMinor: Version = [version[0], version[1] + 1, 0]; + const compatibleVersions = versions.filter(v => compareVersions(v, nextMinor) < 0); + const latestCompatibleVersion = compatibleVersions.at(-1)!; // order is newest to oldest + + if (!latestCompatibleVersion) { + throw new Error(`No compatible language pack found for ${languageId} for version ${version}`); + } + + return await getSpecificNLS(resourceUrlTemplate, languageId, latestCompatibleVersion); +} + +// TODO: add more policy types +const PolicyTypes = [ + BooleanPolicy, + NumberPolicy, + StringEnumPolicy, + StringPolicy, + ObjectPolicy +]; + +async function parsePolicies(policyDataFile: string): Promise { + const contents = JSONC.parse(await fs.readFile(policyDataFile, { encoding: 'utf8' })) as ExportedPolicyDataDto; + const categories = new Map(); + for (const category of contents.categories) { + categories.set(category.key, category); + } + + const policies: Policy[] = []; + for (const policy of contents.policies) { + const category = categories.get(policy.category); + if (!category) { + throw new Error(`Unknown category: ${policy.category}`); + } + + let result: Policy | undefined; + for (const policyType of PolicyTypes) { + if (result = policyType.from(category, policy)) { + break; + } + } + + if (!result) { + throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`); + } + + policies.push(result); + } + + // Sort policies first by category name, then by policy name + policies.sort((a, b) => { + const categoryCompare = a.category.name.value.localeCompare(b.category.name.value); + if (categoryCompare !== 0) { + return categoryCompare; + } + return a.name.localeCompare(b.name); + }); + + return policies; +} + +async function getTranslations(): Promise { + const extensionGalleryServiceUrl = product.extensionsGallery?.serviceUrl; + + if (!extensionGalleryServiceUrl) { + console.warn(`Skipping policy localization: No 'extensionGallery.serviceUrl' found in 'product.json'.`); + return []; + } + + const resourceUrlTemplate = product.extensionsGallery?.resourceUrlTemplate; + + if (!resourceUrlTemplate) { + console.warn(`Skipping policy localization: No 'resourceUrlTemplate' found in 'product.json'.`); + return []; + } + + const version = parseVersion(packageJson.version); + const languageIds = Object.keys(Languages); + + return await Promise.all(languageIds.map( + languageId => getNLS(extensionGalleryServiceUrl, resourceUrlTemplate, languageId, version) + .then(languageTranslations => ({ languageId, languageTranslations })) + )); +} + +async function windowsMain(policies: Policy[], translations: Translations) { + const root = '.build/policies/win32'; + const { admx, adml } = renderGP(product, policies, translations); + + await fs.rm(root, { recursive: true, force: true }); + await fs.mkdir(root, { recursive: true }); + + await fs.writeFile(path.join(root, `${product.win32RegValueName}.admx`), admx.replace(/\r?\n/g, '\n')); + + for (const { languageId, contents } of adml) { + const languagePath = path.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId as keyof typeof Languages]); + await fs.mkdir(languagePath, { recursive: true }); + await fs.writeFile(path.join(languagePath, `${product.win32RegValueName}.adml`), contents.replace(/\r?\n/g, '\n')); + } +} + +async function darwinMain(policies: Policy[], translations: Translations) { + const bundleIdentifier = product.darwinBundleIdentifier; + if (!bundleIdentifier || !product.darwinProfilePayloadUUID || !product.darwinProfileUUID) { + throw new Error(`Missing required product information.`); + } + const root = '.build/policies/darwin'; + const { profile, manifests } = renderMacOSPolicy(product, policies, translations); + + await fs.rm(root, { recursive: true, force: true }); + await fs.mkdir(root, { recursive: true }); + await fs.writeFile(path.join(root, `${bundleIdentifier}.mobileconfig`), profile.replace(/\r?\n/g, '\n')); + + for (const { languageId, contents } of manifests) { + const languagePath = path.join(root, languageId === 'en-us' ? 'en-us' : Languages[languageId as keyof typeof Languages]); + await fs.mkdir(languagePath, { recursive: true }); + await fs.writeFile(path.join(languagePath, `${bundleIdentifier}.plist`), contents.replace(/\r?\n/g, '\n')); + } +} + +async function linuxMain(policies: Policy[]) { + const root = '.build/policies/linux'; + const policyFileContents = JSON.stringify(renderJsonPolicies(policies), undefined, 4); + + await fs.rm(root, { recursive: true, force: true }); + await fs.mkdir(root, { recursive: true }); + + const jsonPath = path.join(root, `policy.json`); + await fs.writeFile(jsonPath, policyFileContents.replace(/\r?\n/g, '\n')); +} + +async function main() { + const args = minimist(process.argv.slice(2)); + if (args._.length !== 2) { + console.error(`Usage: node build/lib/policies `); + process.exit(1); + } + + const policyDataFile = args._[0]; + const platform = args._[1]; + const [policies, translations] = await Promise.all([parsePolicies(policyDataFile), getTranslations()]); + + if (platform === 'darwin') { + await darwinMain(policies, translations); + } else if (platform === 'win32') { + await windowsMain(policies, translations); + } else if (platform === 'linux') { + await linuxMain(policies); + } else { + console.error(`Usage: node build/lib/policies `); + process.exit(1); + } +} + +if (require.main === module) { + main().catch(err => { + console.error(err); + process.exit(1); + }); +} diff --git a/build/lib/policies/render.js b/build/lib/policies/render.js new file mode 100644 index 00000000000..8661dab9154 --- /dev/null +++ b/build/lib/policies/render.js @@ -0,0 +1,283 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.renderADMLString = renderADMLString; +exports.renderProfileString = renderProfileString; +exports.renderADMX = renderADMX; +exports.renderADML = renderADML; +exports.renderProfileManifest = renderProfileManifest; +exports.renderMacOSPolicy = renderMacOSPolicy; +exports.renderGP = renderGP; +exports.renderJsonPolicies = renderJsonPolicies; +function renderADMLString(prefix, moduleName, nlsString, translations) { + let value; + if (translations) { + const moduleTranslations = translations[moduleName]; + if (moduleTranslations) { + value = moduleTranslations[nlsString.nlsKey]; + } + } + if (!value) { + value = nlsString.value; + } + return `${value}`; +} +function renderProfileString(_prefix, moduleName, nlsString, translations) { + let value; + if (translations) { + const moduleTranslations = translations[moduleName]; + if (moduleTranslations) { + value = moduleTranslations[nlsString.nlsKey]; + } + } + if (!value) { + value = nlsString.value; + } + return value; +} +function renderADMX(regKey, versions, categories, policies) { + versions = versions.map(v => v.replace(/\./g, '_')); + return ` + + + + + + + + ${versions.map(v => ``).join(`\n `)} + + + + + ${categories.map(c => ``).join(`\n `)} + + + ${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)} + + +`; +} +function renderADML(appName, versions, categories, policies, translations) { + return ` + + + + + + ${appName} + ${versions.map(v => `${appName} >= ${v}`).join(`\n `)} + ${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)} + ${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)} + + + ${policies.map(p => p.renderADMLPresentation()).join(`\n `)} + + + +`; +} +function renderProfileManifest(appName, bundleIdentifier, _versions, _categories, policies, translations) { + const requiredPayloadFields = ` + + pfm_default + Configure ${appName} + pfm_name + PayloadDescription + pfm_title + Payload Description + pfm_type + string + + + pfm_default + ${appName} + pfm_name + PayloadDisplayName + pfm_require + always + pfm_title + Payload Display Name + pfm_type + string + + + pfm_default + ${bundleIdentifier} + pfm_name + PayloadIdentifier + pfm_require + always + pfm_title + Payload Identifier + pfm_type + string + + + pfm_default + ${bundleIdentifier} + pfm_name + PayloadType + pfm_require + always + pfm_title + Payload Type + pfm_type + string + + + pfm_default + + pfm_name + PayloadUUID + pfm_require + always + pfm_title + Payload UUID + pfm_type + string + + + pfm_default + 1 + pfm_name + PayloadVersion + pfm_range_list + + 1 + + pfm_require + always + pfm_title + Payload Version + pfm_type + integer + + + pfm_default + Microsoft + pfm_name + PayloadOrganization + pfm_title + Payload Organization + pfm_type + string + `; + const profileManifestSubkeys = policies.map(policy => { + return policy.renderProfileManifest(translations); + }).join(''); + return ` + + + + pfm_app_url + https://code.visualstudio.com/ + pfm_description + ${appName} Managed Settings + pfm_documentation_url + https://code.visualstudio.com/docs/setup/enterprise + pfm_domain + ${bundleIdentifier} + pfm_format_version + 1 + pfm_interaction + combined + pfm_last_modified + ${new Date().toISOString().replace(/\.\d+Z$/, 'Z')} + pfm_platforms + + macOS + + pfm_subkeys + + ${requiredPayloadFields} + ${profileManifestSubkeys} + + pfm_title + ${appName} + pfm_unique + + pfm_version + 1 + +`; +} +function renderMacOSPolicy(product, policies, translations) { + const appName = product.nameLong; + const bundleIdentifier = product.darwinBundleIdentifier; + const payloadUUID = product.darwinProfilePayloadUUID; + const UUID = product.darwinProfileUUID; + const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); + const categories = [...new Set(policies.map(p => p.category))]; + const policyEntries = policies.map(policy => policy.renderProfile()) + .flat() + .map(entry => `\t\t\t\t${entry}`) + .join('\n'); + return { + profile: ` + + + + PayloadContent + + + PayloadDisplayName + ${appName} + PayloadIdentifier + ${bundleIdentifier}.${UUID} + PayloadType + ${bundleIdentifier} + PayloadUUID + ${UUID} + PayloadVersion + 1 +${policyEntries} + + + PayloadDescription + This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise + PayloadDisplayName + ${appName} + PayloadIdentifier + ${bundleIdentifier} + PayloadOrganization + Microsoft + PayloadType + Configuration + PayloadUUID + ${payloadUUID} + PayloadVersion + 1 + TargetDeviceType + 5 + +`, + manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) }, + ...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) })) + ] + }; +} +function renderGP(product, policies, translations) { + const appName = product.nameLong; + const regKey = product.win32RegValueName; + const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); + const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))]; + return { + admx: renderADMX(regKey, versions, categories, policies), + adml: [ + { languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) }, + ...translations.map(({ languageId, languageTranslations }) => ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) })) + ] + }; +} +function renderJsonPolicies(policies) { + const policyObject = {}; + for (const policy of policies) { + policyObject[policy.name] = policy.renderJsonValue(); + } + return policyObject; +} +//# sourceMappingURL=render.js.map \ No newline at end of file diff --git a/build/lib/policies/render.ts b/build/lib/policies/render.ts new file mode 100644 index 00000000000..8aa4181753d --- /dev/null +++ b/build/lib/policies/render.ts @@ -0,0 +1,303 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { NlsString, LanguageTranslations, Category, Policy, Translations, ProductJson } from './types'; + +export function renderADMLString(prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string { + let value: string | undefined; + + if (translations) { + const moduleTranslations = translations[moduleName]; + + if (moduleTranslations) { + value = moduleTranslations[nlsString.nlsKey]; + } + } + + if (!value) { + value = nlsString.value; + } + + return `${value}`; +} + +export function renderProfileString(_prefix: string, moduleName: string, nlsString: NlsString, translations?: LanguageTranslations): string { + let value: string | undefined; + + if (translations) { + const moduleTranslations = translations[moduleName]; + + if (moduleTranslations) { + value = moduleTranslations[nlsString.nlsKey]; + } + } + + if (!value) { + value = nlsString.value; + } + + return value; +} + +export function renderADMX(regKey: string, versions: string[], categories: Category[], policies: Policy[]) { + versions = versions.map(v => v.replace(/\./g, '_')); + + return ` + + + + + + + + ${versions.map(v => ``).join(`\n `)} + + + + + ${categories.map(c => ``).join(`\n `)} + + + ${policies.map(p => p.renderADMX(regKey)).flat().join(`\n `)} + + +`; +} + +export function renderADML(appName: string, versions: string[], categories: Category[], policies: Policy[], translations?: LanguageTranslations) { + return ` + + + + + + ${appName} + ${versions.map(v => `${appName} >= ${v}`).join(`\n `)} + ${categories.map(c => renderADMLString('Category', c.moduleName, c.name, translations)).join(`\n `)} + ${policies.map(p => p.renderADMLStrings(translations)).flat().join(`\n `)} + + + ${policies.map(p => p.renderADMLPresentation()).join(`\n `)} + + + +`; +} + +export function renderProfileManifest(appName: string, bundleIdentifier: string, _versions: string[], _categories: Category[], policies: Policy[], translations?: LanguageTranslations) { + + const requiredPayloadFields = ` + + pfm_default + Configure ${appName} + pfm_name + PayloadDescription + pfm_title + Payload Description + pfm_type + string + + + pfm_default + ${appName} + pfm_name + PayloadDisplayName + pfm_require + always + pfm_title + Payload Display Name + pfm_type + string + + + pfm_default + ${bundleIdentifier} + pfm_name + PayloadIdentifier + pfm_require + always + pfm_title + Payload Identifier + pfm_type + string + + + pfm_default + ${bundleIdentifier} + pfm_name + PayloadType + pfm_require + always + pfm_title + Payload Type + pfm_type + string + + + pfm_default + + pfm_name + PayloadUUID + pfm_require + always + pfm_title + Payload UUID + pfm_type + string + + + pfm_default + 1 + pfm_name + PayloadVersion + pfm_range_list + + 1 + + pfm_require + always + pfm_title + Payload Version + pfm_type + integer + + + pfm_default + Microsoft + pfm_name + PayloadOrganization + pfm_title + Payload Organization + pfm_type + string + `; + + const profileManifestSubkeys = policies.map(policy => { + return policy.renderProfileManifest(translations); + }).join(''); + + return ` + + + + pfm_app_url + https://code.visualstudio.com/ + pfm_description + ${appName} Managed Settings + pfm_documentation_url + https://code.visualstudio.com/docs/setup/enterprise + pfm_domain + ${bundleIdentifier} + pfm_format_version + 1 + pfm_interaction + combined + pfm_last_modified + ${new Date().toISOString().replace(/\.\d+Z$/, 'Z')} + pfm_platforms + + macOS + + pfm_subkeys + + ${requiredPayloadFields} + ${profileManifestSubkeys} + + pfm_title + ${appName} + pfm_unique + + pfm_version + 1 + +`; +} + +export function renderMacOSPolicy(product: ProductJson, policies: Policy[], translations: Translations) { + const appName = product.nameLong; + const bundleIdentifier = product.darwinBundleIdentifier; + const payloadUUID = product.darwinProfilePayloadUUID; + const UUID = product.darwinProfileUUID; + + const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); + const categories = [...new Set(policies.map(p => p.category))]; + + const policyEntries = + policies.map(policy => policy.renderProfile()) + .flat() + .map(entry => `\t\t\t\t${entry}`) + .join('\n'); + + + return { + profile: ` + + + + PayloadContent + + + PayloadDisplayName + ${appName} + PayloadIdentifier + ${bundleIdentifier}.${UUID} + PayloadType + ${bundleIdentifier} + PayloadUUID + ${UUID} + PayloadVersion + 1 +${policyEntries} + + + PayloadDescription + This profile manages ${appName}. For more information see https://code.visualstudio.com/docs/setup/enterprise + PayloadDisplayName + ${appName} + PayloadIdentifier + ${bundleIdentifier} + PayloadOrganization + Microsoft + PayloadType + Configuration + PayloadUUID + ${payloadUUID} + PayloadVersion + 1 + TargetDeviceType + 5 + +`, + manifests: [{ languageId: 'en-us', contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies) }, + ...translations.map(({ languageId, languageTranslations }) => + ({ languageId, contents: renderProfileManifest(appName, bundleIdentifier, versions, categories, policies, languageTranslations) })) + ] + }; +} + +export function renderGP(product: ProductJson, policies: Policy[], translations: Translations) { + const appName = product.nameLong; + const regKey = product.win32RegValueName; + + const versions = [...new Set(policies.map(p => p.minimumVersion)).values()].sort(); + const categories = [...Object.values(policies.reduce((acc, p) => ({ ...acc, [p.category.name.nlsKey]: p.category }), {}))] as Category[]; + + return { + admx: renderADMX(regKey, versions, categories, policies), + adml: [ + { languageId: 'en-us', contents: renderADML(appName, versions, categories, policies) }, + ...translations.map(({ languageId, languageTranslations }) => + ({ languageId, contents: renderADML(appName, versions, categories, policies, languageTranslations) })) + ] + }; +} + +export function renderJsonPolicies(policies: Policy[]) { + const policyObject: { [key: string]: string | number | boolean | object | null } = {}; + for (const policy of policies) { + policyObject[policy.name] = policy.renderJsonValue(); + } + return policyObject; +} diff --git a/build/lib/policies/stringEnumPolicy.js b/build/lib/policies/stringEnumPolicy.js new file mode 100644 index 00000000000..20403b3590a --- /dev/null +++ b/build/lib/policies/stringEnumPolicy.js @@ -0,0 +1,74 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StringEnumPolicy = void 0; +const basePolicy_1 = require("./basePolicy"); +const render_1 = require("./render"); +const types_1 = require("./types"); +class StringEnumPolicy extends basePolicy_1.BasePolicy { + enum_; + enumDescriptions; + static from(category, policy) { + const { type, name, minimumVersion, enum: enumValue, localization } = policy; + if (type !== 'string') { + return undefined; + } + const enum_ = enumValue; + if (!enum_) { + return undefined; + } + if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) { + throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`); + } + const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value })); + return new StringEnumPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, '', enum_, enumDescriptions); + } + constructor(name, category, minimumVersion, description, moduleName, enum_, enumDescriptions) { + super(types_1.PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); + this.enum_ = enum_; + this.enumDescriptions = enumDescriptions; + } + renderADMXElements() { + return [ + ``, + ...this.enum_.map((value, index) => ` ${value}`), + `` + ]; + } + renderADMLStrings(translations) { + return [ + ...super.renderADMLStrings(translations), + ...this.enumDescriptions.map(e => this.renderADMLString(e, translations)) + ]; + } + renderADMLPresentationContents() { + return ``; + } + renderJsonValue() { + return this.enum_[0]; + } + renderProfileValue() { + return `${this.enum_[0]}`; + } + renderProfileManifestValue(translations) { + return `pfm_default +${this.enum_[0]} +pfm_description +${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string +pfm_range_list + + ${this.enum_.map(e => `${e}`).join('\n ')} +`; + } +} +exports.StringEnumPolicy = StringEnumPolicy; +//# sourceMappingURL=stringEnumPolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/stringEnumPolicy.ts b/build/lib/policies/stringEnumPolicy.ts new file mode 100644 index 00000000000..c4adabdace7 --- /dev/null +++ b/build/lib/policies/stringEnumPolicy.ts @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BasePolicy } from './basePolicy'; +import { CategoryDto, PolicyDto } from './policyDto'; +import { renderProfileString } from './render'; +import { Category, NlsString, PolicyType, LanguageTranslations } from './types'; + +export class StringEnumPolicy extends BasePolicy { + + static from(category: CategoryDto, policy: PolicyDto): StringEnumPolicy | undefined { + const { type, name, minimumVersion, enum: enumValue, localization } = policy; + + if (type !== 'string') { + return undefined; + } + + const enum_ = enumValue; + + if (!enum_) { + return undefined; + } + + if (!localization.enumDescriptions || !Array.isArray(localization.enumDescriptions) || localization.enumDescriptions.length !== enum_.length) { + throw new Error(`Invalid policy data: enumDescriptions must exist and have the same length as enum_ for policy "${name}".`); + } + const enumDescriptions = localization.enumDescriptions.map((e) => ({ nlsKey: e.key, value: e.value })); + return new StringEnumPolicy( + name, + { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, + minimumVersion, + { nlsKey: localization.description.key, value: localization.description.value }, + '', + enum_, + enumDescriptions + ); + } + + private constructor( + name: string, + category: Category, + minimumVersion: string, + description: NlsString, + moduleName: string, + protected enum_: string[], + protected enumDescriptions: NlsString[], + ) { + super(PolicyType.StringEnum, name, category, minimumVersion, description, moduleName); + } + + protected renderADMXElements(): string[] { + return [ + ``, + ...this.enum_.map((value, index) => ` ${value}`), + `` + ]; + } + + renderADMLStrings(translations?: LanguageTranslations) { + return [ + ...super.renderADMLStrings(translations), + ...this.enumDescriptions.map(e => this.renderADMLString(e, translations)) + ]; + } + + renderADMLPresentationContents() { + return ``; + } + + renderJsonValue() { + return this.enum_[0]; + } + + renderProfileValue() { + return `${this.enum_[0]}`; + } + + renderProfileManifestValue(translations?: LanguageTranslations): string { + return `pfm_default +${this.enum_[0]} +pfm_description +${renderProfileString(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string +pfm_range_list + + ${this.enum_.map(e => `${e}`).join('\n ')} +`; + } +} diff --git a/build/lib/policies/stringPolicy.js b/build/lib/policies/stringPolicy.js new file mode 100644 index 00000000000..1db9e53649b --- /dev/null +++ b/build/lib/policies/stringPolicy.js @@ -0,0 +1,48 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StringPolicy = void 0; +const basePolicy_1 = require("./basePolicy"); +const render_1 = require("./render"); +const types_1 = require("./types"); +class StringPolicy extends basePolicy_1.BasePolicy { + static from(category, policy) { + const { type, name, minimumVersion, localization } = policy; + if (type !== 'string') { + return undefined; + } + return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + constructor(name, category, minimumVersion, description, moduleName) { + super(types_1.PolicyType.String, name, category, minimumVersion, description, moduleName); + } + renderADMXElements() { + return [``]; + } + renderJsonValue() { + return ''; + } + renderADMLPresentationContents() { + return ``; + } + renderProfileValue() { + return ``; + } + renderProfileManifestValue(translations) { + return `pfm_default + +pfm_description +${(0, render_1.renderProfileString)(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string`; + } +} +exports.StringPolicy = StringPolicy; +//# sourceMappingURL=stringPolicy.js.map \ No newline at end of file diff --git a/build/lib/policies/stringPolicy.ts b/build/lib/policies/stringPolicy.ts new file mode 100644 index 00000000000..e318a6165d8 --- /dev/null +++ b/build/lib/policies/stringPolicy.ts @@ -0,0 +1,61 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { BasePolicy } from './basePolicy'; +import { CategoryDto, PolicyDto } from './policyDto'; +import { renderProfileString } from './render'; +import { Category, NlsString, PolicyType, LanguageTranslations } from './types'; + +export class StringPolicy extends BasePolicy { + + static from(category: CategoryDto, policy: PolicyDto): StringPolicy | undefined { + const { type, name, minimumVersion, localization } = policy; + + if (type !== 'string') { + return undefined; + } + + return new StringPolicy(name, { moduleName: '', name: { nlsKey: category.name.key, value: category.name.value } }, minimumVersion, { nlsKey: localization.description.key, value: localization.description.value }, ''); + } + + private constructor( + name: string, + category: Category, + minimumVersion: string, + description: NlsString, + moduleName: string, + ) { + super(PolicyType.String, name, category, minimumVersion, description, moduleName); + } + + protected renderADMXElements(): string[] { + return [``]; + } + + renderJsonValue() { + return ''; + } + + renderADMLPresentationContents() { + return ``; + } + + renderProfileValue(): string { + return ``; + } + + renderProfileManifestValue(translations?: LanguageTranslations): string { + return `pfm_default + +pfm_description +${renderProfileString(this.name, this.moduleName, this.description, translations)} +pfm_name +${this.name} +pfm_title +${this.name} +pfm_type +string`; + } +} diff --git a/build/lib/policies/types.js b/build/lib/policies/types.js new file mode 100644 index 00000000000..9eab676dec5 --- /dev/null +++ b/build/lib/policies/types.js @@ -0,0 +1,31 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Languages = exports.PolicyType = void 0; +var PolicyType; +(function (PolicyType) { + PolicyType["Boolean"] = "boolean"; + PolicyType["Number"] = "number"; + PolicyType["Object"] = "object"; + PolicyType["String"] = "string"; + PolicyType["StringEnum"] = "stringEnum"; +})(PolicyType || (exports.PolicyType = PolicyType = {})); +exports.Languages = { + 'fr': 'fr-fr', + 'it': 'it-it', + 'de': 'de-de', + 'es': 'es-es', + 'ru': 'ru-ru', + 'zh-hans': 'zh-cn', + 'zh-hant': 'zh-tw', + 'ja': 'ja-jp', + 'ko': 'ko-kr', + 'cs': 'cs-cz', + 'pt-br': 'pt-br', + 'tr': 'tr-tr', + 'pl': 'pl-pl', +}; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/lib/policies/types.ts b/build/lib/policies/types.ts new file mode 100644 index 00000000000..861b5205f69 --- /dev/null +++ b/build/lib/policies/types.ts @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export interface ProductJson { + readonly nameLong: string; + readonly darwinBundleIdentifier: string; + readonly darwinProfilePayloadUUID: string; + readonly darwinProfileUUID: string; + readonly win32RegValueName: string; + readonly extensionsGallery?: { + readonly serviceUrl: string; + readonly resourceUrlTemplate: string; + }; +} + +export interface Policy { + readonly name: string; + readonly type: PolicyType; + readonly category: Category; + readonly minimumVersion: string; + renderADMX(regKey: string): string[]; + renderADMLStrings(translations?: LanguageTranslations): string[]; + renderADMLPresentation(): string; + renderJsonValue(): string | number | boolean | object | null; + renderProfile(): string[]; + // https://github.com/ProfileManifests/ProfileManifests/wiki/Manifest-Format + renderProfileManifest(translations?: LanguageTranslations): string; +} + +export type NlsString = { value: string; nlsKey: string }; + +export interface Category { + readonly moduleName: string; + readonly name: NlsString; +} + +export enum PolicyType { + Boolean = 'boolean', + Number = 'number', + Object = 'object', + String = 'string', + StringEnum = 'stringEnum', +} + +export const Languages = { + 'fr': 'fr-fr', + 'it': 'it-it', + 'de': 'de-de', + 'es': 'es-es', + 'ru': 'ru-ru', + 'zh-hans': 'zh-cn', + 'zh-hant': 'zh-tw', + 'ja': 'ja-jp', + 'ko': 'ko-kr', + 'cs': 'cs-cz', + 'pt-br': 'pt-br', + 'tr': 'tr-tr', + 'pl': 'pl-pl', +}; + +export type LanguageTranslations = { [moduleName: string]: { [nlsKey: string]: string } }; +export type Translations = { languageId: string; languageTranslations: LanguageTranslations }[]; + +export type Version = [number, number, number]; diff --git a/build/lib/preLaunch.js b/build/lib/preLaunch.js index ca79a09b068..75207fe50c0 100644 --- a/build/lib/preLaunch.js +++ b/build/lib/preLaunch.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); // @ts-check const path_1 = __importDefault(require("path")); const child_process_1 = require("child_process"); diff --git a/build/lib/propertyInitOrderChecker.js b/build/lib/propertyInitOrderChecker.js index a8dab0f29fe..58921645599 100644 --- a/build/lib/propertyInitOrderChecker.js +++ b/build/lib/propertyInitOrderChecker.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -33,10 +37,6 @@ var __importStar = (this && this.__importStar) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const ts = __importStar(require("typescript")); const path = __importStar(require("path")); const fs = __importStar(require("fs")); diff --git a/build/lib/reporter.js b/build/lib/reporter.js index f07b7626199..cb7fd272d5d 100644 --- a/build/lib/reporter.js +++ b/build/lib/reporter.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createReporter = createReporter; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const fancy_log_1 = __importDefault(require("fancy-log")); const ansi_colors_1 = __importDefault(require("ansi-colors")); diff --git a/build/lib/snapshotLoader.js b/build/lib/snapshotLoader.js index 315ebcc1e01..7d9b3f154f1 100644 --- a/build/lib/snapshotLoader.js +++ b/build/lib/snapshotLoader.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.snaps = void 0; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.snaps = void 0; var snaps; (function (snaps) { const fs = require('fs'); diff --git a/build/lib/standalone.js b/build/lib/standalone.js index b153e70348b..e8f81f92dea 100644 --- a/build/lib/standalone.js +++ b/build/lib/standalone.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -37,10 +41,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractEditor = extractEditor; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const tss = __importStar(require("./treeshaking")); @@ -85,8 +85,11 @@ function extractEditor(options) { const result = tss.shake(options); for (const fileName in result) { if (result.hasOwnProperty(fileName)) { + let fileContents = result[fileName]; + // Replace .ts? with .js? in new URL() patterns + fileContents = fileContents.replace(/(new\s+URL\s*\(\s*['"`][^'"`]*?)\.ts(\?[^'"`]*['"`])/g, '$1.js$2'); const relativePath = path_1.default.relative(options.sourcesRoot, fileName); - writeFile(path_1.default.join(options.destRoot, relativePath), result[fileName]); + writeFile(path_1.default.join(options.destRoot, relativePath), fileContents); } } const copied = {}; diff --git a/build/lib/standalone.ts b/build/lib/standalone.ts index 5f2104cb4c6..bd2971b9894 100644 --- a/build/lib/standalone.ts +++ b/build/lib/standalone.ts @@ -57,8 +57,14 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str const result = tss.shake(options); for (const fileName in result) { if (result.hasOwnProperty(fileName)) { + let fileContents = result[fileName]; + // Replace .ts? with .js? in new URL() patterns + fileContents = fileContents.replace( + /(new\s+URL\s*\(\s*['"`][^'"`]*?)\.ts(\?[^'"`]*['"`])/g, + '$1.js$2' + ); const relativePath = path.relative(options.sourcesRoot, fileName); - writeFile(path.join(options.destRoot, relativePath), result[fileName]); + writeFile(path.join(options.destRoot, relativePath), fileContents); } } const copied: { [fileName: string]: boolean } = {}; diff --git a/build/lib/stats.js b/build/lib/stats.js index e6a4f9f633e..3f6d953ae40 100644 --- a/build/lib/stats.js +++ b/build/lib/stats.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createStatsStream = createStatsStream; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const fancy_log_1 = __importDefault(require("fancy-log")); const ansi_colors_1 = __importDefault(require("ansi-colors")); diff --git a/build/lib/stylelint/validateVariableNames.js b/build/lib/stylelint/validateVariableNames.js index a5e84d415ba..b0e064e7b56 100644 --- a/build/lib/stylelint/validateVariableNames.js +++ b/build/lib/stylelint/validateVariableNames.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getVariableNameValidator = getVariableNameValidator; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const RE_VAR_PROP = /var\(\s*(--([\w\-\.]+))/g; diff --git a/build/lib/stylelint/vscode-known-variables.json b/build/lib/stylelint/vscode-known-variables.json index 3ff1a9f624b..2b42bca7fa3 100644 --- a/build/lib/stylelint/vscode-known-variables.json +++ b/build/lib/stylelint/vscode-known-variables.json @@ -54,13 +54,6 @@ "--vscode-chat-avatarForeground", "--vscode-chat-checkpointSeparator", "--vscode-chat-editedFileForeground", - "--vscode-chat-font-family", - "--vscode-chat-font-size-body-l", - "--vscode-chat-font-size-body-m", - "--vscode-chat-font-size-body-s", - "--vscode-chat-font-size-body-xl", - "--vscode-chat-font-size-body-xs", - "--vscode-chat-font-size-body-xxl", "--vscode-chat-linesAddedForeground", "--vscode-chat-linesRemovedForeground", "--vscode-chat-requestBackground", @@ -70,6 +63,7 @@ "--vscode-chat-requestCodeBorder", "--vscode-chat-slashCommandBackground", "--vscode-chat-slashCommandForeground", + "--vscode-chatManagement-sashBorder", "--vscode-checkbox-background", "--vscode-checkbox-border", "--vscode-checkbox-disabled-background", @@ -245,6 +239,7 @@ "--vscode-editorGutter-addedBackground", "--vscode-editorGutter-addedSecondaryBackground", "--vscode-editorGutter-background", + "--vscode-editorGutter-commentDraftGlyphForeground", "--vscode-editorGutter-commentGlyphForeground", "--vscode-editorGutter-commentRangeForeground", "--vscode-editorGutter-commentUnresolvedGlyphForeground", @@ -310,6 +305,7 @@ "--vscode-editorOverviewRuler-bracketMatchForeground", "--vscode-editorOverviewRuler-commentForeground", "--vscode-editorOverviewRuler-commentUnresolvedForeground", + "--vscode-editorOverviewRuler-commentDraftForeground", "--vscode-editorOverviewRuler-commonContentForeground", "--vscode-editorOverviewRuler-currentContentForeground", "--vscode-editorOverviewRuler-deletedForeground", @@ -464,6 +460,11 @@ "--vscode-listFilterWidget-noMatchesOutline", "--vscode-listFilterWidget-outline", "--vscode-listFilterWidget-shadow", + "--vscode-markdownAlert-caution-foreground", + "--vscode-markdownAlert-important-foreground", + "--vscode-markdownAlert-note-foreground", + "--vscode-markdownAlert-tip-foreground", + "--vscode-markdownAlert-warning-foreground", "--vscode-mcpIcon-starForeground", "--vscode-menu-background", "--vscode-menu-border", @@ -622,6 +623,7 @@ "--vscode-scmGraph-historyItemHoverLabelForeground", "--vscode-scmGraph-historyItemRefColor", "--vscode-scmGraph-historyItemRemoteRefColor", + "--vscode-scrollbar-background", "--vscode-scrollbar-shadow", "--vscode-scrollbarSlider-activeBackground", "--vscode-scrollbarSlider-background", @@ -822,6 +824,7 @@ "--vscode-terminalSymbolIcon-pullRequestForeground", "--vscode-terminalSymbolIcon-remoteForeground", "--vscode-terminalSymbolIcon-stashForeground", + "--vscode-terminalSymbolIcon-symbolText", "--vscode-terminalSymbolIcon-symbolicLinkFileForeground", "--vscode-terminalSymbolIcon-symbolicLinkFolderForeground", "--vscode-terminalSymbolIcon-tagForeground", @@ -895,10 +898,7 @@ "--background-light", "--chat-editing-last-edit-shift", "--chat-current-response-min-height", - "--dropdown-padding-bottom", - "--dropdown-padding-top", "--inline-chat-frame-progress", - "--inline-chat-hint-progress", "--insert-border-color", "--last-tab-margin-right", "--monaco-monospace-font", @@ -986,6 +986,10 @@ "--vscode-chat-font-size-body-s", "--vscode-chat-font-size-body-xl", "--vscode-chat-font-size-body-xs", - "--vscode-chat-font-size-body-xxl" + "--vscode-chat-font-size-body-xxl", + "--comment-thread-editor-font-family", + "--comment-thread-editor-font-weight", + "--comment-thread-state-color", + "--comment-thread-state-background-color" ] } diff --git a/build/lib/task.js b/build/lib/task.js index 23b8d968584..a30b65b288c 100644 --- a/build/lib/task.js +++ b/build/lib/task.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -6,10 +10,6 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.series = series; exports.parallel = parallel; exports.define = define; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fancy_log_1 = __importDefault(require("fancy-log")); const ansi_colors_1 = __importDefault(require("ansi-colors")); function _isPromise(p) { diff --git a/build/lib/test/booleanPolicy.test.js b/build/lib/test/booleanPolicy.test.js new file mode 100644 index 00000000000..944916c3d76 --- /dev/null +++ b/build/lib/test/booleanPolicy.test.js @@ -0,0 +1,126 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const booleanPolicy_js_1 = require("../policies/booleanPolicy.js"); +const types_js_1 = require("../policies/types.js"); +suite('BooleanPolicy', () => { + const mockCategory = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + const mockPolicy = { + key: 'test.boolean.policy', + name: 'TestBooleanPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'boolean', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' } + } + }; + test('should create BooleanPolicy from factory method', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + assert_1.default.strictEqual(policy.name, 'TestBooleanPolicy'); + assert_1.default.strictEqual(policy.minimumVersion, '1.0'); + assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value); + assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Boolean); + }); + test('should render ADMX elements correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admx = policy.renderADMX('TestKey'); + assert_1.default.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '', + '\t', + '' + ]); + }); + test('should render ADML strings correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admlStrings = policy.renderADMLStrings(); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestBooleanPolicy', + 'Test policy description' + ]); + }); + test('should render ADML strings with translations', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + const admlStrings = policy.renderADMLStrings(translations); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestBooleanPolicy', + 'Translated description' + ]); + }); + test('should render ADML presentation correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const presentation = policy.renderADMLPresentation(); + assert_1.default.strictEqual(presentation, 'TestBooleanPolicy'); + }); + test('should render JSON value correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const jsonValue = policy.renderJsonValue(); + assert_1.default.strictEqual(jsonValue, false); + }); + test('should render profile value correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profileValue = policy.renderProfileValue(); + assert_1.default.strictEqual(profileValue, ''); + }); + test('should render profile correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profile = policy.renderProfile(); + assert_1.default.strictEqual(profile.length, 2); + assert_1.default.strictEqual(profile[0], 'TestBooleanPolicy'); + assert_1.default.strictEqual(profile[1], ''); + }); + test('should render profile manifest value correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifestValue = policy.renderProfileManifestValue(); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest policy description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean'); + }); + test('should render profile manifest value with translations', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + const manifestValue = policy.renderProfileManifestValue(translations); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean'); + }); + test('should render profile manifest correctly', () => { + const policy = booleanPolicy_js_1.BooleanPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifest = policy.renderProfileManifest(); + assert_1.default.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest policy description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean\n'); + }); +}); +//# sourceMappingURL=booleanPolicy.test.js.map \ No newline at end of file diff --git a/build/lib/test/booleanPolicy.test.ts b/build/lib/test/booleanPolicy.test.ts new file mode 100644 index 00000000000..8da223530b9 --- /dev/null +++ b/build/lib/test/booleanPolicy.test.ts @@ -0,0 +1,168 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { BooleanPolicy } from '../policies/booleanPolicy.js'; +import { LanguageTranslations, PolicyType } from '../policies/types.js'; +import { CategoryDto, PolicyDto } from '../policies/policyDto.js'; + +suite('BooleanPolicy', () => { + const mockCategory: CategoryDto = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + + const mockPolicy: PolicyDto = { + key: 'test.boolean.policy', + name: 'TestBooleanPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'boolean', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' } + } + }; + + test('should create BooleanPolicy from factory method', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + assert.strictEqual(policy.name, 'TestBooleanPolicy'); + assert.strictEqual(policy.minimumVersion, '1.0'); + assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert.strictEqual(policy.category.name.value, mockCategory.name.value); + assert.strictEqual(policy.type, PolicyType.Boolean); + }); + + test('should render ADMX elements correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admx = policy.renderADMX('TestKey'); + + assert.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '', + '\t', + '' + ]); + }); + + test('should render ADML strings correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admlStrings = policy.renderADMLStrings(); + + assert.deepStrictEqual(admlStrings, [ + 'TestBooleanPolicy', + 'Test policy description' + ]); + }); + + test('should render ADML strings with translations', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + + const admlStrings = policy.renderADMLStrings(translations); + + assert.deepStrictEqual(admlStrings, [ + 'TestBooleanPolicy', + 'Translated description' + ]); + }); + + test('should render ADML presentation correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const presentation = policy.renderADMLPresentation(); + + assert.strictEqual(presentation, 'TestBooleanPolicy'); + }); + + test('should render JSON value correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const jsonValue = policy.renderJsonValue(); + + assert.strictEqual(jsonValue, false); + }); + + test('should render profile value correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profileValue = policy.renderProfileValue(); + + assert.strictEqual(profileValue, ''); + }); + + test('should render profile correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profile = policy.renderProfile(); + + assert.strictEqual(profile.length, 2); + assert.strictEqual(profile[0], 'TestBooleanPolicy'); + assert.strictEqual(profile[1], ''); + }); + + test('should render profile manifest value correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifestValue = policy.renderProfileManifestValue(); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest policy description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean'); + }); + + test('should render profile manifest value with translations', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + + const manifestValue = policy.renderProfileManifestValue(translations); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean'); + }); + + test('should render profile manifest correctly', () => { + const policy = BooleanPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifest = policy.renderProfileManifest(); + + assert.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest policy description\npfm_name\nTestBooleanPolicy\npfm_title\nTestBooleanPolicy\npfm_type\nboolean\n'); + }); +}); diff --git a/build/lib/test/fixtures/policies/darwin/com.visualstudio.code.oss.mobileconfig b/build/lib/test/fixtures/policies/darwin/com.visualstudio.code.oss.mobileconfig new file mode 100644 index 00000000000..0f0ae365d7c --- /dev/null +++ b/build/lib/test/fixtures/policies/darwin/com.visualstudio.code.oss.mobileconfig @@ -0,0 +1,61 @@ + + + + + PayloadContent + + + PayloadDisplayName + Code - OSS + PayloadIdentifier + com.visualstudio.code.oss.47827DD9-4734-49A0-AF80-7E19B11495CC + PayloadType + com.visualstudio.code.oss + PayloadUUID + 47827DD9-4734-49A0-AF80-7E19B11495CC + PayloadVersion + 1 + ChatAgentExtensionTools + + ChatAgentMode + + ChatMCP + none + ChatPromptFiles + + ChatToolsAutoApprove + + McpGalleryServiceUrl + + AllowedExtensions + + ExtensionGalleryServiceUrl + + ChatToolsTerminalEnableAutoApprove + + EnableFeedback + + TelemetryLevel + all + UpdateMode + none + + + PayloadDescription + This profile manages Code - OSS. For more information see https://code.visualstudio.com/docs/setup/enterprise + PayloadDisplayName + Code - OSS + PayloadIdentifier + com.visualstudio.code.oss + PayloadOrganization + Microsoft + PayloadType + Configuration + PayloadUUID + CF808BE7-53F3-46C6-A7E2-7EDB98A5E959 + PayloadVersion + 1 + TargetDeviceType + 5 + + \ No newline at end of file diff --git a/build/lib/test/fixtures/policies/darwin/en-us/com.visualstudio.code.oss.plist b/build/lib/test/fixtures/policies/darwin/en-us/com.visualstudio.code.oss.plist new file mode 100644 index 00000000000..f90533cfeaa --- /dev/null +++ b/build/lib/test/fixtures/policies/darwin/en-us/com.visualstudio.code.oss.plist @@ -0,0 +1,274 @@ + + + + + pfm_app_url + https://code.visualstudio.com/ + pfm_description + Code - OSS Managed Settings + pfm_documentation_url + https://code.visualstudio.com/docs/setup/enterprise + pfm_domain + com.visualstudio.code.oss + pfm_format_version + 1 + pfm_interaction + combined + pfm_last_modified + 2025-10-21T23:04:34Z + pfm_platforms + + macOS + + pfm_subkeys + + + + pfm_default + Configure Code - OSS + pfm_name + PayloadDescription + pfm_title + Payload Description + pfm_type + string + + + pfm_default + Code - OSS + pfm_name + PayloadDisplayName + pfm_require + always + pfm_title + Payload Display Name + pfm_type + string + + + pfm_default + com.visualstudio.code.oss + pfm_name + PayloadIdentifier + pfm_require + always + pfm_title + Payload Identifier + pfm_type + string + + + pfm_default + com.visualstudio.code.oss + pfm_name + PayloadType + pfm_require + always + pfm_title + Payload Type + pfm_type + string + + + pfm_default + + pfm_name + PayloadUUID + pfm_require + always + pfm_title + Payload UUID + pfm_type + string + + + pfm_default + 1 + pfm_name + PayloadVersion + pfm_range_list + + 1 + + pfm_require + always + pfm_title + Payload Version + pfm_type + integer + + + pfm_default + Microsoft + pfm_name + PayloadOrganization + pfm_title + Payload Organization + pfm_type + string + + +pfm_default + +pfm_description +Enable using tools contributed by third-party extensions. +pfm_name +ChatAgentExtensionTools +pfm_title +ChatAgentExtensionTools +pfm_type +boolean + +pfm_default + +pfm_description +Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view. +pfm_name +ChatAgentMode +pfm_title +ChatAgentMode +pfm_type +boolean + +pfm_default +none +pfm_description +Controls access to installed Model Context Protocol servers. +pfm_name +ChatMCP +pfm_title +ChatMCP +pfm_type +string +pfm_range_list + + none + registry + all + + +pfm_default + +pfm_description +Enables reusable prompt and instruction files in Chat sessions. +pfm_name +ChatPromptFiles +pfm_title +ChatPromptFiles +pfm_type +boolean + +pfm_default + +pfm_description +Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised. + +This feature disables critical security protections and makes it much easier for an attacker to compromise the machine. +pfm_name +ChatToolsAutoApprove +pfm_title +ChatToolsAutoApprove +pfm_type +boolean + +pfm_default + +pfm_description +Configure the MCP Gallery service URL to connect to +pfm_name +McpGalleryServiceUrl +pfm_title +McpGalleryServiceUrl +pfm_type +string + +pfm_default + +pfm_description +Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions +pfm_name +AllowedExtensions +pfm_title +AllowedExtensions +pfm_type +string + + +pfm_default + +pfm_description +Configure the Marketplace service URL to connect to +pfm_name +ExtensionGalleryServiceUrl +pfm_title +ExtensionGalleryServiceUrl +pfm_type +string + +pfm_default + +pfm_description +Controls whether to allow auto approval in the run in terminal tool. +pfm_name +ChatToolsTerminalEnableAutoApprove +pfm_title +ChatToolsTerminalEnableAutoApprove +pfm_type +boolean + +pfm_default + +pfm_description +Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options. +pfm_name +EnableFeedback +pfm_title +EnableFeedback +pfm_type +boolean + +pfm_default +all +pfm_description +Controls the level of telemetry. +pfm_name +TelemetryLevel +pfm_title +TelemetryLevel +pfm_type +string +pfm_range_list + + all + error + crash + off + + +pfm_default +none +pfm_description +Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service. +pfm_name +UpdateMode +pfm_title +UpdateMode +pfm_type +string +pfm_range_list + + none + manual + start + default + + + + pfm_title + Code - OSS + pfm_unique + + pfm_version + 1 + + \ No newline at end of file diff --git a/build/lib/test/fixtures/policies/darwin/fr-fr/com.visualstudio.code.oss.plist b/build/lib/test/fixtures/policies/darwin/fr-fr/com.visualstudio.code.oss.plist new file mode 100644 index 00000000000..60f244be3b5 --- /dev/null +++ b/build/lib/test/fixtures/policies/darwin/fr-fr/com.visualstudio.code.oss.plist @@ -0,0 +1,274 @@ + + + + + pfm_app_url + https://code.visualstudio.com/ + pfm_description + Code - OSS Managed Settings + pfm_documentation_url + https://code.visualstudio.com/docs/setup/enterprise + pfm_domain + com.visualstudio.code.oss + pfm_format_version + 1 + pfm_interaction + combined + pfm_last_modified + 2025-10-21T23:04:34Z + pfm_platforms + + macOS + + pfm_subkeys + + + + pfm_default + Configure Code - OSS + pfm_name + PayloadDescription + pfm_title + Payload Description + pfm_type + string + + + pfm_default + Code - OSS + pfm_name + PayloadDisplayName + pfm_require + always + pfm_title + Payload Display Name + pfm_type + string + + + pfm_default + com.visualstudio.code.oss + pfm_name + PayloadIdentifier + pfm_require + always + pfm_title + Payload Identifier + pfm_type + string + + + pfm_default + com.visualstudio.code.oss + pfm_name + PayloadType + pfm_require + always + pfm_title + Payload Type + pfm_type + string + + + pfm_default + + pfm_name + PayloadUUID + pfm_require + always + pfm_title + Payload UUID + pfm_type + string + + + pfm_default + 1 + pfm_name + PayloadVersion + pfm_range_list + + 1 + + pfm_require + always + pfm_title + Payload Version + pfm_type + integer + + + pfm_default + Microsoft + pfm_name + PayloadOrganization + pfm_title + Payload Organization + pfm_type + string + + +pfm_default + +pfm_description +Autorisez l’utilisation d’outils fournis par des extensions tierces. +pfm_name +ChatAgentExtensionTools +pfm_title +ChatAgentExtensionTools +pfm_type +boolean + +pfm_default + +pfm_description +Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue. +pfm_name +ChatAgentMode +pfm_title +ChatAgentMode +pfm_type +boolean + +pfm_default +none +pfm_description +Contrôle l’accès aux serveurs de protocole de contexte du modèle. +pfm_name +ChatMCP +pfm_title +ChatMCP +pfm_type +string +pfm_range_list + + none + registry + all + + +pfm_default + +pfm_description +Active les fichiers d’instruction et de requête réutilisables dans les sessions Conversation. +pfm_name +ChatPromptFiles +pfm_title +ChatPromptFiles +pfm_type +boolean + +pfm_default + +pfm_description +L’approbation automatique globale, également appelée « mode YOLO », désactive complètement l’approbation manuelle pour tous les outils dans tous les espaces de travail, permettant à l’agent d’agir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises. + +Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant. +pfm_name +ChatToolsAutoApprove +pfm_title +ChatToolsAutoApprove +pfm_type +boolean + +pfm_default + +pfm_description +Configurer l’URL du service de la galerie MCP à laquelle se connecter +pfm_name +McpGalleryServiceUrl +pfm_title +McpGalleryServiceUrl +pfm_type +string + +pfm_default + +pfm_description +Spécifiez une liste d’extensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant l’utilisation d’extensions non autorisées. Plus d’informations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions +pfm_name +AllowedExtensions +pfm_title +AllowedExtensions +pfm_type +string + + +pfm_default + +pfm_description +Configurer l’URL du service Place de marché à laquelle se connecter +pfm_name +ExtensionGalleryServiceUrl +pfm_title +ExtensionGalleryServiceUrl +pfm_type +string + +pfm_default + +pfm_description +Contrôle s’il faut autoriser l’approbation automatique lors de l’exécution dans l’outil terminal. +pfm_name +ChatToolsTerminalEnableAutoApprove +pfm_title +ChatToolsTerminalEnableAutoApprove +pfm_type +boolean + +pfm_default + +pfm_description +Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires. +pfm_name +EnableFeedback +pfm_title +EnableFeedback +pfm_type +boolean + +pfm_default +all +pfm_description +Contrôle le niveau de télémétrie. +pfm_name +TelemetryLevel +pfm_title +TelemetryLevel +pfm_type +string +pfm_range_list + + all + error + crash + off + + +pfm_default +none +pfm_description +Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft. +pfm_name +UpdateMode +pfm_title +UpdateMode +pfm_type +string +pfm_range_list + + none + manual + start + default + + + + pfm_title + Code - OSS + pfm_unique + + pfm_version + 1 + + \ No newline at end of file diff --git a/build/lib/test/fixtures/policies/linux/policy.json b/build/lib/test/fixtures/policies/linux/policy.json new file mode 100644 index 00000000000..3a941999da6 --- /dev/null +++ b/build/lib/test/fixtures/policies/linux/policy.json @@ -0,0 +1,14 @@ +{ + "ChatAgentExtensionTools": false, + "ChatAgentMode": false, + "ChatMCP": "none", + "ChatPromptFiles": false, + "ChatToolsAutoApprove": false, + "McpGalleryServiceUrl": "", + "AllowedExtensions": "", + "ExtensionGalleryServiceUrl": "", + "ChatToolsTerminalEnableAutoApprove": false, + "EnableFeedback": false, + "TelemetryLevel": "all", + "UpdateMode": "none" +} \ No newline at end of file diff --git a/build/lib/test/fixtures/policies/win32/CodeOSS.admx b/build/lib/test/fixtures/policies/win32/CodeOSS.admx new file mode 100644 index 00000000000..fee094c56c5 --- /dev/null +++ b/build/lib/test/fixtures/policies/win32/CodeOSS.admx @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + none + registry + all + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + all + error + crash + off + + + + + + + + + none + manual + start + default + + + + + diff --git a/build/lib/test/fixtures/policies/win32/en-us/CodeOSS.adml b/build/lib/test/fixtures/policies/win32/en-us/CodeOSS.adml new file mode 100644 index 00000000000..39b05ddc72d --- /dev/null +++ b/build/lib/test/fixtures/policies/win32/en-us/CodeOSS.adml @@ -0,0 +1,71 @@ + + + + + + + Code - OSS + Code - OSS >= 1.101 + Code - OSS >= 1.104 + Code - OSS >= 1.67 + Code - OSS >= 1.96 + Code - OSS >= 1.99 + Chat + Extensions + Integrated Terminal + Telemetry + Update + ChatAgentExtensionTools + Enable using tools contributed by third-party extensions. + ChatAgentMode + Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view. + ChatMCP + Controls access to installed Model Context Protocol servers. + No access to MCP servers. + Allows access to MCP servers installed from the registry that VS Code is connected to. + Allow access to any installed MCP server. + ChatPromptFiles + Enables reusable prompt and instruction files in Chat sessions. + ChatToolsAutoApprove + Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised. + +This feature disables critical security protections and makes it much easier for an attacker to compromise the machine. + McpGalleryServiceUrl + Configure the MCP Gallery service URL to connect to + AllowedExtensions + Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions + ExtensionGalleryServiceUrl + Configure the Marketplace service URL to connect to + ChatToolsTerminalEnableAutoApprove + Controls whether to allow auto approval in the run in terminal tool. + EnableFeedback + Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options. + TelemetryLevel + Controls the level of telemetry. + Sends usage data, errors, and crash reports. + Sends general error telemetry and crash reports. + Sends OS level crash reports. + Disables all product telemetry. + UpdateMode + Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service. + Disable updates. + Disable automatic background update checks. Updates will be available if you manually check for updates. + Check for updates only on startup. Disable automatic background update checks. + Enable automatic update checks. Code will check for updates automatically and periodically. + + + ChatAgentExtensionTools + ChatAgentMode + + ChatPromptFiles + ChatToolsAutoApprove + + + + ChatToolsTerminalEnableAutoApprove + EnableFeedback + + + + + diff --git a/build/lib/test/fixtures/policies/win32/fr-fr/CodeOSS.adml b/build/lib/test/fixtures/policies/win32/fr-fr/CodeOSS.adml new file mode 100644 index 00000000000..eab50282b2d --- /dev/null +++ b/build/lib/test/fixtures/policies/win32/fr-fr/CodeOSS.adml @@ -0,0 +1,71 @@ + + + + + + + Code - OSS + Code - OSS >= 1.101 + Code - OSS >= 1.104 + Code - OSS >= 1.67 + Code - OSS >= 1.96 + Code - OSS >= 1.99 + Session interactive + Extensions + Terminal intégré + Télémétrie + Mettre à jour + ChatAgentExtensionTools + Autorisez l’utilisation d’outils fournis par des extensions tierces. + ChatAgentMode + Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue. + ChatMCP + Contrôle l’accès aux serveurs de protocole de contexte du modèle. + Aucun accès aux serveurs MCP. + Autorise l’accès aux serveurs MCP installés à partir du registre auquel VS Code est connecté. + Autorisez l’accès à tout serveur MCP installé. + ChatPromptFiles + Active les fichiers d’instruction et de requête réutilisables dans les sessions Conversation. + ChatToolsAutoApprove + L’approbation automatique globale, également appelée « mode YOLO », désactive complètement l’approbation manuelle pour tous les outils dans tous les espaces de travail, permettant à l’agent d’agir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises. + +Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant. + McpGalleryServiceUrl + Configurer l’URL du service de la galerie MCP à laquelle se connecter + AllowedExtensions + Spécifiez une liste d’extensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant l’utilisation d’extensions non autorisées. Plus d’informations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions + ExtensionGalleryServiceUrl + Configurer l’URL du service Place de marché à laquelle se connecter + ChatToolsTerminalEnableAutoApprove + Contrôle s’il faut autoriser l’approbation automatique lors de l’exécution dans l’outil terminal. + EnableFeedback + Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires. + TelemetryLevel + Contrôle le niveau de télémétrie. + Envoie les données d'utilisation, les erreurs et les rapports d'erreur. + Envoie la télémétrie d'erreur générale et les rapports de plantage. + Envoie des rapports de plantage au niveau du système d'exploitation. + Désactive toutes les données de télémétrie du produit. + UpdateMode + Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft. + Aucun + Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement. + Démarrer + Système + + + ChatAgentExtensionTools + ChatAgentMode + + ChatPromptFiles + ChatToolsAutoApprove + + + + ChatToolsTerminalEnableAutoApprove + EnableFeedback + + + + + diff --git a/build/lib/test/i18n.test.js b/build/lib/test/i18n.test.js index da7a426a103..41aa8a7f668 100644 --- a/build/lib/test/i18n.test.js +++ b/build/lib/test/i18n.test.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -36,10 +40,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const assert_1 = __importDefault(require("assert")); const i18n = __importStar(require("../i18n")); suite('XLF Parser Tests', () => { diff --git a/build/lib/test/numberPolicy.test.js b/build/lib/test/numberPolicy.test.js new file mode 100644 index 00000000000..312ec7587ee --- /dev/null +++ b/build/lib/test/numberPolicy.test.js @@ -0,0 +1,125 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const numberPolicy_js_1 = require("../policies/numberPolicy.js"); +const types_js_1 = require("../policies/types.js"); +suite('NumberPolicy', () => { + const mockCategory = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + const mockPolicy = { + key: 'test.number.policy', + name: 'TestNumberPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'number', + default: 42, + localization: { + description: { key: 'test.policy.description', value: 'Test number policy description' } + } + }; + test('should create NumberPolicy from factory method', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + assert_1.default.strictEqual(policy.name, 'TestNumberPolicy'); + assert_1.default.strictEqual(policy.minimumVersion, '1.0'); + assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value); + assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Number); + }); + test('should render ADMX elements correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admx = policy.renderADMX('TestKey'); + assert_1.default.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + test('should render ADML strings correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admlStrings = policy.renderADMLStrings(); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestNumberPolicy', + 'Test number policy description' + ]); + }); + test('should render ADML strings with translations', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + const admlStrings = policy.renderADMLStrings(translations); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestNumberPolicy', + 'Translated description' + ]); + }); + test('should render ADML presentation correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const presentation = policy.renderADMLPresentation(); + assert_1.default.strictEqual(presentation, 'TestNumberPolicy'); + }); + test('should render JSON value correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const jsonValue = policy.renderJsonValue(); + assert_1.default.strictEqual(jsonValue, 42); + }); + test('should render profile value correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profileValue = policy.renderProfileValue(); + assert_1.default.strictEqual(profileValue, '42'); + }); + test('should render profile correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profile = policy.renderProfile(); + assert_1.default.strictEqual(profile.length, 2); + assert_1.default.strictEqual(profile[0], 'TestNumberPolicy'); + assert_1.default.strictEqual(profile[1], '42'); + }); + test('should render profile manifest value correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifestValue = policy.renderProfileManifestValue(); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n42\npfm_description\nTest number policy description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger'); + }); + test('should render profile manifest value with translations', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + const manifestValue = policy.renderProfileManifestValue(translations); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n42\npfm_description\nTranslated manifest description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger'); + }); + test('should render profile manifest correctly', () => { + const policy = numberPolicy_js_1.NumberPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifest = policy.renderProfileManifest(); + assert_1.default.strictEqual(manifest, '\npfm_default\n42\npfm_description\nTest number policy description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger\n'); + }); +}); +//# sourceMappingURL=numberPolicy.test.js.map \ No newline at end of file diff --git a/build/lib/test/numberPolicy.test.ts b/build/lib/test/numberPolicy.test.ts new file mode 100644 index 00000000000..dfb6276e34e --- /dev/null +++ b/build/lib/test/numberPolicy.test.ts @@ -0,0 +1,167 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { NumberPolicy } from '../policies/numberPolicy.js'; +import { LanguageTranslations, PolicyType } from '../policies/types.js'; +import { CategoryDto, PolicyDto } from '../policies/policyDto.js'; + +suite('NumberPolicy', () => { + const mockCategory: CategoryDto = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + + const mockPolicy: PolicyDto = { + key: 'test.number.policy', + name: 'TestNumberPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'number', + default: 42, + localization: { + description: { key: 'test.policy.description', value: 'Test number policy description' } + } + }; + + test('should create NumberPolicy from factory method', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + assert.strictEqual(policy.name, 'TestNumberPolicy'); + assert.strictEqual(policy.minimumVersion, '1.0'); + assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert.strictEqual(policy.category.name.value, mockCategory.name.value); + assert.strictEqual(policy.type, PolicyType.Number); + }); + + test('should render ADMX elements correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admx = policy.renderADMX('TestKey'); + + assert.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + + test('should render ADML strings correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admlStrings = policy.renderADMLStrings(); + + assert.deepStrictEqual(admlStrings, [ + 'TestNumberPolicy', + 'Test number policy description' + ]); + }); + + test('should render ADML strings with translations', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + + const admlStrings = policy.renderADMLStrings(translations); + + assert.deepStrictEqual(admlStrings, [ + 'TestNumberPolicy', + 'Translated description' + ]); + }); + + test('should render ADML presentation correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const presentation = policy.renderADMLPresentation(); + + assert.strictEqual(presentation, 'TestNumberPolicy'); + }); + + test('should render JSON value correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const jsonValue = policy.renderJsonValue(); + + assert.strictEqual(jsonValue, 42); + }); + + test('should render profile value correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profileValue = policy.renderProfileValue(); + + assert.strictEqual(profileValue, '42'); + }); + + test('should render profile correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profile = policy.renderProfile(); + + assert.strictEqual(profile.length, 2); + assert.strictEqual(profile[0], 'TestNumberPolicy'); + assert.strictEqual(profile[1], '42'); + }); + + test('should render profile manifest value correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifestValue = policy.renderProfileManifestValue(); + + assert.strictEqual(manifestValue, 'pfm_default\n42\npfm_description\nTest number policy description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger'); + }); + + test('should render profile manifest value with translations', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + + const manifestValue = policy.renderProfileManifestValue(translations); + + assert.strictEqual(manifestValue, 'pfm_default\n42\npfm_description\nTranslated manifest description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger'); + }); + + test('should render profile manifest correctly', () => { + const policy = NumberPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifest = policy.renderProfileManifest(); + + assert.strictEqual(manifest, '\npfm_default\n42\npfm_description\nTest number policy description\npfm_name\nTestNumberPolicy\npfm_title\nTestNumberPolicy\npfm_type\ninteger\n'); + }); +}); diff --git a/build/lib/test/objectPolicy.test.js b/build/lib/test/objectPolicy.test.js new file mode 100644 index 00000000000..a34d71383d2 --- /dev/null +++ b/build/lib/test/objectPolicy.test.js @@ -0,0 +1,124 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const objectPolicy_js_1 = require("../policies/objectPolicy.js"); +const types_js_1 = require("../policies/types.js"); +suite('ObjectPolicy', () => { + const mockCategory = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + const mockPolicy = { + key: 'test.object.policy', + name: 'TestObjectPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'object', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' } + } + }; + test('should create ObjectPolicy from factory method', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + assert_1.default.strictEqual(policy.name, 'TestObjectPolicy'); + assert_1.default.strictEqual(policy.minimumVersion, '1.0'); + assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value); + assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.Object); + }); + test('should render ADMX elements correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admx = policy.renderADMX('TestKey'); + assert_1.default.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + test('should render ADML strings correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admlStrings = policy.renderADMLStrings(); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestObjectPolicy', + 'Test policy description' + ]); + }); + test('should render ADML strings with translations', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + const admlStrings = policy.renderADMLStrings(translations); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestObjectPolicy', + 'Translated description' + ]); + }); + test('should render ADML presentation correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const presentation = policy.renderADMLPresentation(); + assert_1.default.strictEqual(presentation, ''); + }); + test('should render JSON value correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const jsonValue = policy.renderJsonValue(); + assert_1.default.strictEqual(jsonValue, ''); + }); + test('should render profile value correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profileValue = policy.renderProfileValue(); + assert_1.default.strictEqual(profileValue, ''); + }); + test('should render profile correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profile = policy.renderProfile(); + assert_1.default.strictEqual(profile.length, 2); + assert_1.default.strictEqual(profile[0], 'TestObjectPolicy'); + assert_1.default.strictEqual(profile[1], ''); + }); + test('should render profile manifest value correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifestValue = policy.renderProfileManifestValue(); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest policy description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n'); + }); + test('should render profile manifest value with translations', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + const manifestValue = policy.renderProfileManifestValue(translations); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n'); + }); + test('should render profile manifest correctly', () => { + const policy = objectPolicy_js_1.ObjectPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifest = policy.renderProfileManifest(); + assert_1.default.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest policy description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n\n'); + }); +}); +//# sourceMappingURL=objectPolicy.test.js.map \ No newline at end of file diff --git a/build/lib/test/objectPolicy.test.ts b/build/lib/test/objectPolicy.test.ts new file mode 100644 index 00000000000..6012b8012da --- /dev/null +++ b/build/lib/test/objectPolicy.test.ts @@ -0,0 +1,166 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { ObjectPolicy } from '../policies/objectPolicy.js'; +import { LanguageTranslations, PolicyType } from '../policies/types.js'; +import { CategoryDto, PolicyDto } from '../policies/policyDto.js'; + +suite('ObjectPolicy', () => { + const mockCategory: CategoryDto = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + + const mockPolicy: PolicyDto = { + key: 'test.object.policy', + name: 'TestObjectPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'object', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' } + } + }; + + test('should create ObjectPolicy from factory method', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + assert.strictEqual(policy.name, 'TestObjectPolicy'); + assert.strictEqual(policy.minimumVersion, '1.0'); + assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert.strictEqual(policy.category.name.value, mockCategory.name.value); + assert.strictEqual(policy.type, PolicyType.Object); + }); + + test('should render ADMX elements correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admx = policy.renderADMX('TestKey'); + + assert.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + + test('should render ADML strings correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admlStrings = policy.renderADMLStrings(); + + assert.deepStrictEqual(admlStrings, [ + 'TestObjectPolicy', + 'Test policy description' + ]); + }); + + test('should render ADML strings with translations', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + + const admlStrings = policy.renderADMLStrings(translations); + + assert.deepStrictEqual(admlStrings, [ + 'TestObjectPolicy', + 'Translated description' + ]); + }); + + test('should render ADML presentation correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const presentation = policy.renderADMLPresentation(); + + assert.strictEqual(presentation, ''); + }); + + test('should render JSON value correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const jsonValue = policy.renderJsonValue(); + + assert.strictEqual(jsonValue, ''); + }); + + test('should render profile value correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profileValue = policy.renderProfileValue(); + + assert.strictEqual(profileValue, ''); + }); + + test('should render profile correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profile = policy.renderProfile(); + + assert.strictEqual(profile.length, 2); + assert.strictEqual(profile[0], 'TestObjectPolicy'); + assert.strictEqual(profile[1], ''); + }); + + test('should render profile manifest value correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifestValue = policy.renderProfileManifestValue(); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest policy description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n'); + }); + + test('should render profile manifest value with translations', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + + const manifestValue = policy.renderProfileManifestValue(translations); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n'); + }); + + test('should render profile manifest correctly', () => { + const policy = ObjectPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifest = policy.renderProfileManifest(); + + assert.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest policy description\npfm_name\nTestObjectPolicy\npfm_title\nTestObjectPolicy\npfm_type\nstring\n\n'); + }); +}); diff --git a/build/lib/test/policyConversion.test.js b/build/lib/test/policyConversion.test.js new file mode 100644 index 00000000000..6fc735f1127 --- /dev/null +++ b/build/lib/test/policyConversion.test.js @@ -0,0 +1,465 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const fs_1 = require("fs"); +const path_1 = __importDefault(require("path")); +const booleanPolicy_1 = require("../policies/booleanPolicy"); +const numberPolicy_1 = require("../policies/numberPolicy"); +const objectPolicy_1 = require("../policies/objectPolicy"); +const stringEnumPolicy_1 = require("../policies/stringEnumPolicy"); +const stringPolicy_1 = require("../policies/stringPolicy"); +const render_1 = require("../policies/render"); +const PolicyTypes = [ + booleanPolicy_1.BooleanPolicy, + numberPolicy_1.NumberPolicy, + stringEnumPolicy_1.StringEnumPolicy, + stringPolicy_1.StringPolicy, + objectPolicy_1.ObjectPolicy +]; +function parsePolicies(policyData) { + const categories = new Map(); + for (const category of policyData.categories) { + categories.set(category.key, category); + } + const policies = []; + for (const policy of policyData.policies) { + const category = categories.get(policy.category); + if (!category) { + throw new Error(`Unknown category: ${policy.category}`); + } + let result; + for (const policyType of PolicyTypes) { + if (result = policyType.from(category, policy)) { + break; + } + } + if (!result) { + throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`); + } + policies.push(result); + } + // Sort policies first by category name, then by policy name + policies.sort((a, b) => { + const categoryCompare = a.category.name.value.localeCompare(b.category.name.value); + if (categoryCompare !== 0) { + return categoryCompare; + } + return a.name.localeCompare(b.name); + }); + return policies; +} +/** + * This is a snapshot of the data taken on Oct. 20 2025 as part of the + * policy refactor effort. Let's make sure that nothing has regressed. + */ +const policies = { + categories: [ + { + key: 'Extensions', + name: { + key: 'extensionsConfigurationTitle', + value: 'Extensions' + } + }, + { + key: 'IntegratedTerminal', + name: { + key: 'terminalIntegratedConfigurationTitle', + value: 'Integrated Terminal' + } + }, + { + key: 'InteractiveSession', + name: { + key: 'interactiveSessionConfigurationTitle', + value: 'Chat' + } + }, + { + key: 'Telemetry', + name: { + key: 'telemetryConfigurationTitle', + value: 'Telemetry' + } + }, + { + key: 'Update', + name: { + key: 'updateConfigurationTitle', + value: 'Update' + } + } + ], + policies: [ + { + key: 'chat.mcp.gallery.serviceUrl', + name: 'McpGalleryServiceUrl', + category: 'InteractiveSession', + minimumVersion: '1.101', + localization: { + description: { + key: 'mcp.gallery.serviceUrl', + value: 'Configure the MCP Gallery service URL to connect to' + } + }, + type: 'string', + default: '' + }, + { + key: 'extensions.gallery.serviceUrl', + name: 'ExtensionGalleryServiceUrl', + category: 'Extensions', + minimumVersion: '1.99', + localization: { + description: { + key: 'extensions.gallery.serviceUrl', + value: 'Configure the Marketplace service URL to connect to' + } + }, + type: 'string', + default: '' + }, + { + key: 'extensions.allowed', + name: 'AllowedExtensions', + category: 'Extensions', + minimumVersion: '1.96', + localization: { + description: { + key: 'extensions.allowed.policy', + value: 'Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions' + } + }, + type: 'object', + default: '*' + }, + { + key: 'chat.tools.global.autoApprove', + name: 'ChatToolsAutoApprove', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'autoApprove2.description', + value: 'Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.\n\nThis feature disables critical security protections and makes it much easier for an attacker to compromise the machine.' + } + }, + type: 'boolean', + default: false + }, + { + key: 'chat.mcp.access', + name: 'ChatMCP', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.mcp.access', + value: 'Controls access to installed Model Context Protocol servers.' + }, + enumDescriptions: [ + { + key: 'chat.mcp.access.none', + value: 'No access to MCP servers.' + }, + { + key: 'chat.mcp.access.registry', + value: 'Allows access to MCP servers installed from the registry that VS Code is connected to.' + }, + { + key: 'chat.mcp.access.any', + value: 'Allow access to any installed MCP server.' + } + ] + }, + type: 'string', + default: 'all', + enum: [ + 'none', + 'registry', + 'all' + ] + }, + { + key: 'chat.extensionTools.enabled', + name: 'ChatAgentExtensionTools', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.extensionToolsEnabled', + value: 'Enable using tools contributed by third-party extensions.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.agent.enabled', + name: 'ChatAgentMode', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.agent.enabled.description', + value: 'Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.promptFiles', + name: 'ChatPromptFiles', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.promptFiles.policy', + value: 'Enables reusable prompt and instruction files in Chat sessions.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.tools.terminal.enableAutoApprove', + name: 'ChatToolsTerminalEnableAutoApprove', + category: 'IntegratedTerminal', + minimumVersion: '1.104', + localization: { + description: { + key: 'autoApproveMode.description', + value: 'Controls whether to allow auto approval in the run in terminal tool.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'update.mode', + name: 'UpdateMode', + category: 'Update', + minimumVersion: '1.67', + localization: { + description: { + key: 'updateMode', + value: 'Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.' + }, + enumDescriptions: [ + { + key: 'none', + value: 'Disable updates.' + }, + { + key: 'manual', + value: 'Disable automatic background update checks. Updates will be available if you manually check for updates.' + }, + { + key: 'start', + value: 'Check for updates only on startup. Disable automatic background update checks.' + }, + { + key: 'default', + value: 'Enable automatic update checks. Code will check for updates automatically and periodically.' + } + ] + }, + type: 'string', + default: 'default', + enum: [ + 'none', + 'manual', + 'start', + 'default' + ] + }, + { + key: 'telemetry.telemetryLevel', + name: 'TelemetryLevel', + category: 'Telemetry', + minimumVersion: '1.99', + localization: { + description: { + key: 'telemetry.telemetryLevel.policyDescription', + value: 'Controls the level of telemetry.' + }, + enumDescriptions: [ + { + key: 'telemetry.telemetryLevel.default', + value: 'Sends usage data, errors, and crash reports.' + }, + { + key: 'telemetry.telemetryLevel.error', + value: 'Sends general error telemetry and crash reports.' + }, + { + key: 'telemetry.telemetryLevel.crash', + value: 'Sends OS level crash reports.' + }, + { + key: 'telemetry.telemetryLevel.off', + value: 'Disables all product telemetry.' + } + ] + }, + type: 'string', + default: 'all', + enum: [ + 'all', + 'error', + 'crash', + 'off' + ] + }, + { + key: 'telemetry.feedback.enabled', + name: 'EnableFeedback', + category: 'Telemetry', + minimumVersion: '1.99', + localization: { + description: { + key: 'telemetry.feedback.enabled', + value: 'Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.' + } + }, + type: 'boolean', + default: true + } + ] +}; +const mockProduct = { + nameLong: 'Code - OSS', + darwinBundleIdentifier: 'com.visualstudio.code.oss', + darwinProfilePayloadUUID: 'CF808BE7-53F3-46C6-A7E2-7EDB98A5E959', + darwinProfileUUID: '47827DD9-4734-49A0-AF80-7E19B11495CC', + win32RegValueName: 'CodeOSS' +}; +const frenchTranslations = [ + { + languageId: 'fr-fr', + languageTranslations: { + '': { + 'interactiveSessionConfigurationTitle': 'Session interactive', + 'extensionsConfigurationTitle': 'Extensions', + 'terminalIntegratedConfigurationTitle': 'Terminal intégré', + 'telemetryConfigurationTitle': 'Télémétrie', + 'updateConfigurationTitle': 'Mettre à jour', + 'chat.extensionToolsEnabled': 'Autorisez l’utilisation d’outils fournis par des extensions tierces.', + 'chat.agent.enabled.description': 'Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.', + 'chat.mcp.access': 'Contrôle l’accès aux serveurs de protocole de contexte du modèle.', + 'chat.mcp.access.none': 'Aucun accès aux serveurs MCP.', + 'chat.mcp.access.registry': `Autorise l’accès aux serveurs MCP installés à partir du registre auquel VS Code est connecté.`, + 'chat.mcp.access.any': 'Autorisez l’accès à tout serveur MCP installé.', + 'chat.promptFiles.policy': 'Active les fichiers d’instruction et de requête réutilisables dans les sessions Conversation.', + 'autoApprove2.description': `L’approbation automatique globale, également appelée « mode YOLO », désactive complètement l’approbation manuelle pour tous les outils dans tous les espaces de travail, permettant à l’agent d’agir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises. + +Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.`, + 'mcp.gallery.serviceUrl': 'Configurer l’URL du service de la galerie MCP à laquelle se connecter', + 'extensions.allowed.policy': 'Spécifiez une liste d’extensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant l’utilisation d’extensions non autorisées. Plus d’informations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions', + 'extensions.gallery.serviceUrl': 'Configurer l’URL du service Place de marché à laquelle se connecter', + 'autoApproveMode.description': 'Contrôle s’il faut autoriser l’approbation automatique lors de l’exécution dans l’outil terminal.', + 'telemetry.feedback.enabled': 'Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.', + 'telemetry.telemetryLevel.policyDescription': 'Contrôle le niveau de télémétrie.', + 'telemetry.telemetryLevel.default': `Envoie les données d'utilisation, les erreurs et les rapports d'erreur.`, + 'telemetry.telemetryLevel.error': `Envoie la télémétrie d'erreur générale et les rapports de plantage.`, + 'telemetry.telemetryLevel.crash': `Envoie des rapports de plantage au niveau du système d'exploitation.`, + 'telemetry.telemetryLevel.off': 'Désactive toutes les données de télémétrie du produit.', + 'updateMode': `Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.`, + 'none': 'Aucun', + 'manual': 'Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement.', + 'start': 'Démarrer', + 'default': 'Système' + } + } + } +]; +suite('Policy E2E conversion', () => { + test('should render macOS policy profile from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, []); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'com.visualstudio.code.oss.mobileconfig'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Compare the rendered profile with the fixture + assert_1.default.strictEqual(result.profile, expectedContent, 'macOS policy profile should match the fixture'); + }); + test('should render macOS manifest from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, []); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'en-us', 'com.visualstudio.code.oss.plist'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Find the en-us manifest + const enUsManifest = result.manifests.find(m => m.languageId === 'en-us'); + assert_1.default.ok(enUsManifest, 'en-us manifest should exist'); + // Compare the rendered manifest with the fixture, ignoring the timestamp + // The pfm_last_modified field contains a timestamp that will differ each time + const normalizeTimestamp = (content) => content.replace(/.*?<\/date>/, 'TIMESTAMP'); + assert_1.default.strictEqual(normalizeTimestamp(enUsManifest.contents), normalizeTimestamp(expectedContent), 'macOS manifest should match the fixture (ignoring timestamp)'); + }); + test('should render Windows ADMX from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, []); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'CodeOSS.admx'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Compare the rendered ADMX with the fixture + assert_1.default.strictEqual(result.admx, expectedContent, 'Windows ADMX should match the fixture'); + }); + test('should render Windows ADML from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, []); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'en-us', 'CodeOSS.adml'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Find the en-us ADML + const enUsAdml = result.adml.find(a => a.languageId === 'en-us'); + assert_1.default.ok(enUsAdml, 'en-us ADML should exist'); + // Compare the rendered ADML with the fixture + assert_1.default.strictEqual(enUsAdml.contents, expectedContent, 'Windows ADML should match the fixture'); + }); + test('should render macOS manifest with fr-fr locale', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderMacOSPolicy)(mockProduct, parsedPolicies, frenchTranslations); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'darwin', 'fr-fr', 'com.visualstudio.code.oss.plist'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Find the fr-fr manifest + const frFrManifest = result.manifests.find(m => m.languageId === 'fr-fr'); + assert_1.default.ok(frFrManifest, 'fr-fr manifest should exist'); + // Compare the rendered manifest with the fixture, ignoring the timestamp + const normalizeTimestamp = (content) => content.replace(/.*?<\/date>/, 'TIMESTAMP'); + assert_1.default.strictEqual(normalizeTimestamp(frFrManifest.contents), normalizeTimestamp(expectedContent), 'macOS fr-fr manifest should match the fixture (ignoring timestamp)'); + }); + test('should render Windows ADML with fr-fr locale', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderGP)(mockProduct, parsedPolicies, frenchTranslations); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'win32', 'fr-fr', 'CodeOSS.adml'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + // Find the fr-fr ADML + const frFrAdml = result.adml.find(a => a.languageId === 'fr-fr'); + assert_1.default.ok(frFrAdml, 'fr-fr ADML should exist'); + // Compare the rendered ADML with the fixture + assert_1.default.strictEqual(frFrAdml.contents, expectedContent, 'Windows fr-fr ADML should match the fixture'); + }); + test('should render Linux policy JSON from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = (0, render_1.renderJsonPolicies)(parsedPolicies); + // Load the expected fixture file + const fixturePath = path_1.default.join(__dirname, 'fixtures', 'policies', 'linux', 'policy.json'); + const expectedContent = await fs_1.promises.readFile(fixturePath, 'utf-8'); + const expectedJson = JSON.parse(expectedContent); + // Compare the rendered JSON with the fixture + assert_1.default.deepStrictEqual(result, expectedJson, 'Linux policy JSON should match the fixture'); + }); +}); +//# sourceMappingURL=policyConversion.test.js.map \ No newline at end of file diff --git a/build/lib/test/policyConversion.test.ts b/build/lib/test/policyConversion.test.ts new file mode 100644 index 00000000000..0610b0cd980 --- /dev/null +++ b/build/lib/test/policyConversion.test.ts @@ -0,0 +1,508 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { promises as fs } from 'fs'; +import path from 'path'; +import { ExportedPolicyDataDto, CategoryDto } from '../policies/policyDto'; +import { BooleanPolicy } from '../policies/booleanPolicy'; +import { NumberPolicy } from '../policies/numberPolicy'; +import { ObjectPolicy } from '../policies/objectPolicy'; +import { StringEnumPolicy } from '../policies/stringEnumPolicy'; +import { StringPolicy } from '../policies/stringPolicy'; +import { Policy, ProductJson } from '../policies/types'; +import { renderGP, renderMacOSPolicy, renderJsonPolicies } from '../policies/render'; + +const PolicyTypes = [ + BooleanPolicy, + NumberPolicy, + StringEnumPolicy, + StringPolicy, + ObjectPolicy +]; + +function parsePolicies(policyData: ExportedPolicyDataDto): Policy[] { + const categories = new Map(); + for (const category of policyData.categories) { + categories.set(category.key, category); + } + + const policies: Policy[] = []; + for (const policy of policyData.policies) { + const category = categories.get(policy.category); + if (!category) { + throw new Error(`Unknown category: ${policy.category}`); + } + + let result: Policy | undefined; + for (const policyType of PolicyTypes) { + if (result = policyType.from(category, policy)) { + break; + } + } + + if (!result) { + throw new Error(`Unsupported policy type: ${policy.type} for policy ${policy.name}`); + } + + policies.push(result); + } + + // Sort policies first by category name, then by policy name + policies.sort((a, b) => { + const categoryCompare = a.category.name.value.localeCompare(b.category.name.value); + if (categoryCompare !== 0) { + return categoryCompare; + } + return a.name.localeCompare(b.name); + }); + + return policies; +} + +/** + * This is a snapshot of the data taken on Oct. 20 2025 as part of the + * policy refactor effort. Let's make sure that nothing has regressed. + */ +const policies: ExportedPolicyDataDto = { + categories: [ + { + key: 'Extensions', + name: { + key: 'extensionsConfigurationTitle', + value: 'Extensions' + } + }, + { + key: 'IntegratedTerminal', + name: { + key: 'terminalIntegratedConfigurationTitle', + value: 'Integrated Terminal' + } + }, + { + key: 'InteractiveSession', + name: { + key: 'interactiveSessionConfigurationTitle', + value: 'Chat' + } + }, + { + key: 'Telemetry', + name: { + key: 'telemetryConfigurationTitle', + value: 'Telemetry' + } + }, + { + key: 'Update', + name: { + key: 'updateConfigurationTitle', + value: 'Update' + } + } + ], + policies: [ + { + key: 'chat.mcp.gallery.serviceUrl', + name: 'McpGalleryServiceUrl', + category: 'InteractiveSession', + minimumVersion: '1.101', + localization: { + description: { + key: 'mcp.gallery.serviceUrl', + value: 'Configure the MCP Gallery service URL to connect to' + } + }, + type: 'string', + default: '' + }, + { + key: 'extensions.gallery.serviceUrl', + name: 'ExtensionGalleryServiceUrl', + category: 'Extensions', + minimumVersion: '1.99', + localization: { + description: { + key: 'extensions.gallery.serviceUrl', + value: 'Configure the Marketplace service URL to connect to' + } + }, + type: 'string', + default: '' + }, + { + key: 'extensions.allowed', + name: 'AllowedExtensions', + category: 'Extensions', + minimumVersion: '1.96', + localization: { + description: { + key: 'extensions.allowed.policy', + value: 'Specify a list of extensions that are allowed to use. This helps maintain a secure and consistent development environment by restricting the use of unauthorized extensions. More information: https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions' + } + }, + type: 'object', + default: '*' + }, + { + key: 'chat.tools.global.autoApprove', + name: 'ChatToolsAutoApprove', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'autoApprove2.description', + value: 'Global auto approve also known as "YOLO mode" disables manual approval completely for all tools in all workspaces, allowing the agent to act fully autonomously. This is extremely dangerous and is *never* recommended, even containerized environments like Codespaces and Dev Containers have user keys forwarded into the container that could be compromised.\n\nThis feature disables critical security protections and makes it much easier for an attacker to compromise the machine.' + } + }, + type: 'boolean', + default: false + }, + { + key: 'chat.mcp.access', + name: 'ChatMCP', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.mcp.access', + value: 'Controls access to installed Model Context Protocol servers.' + }, + enumDescriptions: [ + { + key: 'chat.mcp.access.none', + value: 'No access to MCP servers.' + }, + { + key: 'chat.mcp.access.registry', + value: 'Allows access to MCP servers installed from the registry that VS Code is connected to.' + }, + { + key: 'chat.mcp.access.any', + value: 'Allow access to any installed MCP server.' + } + ] + }, + type: 'string', + default: 'all', + enum: [ + 'none', + 'registry', + 'all' + ] + }, + { + key: 'chat.extensionTools.enabled', + name: 'ChatAgentExtensionTools', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.extensionToolsEnabled', + value: 'Enable using tools contributed by third-party extensions.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.agent.enabled', + name: 'ChatAgentMode', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.agent.enabled.description', + value: 'Enable agent mode for chat. When this is enabled, agent mode can be activated via the dropdown in the view.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.promptFiles', + name: 'ChatPromptFiles', + category: 'InteractiveSession', + minimumVersion: '1.99', + localization: { + description: { + key: 'chat.promptFiles.policy', + value: 'Enables reusable prompt and instruction files in Chat sessions.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'chat.tools.terminal.enableAutoApprove', + name: 'ChatToolsTerminalEnableAutoApprove', + category: 'IntegratedTerminal', + minimumVersion: '1.104', + localization: { + description: { + key: 'autoApproveMode.description', + value: 'Controls whether to allow auto approval in the run in terminal tool.' + } + }, + type: 'boolean', + default: true + }, + { + key: 'update.mode', + name: 'UpdateMode', + category: 'Update', + minimumVersion: '1.67', + localization: { + description: { + key: 'updateMode', + value: 'Configure whether you receive automatic updates. Requires a restart after change. The updates are fetched from a Microsoft online service.' + }, + enumDescriptions: [ + { + key: 'none', + value: 'Disable updates.' + }, + { + key: 'manual', + value: 'Disable automatic background update checks. Updates will be available if you manually check for updates.' + }, + { + key: 'start', + value: 'Check for updates only on startup. Disable automatic background update checks.' + }, + { + key: 'default', + value: 'Enable automatic update checks. Code will check for updates automatically and periodically.' + } + ] + }, + type: 'string', + default: 'default', + enum: [ + 'none', + 'manual', + 'start', + 'default' + ] + }, + { + key: 'telemetry.telemetryLevel', + name: 'TelemetryLevel', + category: 'Telemetry', + minimumVersion: '1.99', + localization: { + description: { + key: 'telemetry.telemetryLevel.policyDescription', + value: 'Controls the level of telemetry.' + }, + enumDescriptions: [ + { + key: 'telemetry.telemetryLevel.default', + value: 'Sends usage data, errors, and crash reports.' + }, + { + key: 'telemetry.telemetryLevel.error', + value: 'Sends general error telemetry and crash reports.' + }, + { + key: 'telemetry.telemetryLevel.crash', + value: 'Sends OS level crash reports.' + }, + { + key: 'telemetry.telemetryLevel.off', + value: 'Disables all product telemetry.' + } + ] + }, + type: 'string', + default: 'all', + enum: [ + 'all', + 'error', + 'crash', + 'off' + ] + }, + { + key: 'telemetry.feedback.enabled', + name: 'EnableFeedback', + category: 'Telemetry', + minimumVersion: '1.99', + localization: { + description: { + key: 'telemetry.feedback.enabled', + value: 'Enable feedback mechanisms such as the issue reporter, surveys, and other feedback options.' + } + }, + type: 'boolean', + default: true + } + ] +}; + +const mockProduct: ProductJson = { + nameLong: 'Code - OSS', + darwinBundleIdentifier: 'com.visualstudio.code.oss', + darwinProfilePayloadUUID: 'CF808BE7-53F3-46C6-A7E2-7EDB98A5E959', + darwinProfileUUID: '47827DD9-4734-49A0-AF80-7E19B11495CC', + win32RegValueName: 'CodeOSS' +}; + +const frenchTranslations = [ + { + languageId: 'fr-fr', + languageTranslations: { + '': { + 'interactiveSessionConfigurationTitle': 'Session interactive', + 'extensionsConfigurationTitle': 'Extensions', + 'terminalIntegratedConfigurationTitle': 'Terminal intégré', + 'telemetryConfigurationTitle': 'Télémétrie', + 'updateConfigurationTitle': 'Mettre à jour', + 'chat.extensionToolsEnabled': 'Autorisez l’utilisation d’outils fournis par des extensions tierces.', + 'chat.agent.enabled.description': 'Activez le mode Assistant pour la conversation. Lorsque cette option est activée, le mode Assistant peut être activé via la liste déroulante de la vue.', + 'chat.mcp.access': 'Contrôle l’accès aux serveurs de protocole de contexte du modèle.', + 'chat.mcp.access.none': 'Aucun accès aux serveurs MCP.', + 'chat.mcp.access.registry': `Autorise l’accès aux serveurs MCP installés à partir du registre auquel VS Code est connecté.`, + 'chat.mcp.access.any': 'Autorisez l’accès à tout serveur MCP installé.', + 'chat.promptFiles.policy': 'Active les fichiers d’instruction et de requête réutilisables dans les sessions Conversation.', + 'autoApprove2.description': `L’approbation automatique globale, également appelée « mode YOLO », désactive complètement l’approbation manuelle pour tous les outils dans tous les espaces de travail, permettant à l’agent d’agir de manière totalement autonome. Ceci est extrêmement dangereux et est *jamais* recommandé, même dans des environnements conteneurisés comme [Codespaces](https://github.com/features/codespaces) et [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers), où des clés utilisateur sont transférées dans le conteneur et pourraient être compromises. + +Cette fonctionnalité désactive [les protections de sécurité critiques](https://code.visualstudio.com/docs/copilot/security) et facilite considérablement la compromission de la machine par un attaquant.`, + 'mcp.gallery.serviceUrl': 'Configurer l’URL du service de la galerie MCP à laquelle se connecter', + 'extensions.allowed.policy': 'Spécifiez une liste d’extensions autorisées. Cela permet de maintenir un environnement de développement sécurisé et cohérent en limitant l’utilisation d’extensions non autorisées. Plus d’informations : https://code.visualstudio.com/docs/setup/enterprise#_configure-allowed-extensions', + 'extensions.gallery.serviceUrl': 'Configurer l’URL du service Place de marché à laquelle se connecter', + 'autoApproveMode.description': 'Contrôle s’il faut autoriser l’approbation automatique lors de l’exécution dans l’outil terminal.', + 'telemetry.feedback.enabled': 'Activez les mécanismes de commentaires tels que le système de rapport de problèmes, les sondages et autres options de commentaires.', + 'telemetry.telemetryLevel.policyDescription': 'Contrôle le niveau de télémétrie.', + 'telemetry.telemetryLevel.default': `Envoie les données d'utilisation, les erreurs et les rapports d'erreur.`, + 'telemetry.telemetryLevel.error': `Envoie la télémétrie d'erreur générale et les rapports de plantage.`, + 'telemetry.telemetryLevel.crash': `Envoie des rapports de plantage au niveau du système d'exploitation.`, + 'telemetry.telemetryLevel.off': 'Désactive toutes les données de télémétrie du produit.', + 'updateMode': `Choisissez si vous voulez recevoir des mises à jour automatiques. Nécessite un redémarrage après le changement. Les mises à jour sont récupérées auprès d'un service en ligne Microsoft.`, + 'none': 'Aucun', + 'manual': 'Désactivez la recherche de mises à jour automatique en arrière-plan. Les mises à jour sont disponibles si vous les rechercher manuellement.', + 'start': 'Démarrer', + 'default': 'Système' + } + } + } +]; + +suite('Policy E2E conversion', () => { + + test('should render macOS policy profile from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderMacOSPolicy(mockProduct, parsedPolicies, []); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'com.visualstudio.code.oss.mobileconfig'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Compare the rendered profile with the fixture + assert.strictEqual(result.profile, expectedContent, 'macOS policy profile should match the fixture'); + }); + + test('should render macOS manifest from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderMacOSPolicy(mockProduct, parsedPolicies, []); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'en-us', 'com.visualstudio.code.oss.plist'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Find the en-us manifest + const enUsManifest = result.manifests.find(m => m.languageId === 'en-us'); + assert.ok(enUsManifest, 'en-us manifest should exist'); + + // Compare the rendered manifest with the fixture, ignoring the timestamp + // The pfm_last_modified field contains a timestamp that will differ each time + const normalizeTimestamp = (content: string) => content.replace(/.*?<\/date>/, 'TIMESTAMP'); + assert.strictEqual( + normalizeTimestamp(enUsManifest.contents), + normalizeTimestamp(expectedContent), + 'macOS manifest should match the fixture (ignoring timestamp)' + ); + }); + + test('should render Windows ADMX from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderGP(mockProduct, parsedPolicies, []); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'CodeOSS.admx'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Compare the rendered ADMX with the fixture + assert.strictEqual(result.admx, expectedContent, 'Windows ADMX should match the fixture'); + }); + + test('should render Windows ADML from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderGP(mockProduct, parsedPolicies, []); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'en-us', 'CodeOSS.adml'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Find the en-us ADML + const enUsAdml = result.adml.find(a => a.languageId === 'en-us'); + assert.ok(enUsAdml, 'en-us ADML should exist'); + + // Compare the rendered ADML with the fixture + assert.strictEqual(enUsAdml.contents, expectedContent, 'Windows ADML should match the fixture'); + }); + + test('should render macOS manifest with fr-fr locale', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderMacOSPolicy(mockProduct, parsedPolicies, frenchTranslations); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'darwin', 'fr-fr', 'com.visualstudio.code.oss.plist'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Find the fr-fr manifest + const frFrManifest = result.manifests.find(m => m.languageId === 'fr-fr'); + assert.ok(frFrManifest, 'fr-fr manifest should exist'); + + // Compare the rendered manifest with the fixture, ignoring the timestamp + const normalizeTimestamp = (content: string) => content.replace(/.*?<\/date>/, 'TIMESTAMP'); + assert.strictEqual( + normalizeTimestamp(frFrManifest.contents), + normalizeTimestamp(expectedContent), + 'macOS fr-fr manifest should match the fixture (ignoring timestamp)' + ); + }); + + test('should render Windows ADML with fr-fr locale', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderGP(mockProduct, parsedPolicies, frenchTranslations); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'win32', 'fr-fr', 'CodeOSS.adml'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + + // Find the fr-fr ADML + const frFrAdml = result.adml.find(a => a.languageId === 'fr-fr'); + assert.ok(frFrAdml, 'fr-fr ADML should exist'); + + // Compare the rendered ADML with the fixture + assert.strictEqual(frFrAdml.contents, expectedContent, 'Windows fr-fr ADML should match the fixture'); + }); + + test('should render Linux policy JSON from policies list', async () => { + const parsedPolicies = parsePolicies(policies); + const result = renderJsonPolicies(parsedPolicies); + + // Load the expected fixture file + const fixturePath = path.join(__dirname, 'fixtures', 'policies', 'linux', 'policy.json'); + const expectedContent = await fs.readFile(fixturePath, 'utf-8'); + const expectedJson = JSON.parse(expectedContent); + + // Compare the rendered JSON with the fixture + assert.deepStrictEqual(result, expectedJson, 'Linux policy JSON should match the fixture'); + }); + +}); diff --git a/build/lib/test/render.test.js b/build/lib/test/render.test.js new file mode 100644 index 00000000000..87c7fa14621 --- /dev/null +++ b/build/lib/test/render.test.js @@ -0,0 +1,855 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const render_js_1 = require("../policies/render.js"); +const types_js_1 = require("../policies/types.js"); +suite('Render Functions', () => { + suite('renderADMLString', () => { + test('should render ADML string without translations', () => { + const nlsString = { + value: 'Test description', + nlsKey: 'test.description' + }; + const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString); + assert_1.default.strictEqual(result, 'Test description'); + }); + test('should replace dots with underscores in nls key', () => { + const nlsString = { + value: 'Test value', + nlsKey: 'my.test.nls.key' + }; + const result = (0, render_js_1.renderADMLString)('Prefix', 'testModule', nlsString); + assert_1.default.ok(result.includes('id="Prefix_my_test_nls_key"')); + }); + test('should use translation when available', () => { + const nlsString = { + value: 'Original value', + nlsKey: 'test.key' + }; + const translations = { + 'testModule': { + 'test.key': 'Translated value' + } + }; + const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString, translations); + assert_1.default.ok(result.includes('>Translated value')); + }); + test('should fallback to original value when translation not found', () => { + const nlsString = { + value: 'Original value', + nlsKey: 'test.key' + }; + const translations = { + 'testModule': { + 'other.key': 'Other translation' + } + }; + const result = (0, render_js_1.renderADMLString)('TestPrefix', 'testModule', nlsString, translations); + assert_1.default.ok(result.includes('>Original value')); + }); + }); + suite('renderProfileString', () => { + test('should render profile string without translations', () => { + const nlsString = { + value: 'Profile description', + nlsKey: 'profile.description' + }; + const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString); + assert_1.default.strictEqual(result, 'Profile description'); + }); + test('should use translation when available', () => { + const nlsString = { + value: 'Original profile value', + nlsKey: 'profile.key' + }; + const translations = { + 'testModule': { + 'profile.key': 'Translated profile value' + } + }; + const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString, translations); + assert_1.default.strictEqual(result, 'Translated profile value'); + }); + test('should fallback to original value when translation not found', () => { + const nlsString = { + value: 'Original profile value', + nlsKey: 'profile.key' + }; + const translations = { + 'testModule': { + 'other.key': 'Other translation' + } + }; + const result = (0, render_js_1.renderProfileString)('ProfilePrefix', 'testModule', nlsString, translations); + assert_1.default.strictEqual(result, 'Original profile value'); + }); + }); + suite('renderADMX', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + const mockPolicy = { + name: 'TestPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy'], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy', ''], + renderProfileManifest: () => 'pfm_nameTestPolicy', + renderJsonValue: () => null + }; + test('should render ADMX with correct XML structure', () => { + const result = (0, render_js_1.renderADMX)('VSCode', ['1.85'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + }); + test('should include policy namespaces with regKey', () => { + const result = (0, render_js_1.renderADMX)('TestApp', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes(' { + const result = (0, render_js_1.renderADMX)('VSCode', ['1.85.0', '1.90.1'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('Supported_1_85_0')); + assert_1.default.ok(result.includes('Supported_1_90_1')); + assert_1.default.ok(!result.includes('Supported_1.85.0')); + }); + test('should include categories in correct structure', () => { + const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + }); + test('should include policies section', () => { + const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('TestPolicy')); + assert_1.default.ok(result.includes('')); + }); + test('should handle multiple versions', () => { + const result = (0, render_js_1.renderADMX)('VSCode', ['1.0', '1.5', '2.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('Supported_1_0')); + assert_1.default.ok(result.includes('Supported_1_5')); + assert_1.default.ok(result.includes('Supported_2_0')); + }); + test('should handle multiple categories', () => { + const category1 = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } }; + const category2 = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } }; + const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [category1, category2], [mockPolicy]); + assert_1.default.ok(result.includes('Category_cat1')); + assert_1.default.ok(result.includes('Category_cat2')); + }); + test('should handle multiple policies', () => { + const policy2 = { + name: 'TestPolicy2', + type: types_js_1.PolicyType.String, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy 2'], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy2', ''], + renderProfileManifest: () => 'pfm_nameTestPolicy2', + renderJsonValue: () => null + }; + const result = (0, render_js_1.renderADMX)('VSCode', ['1.0'], [mockCategory], [mockPolicy, policy2]); + assert_1.default.ok(result.includes('TestPolicy')); + assert_1.default.ok(result.includes('TestPolicy2')); + }); + }); + suite('renderADML', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + const mockPolicy = { + name: 'TestPolicy', + type: types_js_1.PolicyType.String, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: () => [], + renderADMLStrings: (translations) => [ + `Test Policy ${translations?.['testModule']?.['test.policy'] || 'Default'}` + ], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + test('should render ADML with correct XML structure', () => { + const result = (0, render_js_1.renderADML)('VS Code', ['1.85'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + }); + test('should include application name', () => { + const result = (0, render_js_1.renderADML)('My Application', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('My Application')); + }); + test('should include supported versions with escaped greater-than', () => { + const result = (0, render_js_1.renderADML)('VS Code', ['1.85', '1.90'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('VS Code >= 1.85')); + assert_1.default.ok(result.includes('VS Code >= 1.90')); + }); + test('should include category strings', () => { + const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('Category_test_category')); + }); + test('should include policy strings', () => { + const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('TestPolicy')); + assert_1.default.ok(result.includes('Test Policy Default')); + }); + test('should include policy presentations', () => { + const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + }); + test('should pass translations to policy strings', () => { + const translations = { + 'testModule': { + 'test.policy': 'Translated' + } + }; + const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [mockCategory], [mockPolicy], translations); + assert_1.default.ok(result.includes('Test Policy Translated')); + }); + test('should handle multiple categories', () => { + const category1 = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } }; + const category2 = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } }; + const result = (0, render_js_1.renderADML)('VS Code', ['1.0'], [category1, category2], [mockPolicy]); + assert_1.default.ok(result.includes('Category_cat1')); + assert_1.default.ok(result.includes('Category_cat2')); + }); + }); + suite('renderProfileManifest', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + const mockPolicy = { + name: 'TestPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: (translations) => ` +pfm_name +TestPolicy +pfm_description +${translations?.['testModule']?.['test.desc'] || 'Default Desc'} +`, + renderJsonValue: () => null + }; + test('should render profile manifest with correct XML structure', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + assert_1.default.ok(result.includes('')); + }); + test('should include app name', () => { + const result = (0, render_js_1.renderProfileManifest)('My App', 'com.example.myapp', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('My App Managed Settings')); + assert_1.default.ok(result.includes('My App')); + }); + test('should include bundle identifier', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('com.microsoft.vscode')); + }); + test('should include required payload fields', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('PayloadDescription')); + assert_1.default.ok(result.includes('PayloadDisplayName')); + assert_1.default.ok(result.includes('PayloadIdentifier')); + assert_1.default.ok(result.includes('PayloadType')); + assert_1.default.ok(result.includes('PayloadUUID')); + assert_1.default.ok(result.includes('PayloadVersion')); + assert_1.default.ok(result.includes('PayloadOrganization')); + }); + test('should include policy manifests in subkeys', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_subkeys')); + assert_1.default.ok(result.includes('TestPolicy')); + assert_1.default.ok(result.includes('Default Desc')); + }); + test('should pass translations to policy manifests', () => { + const translations = { + 'testModule': { + 'test.desc': 'Translated Description' + } + }; + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy], translations); + assert_1.default.ok(result.includes('Translated Description')); + }); + test('should include VS Code specific URLs', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('https://code.visualstudio.com/')); + assert_1.default.ok(result.includes('https://code.visualstudio.com/docs/setup/enterprise')); + }); + test('should include last modified date', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_last_modified')); + assert_1.default.ok(result.includes('')); + }); + test('should mark manifest as unique', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_unique')); + assert_1.default.ok(result.includes('')); + }); + test('should handle multiple policies', () => { + const policy2 = { + ...mockPolicy, + name: 'TestPolicy2', + renderProfileManifest: () => ` +pfm_name +TestPolicy2 +` + }; + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy, policy2]); + assert_1.default.ok(result.includes('TestPolicy')); + assert_1.default.ok(result.includes('TestPolicy2')); + }); + test('should set format version to 1', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_format_version')); + assert_1.default.ok(result.includes('1')); + }); + test('should set interaction to combined', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_interaction')); + assert_1.default.ok(result.includes('combined')); + }); + test('should set platform to macOS', () => { + const result = (0, render_js_1.renderProfileManifest)('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + assert_1.default.ok(result.includes('pfm_platforms')); + assert_1.default.ok(result.includes('macOS')); + }); + }); + suite('renderMacOSPolicy', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + const mockPolicy = { + name: 'TestPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy', ''], + renderProfileManifest: (translations) => ` +pfm_name +TestPolicy +pfm_description +${translations?.['testModule']?.['test.desc'] || 'Default Desc'} +`, + renderJsonValue: () => null + }; + test('should render complete macOS policy profile', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []); + const expected = ` + + + + PayloadContent + + + PayloadDisplayName + VS Code + PayloadIdentifier + com.microsoft.vscode.uuid + PayloadType + com.microsoft.vscode + PayloadUUID + uuid + PayloadVersion + 1 + TestPolicy + + + + PayloadDescription + This profile manages VS Code. For more information see https://code.visualstudio.com/docs/setup/enterprise + PayloadDisplayName + VS Code + PayloadIdentifier + com.microsoft.vscode + PayloadOrganization + Microsoft + PayloadType + Configuration + PayloadUUID + payload-uuid + PayloadVersion + 1 + TargetDeviceType + 5 + +`; + assert_1.default.strictEqual(result.profile, expected); + }); + test('should include en-us manifest by default', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []); + assert_1.default.strictEqual(result.manifests.length, 1); + assert_1.default.strictEqual(result.manifests[0].languageId, 'en-us'); + assert_1.default.ok(result.manifests[0].contents.includes('VS Code Managed Settings')); + }); + test('should include translations', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const translations = [ + { languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.desc': 'Description Française' } } }, + { languageId: 'de-de', languageTranslations: { 'testModule': { 'test.desc': 'Deutsche Beschreibung' } } } + ]; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], translations); + assert_1.default.strictEqual(result.manifests.length, 3); // en-us + 2 translations + assert_1.default.strictEqual(result.manifests[0].languageId, 'en-us'); + assert_1.default.strictEqual(result.manifests[1].languageId, 'fr-fr'); + assert_1.default.strictEqual(result.manifests[2].languageId, 'de-de'); + assert_1.default.ok(result.manifests[1].contents.includes('Description Française')); + assert_1.default.ok(result.manifests[2].contents.includes('Deutsche Beschreibung')); + }); + test('should handle multiple policies with correct indentation', () => { + const policy2 = { + ...mockPolicy, + name: 'TestPolicy2', + renderProfile: () => ['TestPolicy2', 'test value'] + }; + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy, policy2], []); + assert_1.default.ok(result.profile.includes('TestPolicy')); + assert_1.default.ok(result.profile.includes('')); + assert_1.default.ok(result.profile.includes('TestPolicy2')); + assert_1.default.ok(result.profile.includes('test value')); + }); + test('should use provided UUIDs in profile', () => { + const product = { + nameLong: 'My App', + darwinBundleIdentifier: 'com.example.app', + darwinProfilePayloadUUID: 'custom-payload-uuid', + darwinProfileUUID: 'custom-uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []); + assert_1.default.ok(result.profile.includes('custom-payload-uuid')); + assert_1.default.ok(result.profile.includes('custom-uuid')); + assert_1.default.ok(result.profile.includes('com.example.app.custom-uuid')); + }); + test('should include enterprise documentation link', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []); + assert_1.default.ok(result.profile.includes('https://code.visualstudio.com/docs/setup/enterprise')); + }); + test('should set TargetDeviceType to 5', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderMacOSPolicy)(product, [mockPolicy], []); + assert_1.default.ok(result.profile.includes('TargetDeviceType')); + assert_1.default.ok(result.profile.includes('5')); + }); + }); + suite('renderGP', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + const mockPolicy = { + name: 'TestPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey) => [ + ``, + ` `, + `` + ], + renderADMLStrings: (translations) => [ + `${translations?.['testModule']?.['test.policy'] || 'Test Policy'}` + ], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + test('should render complete GP with ADMX and ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.admx); + assert_1.default.ok(result.adml); + assert_1.default.ok(Array.isArray(result.adml)); + }); + test('should include regKey in ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'CustomRegKey' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.admx.includes('CustomRegKey')); + assert_1.default.ok(result.admx.includes('Software\\Policies\\Microsoft\\CustomRegKey')); + }); + test('should include en-us ADML by default', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.strictEqual(result.adml.length, 1); + assert_1.default.strictEqual(result.adml[0].languageId, 'en-us'); + assert_1.default.ok(result.adml[0].contents.includes('VS Code')); + }); + test('should include translations in ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const translations = [ + { languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.policy': 'Politique de test' } } }, + { languageId: 'de-de', languageTranslations: { 'testModule': { 'test.policy': 'Testrichtlinie' } } } + ]; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], translations); + assert_1.default.strictEqual(result.adml.length, 3); // en-us + 2 translations + assert_1.default.strictEqual(result.adml[0].languageId, 'en-us'); + assert_1.default.strictEqual(result.adml[1].languageId, 'fr-fr'); + assert_1.default.strictEqual(result.adml[2].languageId, 'de-de'); + assert_1.default.ok(result.adml[1].contents.includes('Politique de test')); + assert_1.default.ok(result.adml[2].contents.includes('Testrichtlinie')); + }); + test('should pass versions to ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.admx.includes('Supported_1_85')); + }); + test('should pass versions to ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.adml[0].contents.includes('VS Code >= 1.85')); + }); + test('should pass categories to ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.admx.includes('test.category')); + }); + test('should pass categories to ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.adml[0].contents.includes('Category_test_category')); + }); + test('should handle multiple policies', () => { + const policy2 = { + ...mockPolicy, + name: 'TestPolicy2', + renderADMX: (regKey) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy 2'] + }; + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy, policy2], []); + assert_1.default.ok(result.admx.includes('TestPolicy')); + assert_1.default.ok(result.admx.includes('TestPolicy2')); + assert_1.default.ok(result.adml[0].contents.includes('TestPolicy')); + assert_1.default.ok(result.adml[0].contents.includes('TestPolicy2')); + }); + test('should include app name in ADML', () => { + const product = { + nameLong: 'My Custom App', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok(result.adml[0].contents.includes('My Custom App')); + }); + test('should return structured result with admx and adml properties', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = (0, render_js_1.renderGP)(product, [mockPolicy], []); + assert_1.default.ok('admx' in result); + assert_1.default.ok('adml' in result); + assert_1.default.strictEqual(typeof result.admx, 'string'); + assert_1.default.ok(Array.isArray(result.adml)); + }); + }); + suite('renderJsonPolicies', () => { + const mockCategory = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + test('should render boolean policy JSON value', () => { + const booleanPolicy = { + name: 'BooleanPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => false + }; + const result = (0, render_js_1.renderJsonPolicies)([booleanPolicy]); + assert_1.default.deepStrictEqual(result, { BooleanPolicy: false }); + }); + test('should render number policy JSON value', () => { + const numberPolicy = { + name: 'NumberPolicy', + type: types_js_1.PolicyType.Number, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 42 + }; + const result = (0, render_js_1.renderJsonPolicies)([numberPolicy]); + assert_1.default.deepStrictEqual(result, { NumberPolicy: 42 }); + }); + test('should render string policy JSON value', () => { + const stringPolicy = { + name: 'StringPolicy', + type: types_js_1.PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => '' + }; + const result = (0, render_js_1.renderJsonPolicies)([stringPolicy]); + assert_1.default.deepStrictEqual(result, { StringPolicy: '' }); + }); + test('should render string enum policy JSON value', () => { + const stringEnumPolicy = { + name: 'StringEnumPolicy', + type: types_js_1.PolicyType.StringEnum, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 'auto' + }; + const result = (0, render_js_1.renderJsonPolicies)([stringEnumPolicy]); + assert_1.default.deepStrictEqual(result, { StringEnumPolicy: 'auto' }); + }); + test('should render object policy JSON value', () => { + const objectPolicy = { + name: 'ObjectPolicy', + type: types_js_1.PolicyType.Object, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => '' + }; + const result = (0, render_js_1.renderJsonPolicies)([objectPolicy]); + assert_1.default.deepStrictEqual(result, { ObjectPolicy: '' }); + }); + test('should render multiple policies', () => { + const booleanPolicy = { + name: 'BooleanPolicy', + type: types_js_1.PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => true + }; + const numberPolicy = { + name: 'NumberPolicy', + type: types_js_1.PolicyType.Number, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 100 + }; + const stringPolicy = { + name: 'StringPolicy', + type: types_js_1.PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 'test-value' + }; + const result = (0, render_js_1.renderJsonPolicies)([booleanPolicy, numberPolicy, stringPolicy]); + assert_1.default.deepStrictEqual(result, { + BooleanPolicy: true, + NumberPolicy: 100, + StringPolicy: 'test-value' + }); + }); + test('should handle empty policies array', () => { + const result = (0, render_js_1.renderJsonPolicies)([]); + assert_1.default.deepStrictEqual(result, {}); + }); + test('should handle null JSON value', () => { + const nullPolicy = { + name: 'NullPolicy', + type: types_js_1.PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + const result = (0, render_js_1.renderJsonPolicies)([nullPolicy]); + assert_1.default.deepStrictEqual(result, { NullPolicy: null }); + }); + test('should handle object JSON value', () => { + const objectPolicy = { + name: 'ComplexObjectPolicy', + type: types_js_1.PolicyType.Object, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => ({ nested: { value: 123 } }) + }; + const result = (0, render_js_1.renderJsonPolicies)([objectPolicy]); + assert_1.default.deepStrictEqual(result, { ComplexObjectPolicy: { nested: { value: 123 } } }); + }); + }); +}); +//# sourceMappingURL=render.test.js.map \ No newline at end of file diff --git a/build/lib/test/render.test.ts b/build/lib/test/render.test.ts new file mode 100644 index 00000000000..325831247c4 --- /dev/null +++ b/build/lib/test/render.test.ts @@ -0,0 +1,1029 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { renderADMLString, renderProfileString, renderADMX, renderADML, renderProfileManifest, renderMacOSPolicy, renderGP, renderJsonPolicies } from '../policies/render.js'; +import { NlsString, LanguageTranslations, Category, Policy, PolicyType } from '../policies/types.js'; + +suite('Render Functions', () => { + + suite('renderADMLString', () => { + + test('should render ADML string without translations', () => { + const nlsString: NlsString = { + value: 'Test description', + nlsKey: 'test.description' + }; + + const result = renderADMLString('TestPrefix', 'testModule', nlsString); + + assert.strictEqual(result, 'Test description'); + }); + + test('should replace dots with underscores in nls key', () => { + const nlsString: NlsString = { + value: 'Test value', + nlsKey: 'my.test.nls.key' + }; + + const result = renderADMLString('Prefix', 'testModule', nlsString); + + assert.ok(result.includes('id="Prefix_my_test_nls_key"')); + }); + + test('should use translation when available', () => { + const nlsString: NlsString = { + value: 'Original value', + nlsKey: 'test.key' + }; + + const translations: LanguageTranslations = { + 'testModule': { + 'test.key': 'Translated value' + } + }; + + const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations); + + assert.ok(result.includes('>Translated value')); + }); + + test('should fallback to original value when translation not found', () => { + const nlsString: NlsString = { + value: 'Original value', + nlsKey: 'test.key' + }; + + const translations: LanguageTranslations = { + 'testModule': { + 'other.key': 'Other translation' + } + }; + + const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations); + + assert.ok(result.includes('>Original value')); + }); + }); + + suite('renderProfileString', () => { + + test('should render profile string without translations', () => { + const nlsString: NlsString = { + value: 'Profile description', + nlsKey: 'profile.description' + }; + + const result = renderProfileString('ProfilePrefix', 'testModule', nlsString); + + assert.strictEqual(result, 'Profile description'); + }); + + test('should use translation when available', () => { + const nlsString: NlsString = { + value: 'Original profile value', + nlsKey: 'profile.key' + }; + + const translations: LanguageTranslations = { + 'testModule': { + 'profile.key': 'Translated profile value' + } + }; + + const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations); + + assert.strictEqual(result, 'Translated profile value'); + }); + + test('should fallback to original value when translation not found', () => { + const nlsString: NlsString = { + value: 'Original profile value', + nlsKey: 'profile.key' + }; + + const translations: LanguageTranslations = { + 'testModule': { + 'other.key': 'Other translation' + } + }; + + const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations); + + assert.strictEqual(result, 'Original profile value'); + }); + }); + + suite('renderADMX', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + const mockPolicy: Policy = { + name: 'TestPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey: string) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy'], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy', ''], + renderProfileManifest: () => 'pfm_nameTestPolicy', + renderJsonValue: () => null + }; + + test('should render ADMX with correct XML structure', () => { + const result = renderADMX('VSCode', ['1.85'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('')); + }); + + test('should include policy namespaces with regKey', () => { + const result = renderADMX('TestApp', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes(' { + const result = renderADMX('VSCode', ['1.85.0', '1.90.1'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('Supported_1_85_0')); + assert.ok(result.includes('Supported_1_90_1')); + assert.ok(!result.includes('Supported_1.85.0')); + }); + + test('should include categories in correct structure', () => { + const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('')); + }); + + test('should include policies section', () => { + const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('TestPolicy')); + assert.ok(result.includes('')); + }); + + test('should handle multiple versions', () => { + const result = renderADMX('VSCode', ['1.0', '1.5', '2.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('Supported_1_0')); + assert.ok(result.includes('Supported_1_5')); + assert.ok(result.includes('Supported_2_0')); + }); + + test('should handle multiple categories', () => { + const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } }; + const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } }; + + const result = renderADMX('VSCode', ['1.0'], [category1, category2], [mockPolicy]); + + assert.ok(result.includes('Category_cat1')); + assert.ok(result.includes('Category_cat2')); + }); + + test('should handle multiple policies', () => { + const policy2: Policy = { + name: 'TestPolicy2', + type: PolicyType.String, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey: string) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy 2'], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy2', ''], + renderProfileManifest: () => 'pfm_nameTestPolicy2', + renderJsonValue: () => null + }; + const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy, policy2]); + + assert.ok(result.includes('TestPolicy')); + assert.ok(result.includes('TestPolicy2')); + }); + }); + + suite('renderADML', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + const mockPolicy: Policy = { + name: 'TestPolicy', + type: PolicyType.String, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: () => [], + renderADMLStrings: (translations?: LanguageTranslations) => [ + `Test Policy ${translations?.['testModule']?.['test.policy'] || 'Default'}` + ], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + + test('should render ADML with correct XML structure', () => { + const result = renderADML('VS Code', ['1.85'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('')); + }); + + test('should include application name', () => { + const result = renderADML('My Application', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('My Application')); + }); + + test('should include supported versions with escaped greater-than', () => { + const result = renderADML('VS Code', ['1.85', '1.90'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('VS Code >= 1.85')); + assert.ok(result.includes('VS Code >= 1.90')); + }); + + test('should include category strings', () => { + const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('Category_test_category')); + }); + + test('should include policy strings', () => { + const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('TestPolicy')); + assert.ok(result.includes('Test Policy Default')); + }); + + test('should include policy presentations', () => { + const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('')); + assert.ok(result.includes('')); + }); + + test('should pass translations to policy strings', () => { + const translations: LanguageTranslations = { + 'testModule': { + 'test.policy': 'Translated' + } + }; + + const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy], translations); + + assert.ok(result.includes('Test Policy Translated')); + }); + + test('should handle multiple categories', () => { + const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } }; + const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } }; + + const result = renderADML('VS Code', ['1.0'], [category1, category2], [mockPolicy]); + + assert.ok(result.includes('Category_cat1')); + assert.ok(result.includes('Category_cat2')); + }); + }); + + suite('renderProfileManifest', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + const mockPolicy: Policy = { + name: 'TestPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: (translations?: LanguageTranslations) => ` +pfm_name +TestPolicy +pfm_description +${translations?.['testModule']?.['test.desc'] || 'Default Desc'} +`, + renderJsonValue: () => null + }; + + test('should render profile manifest with correct XML structure', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('')); + assert.ok(result.includes('')); + assert.ok(result.includes('')); + }); + + test('should include app name', () => { + const result = renderProfileManifest('My App', 'com.example.myapp', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('My App Managed Settings')); + assert.ok(result.includes('My App')); + }); + + test('should include bundle identifier', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('com.microsoft.vscode')); + }); + + test('should include required payload fields', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('PayloadDescription')); + assert.ok(result.includes('PayloadDisplayName')); + assert.ok(result.includes('PayloadIdentifier')); + assert.ok(result.includes('PayloadType')); + assert.ok(result.includes('PayloadUUID')); + assert.ok(result.includes('PayloadVersion')); + assert.ok(result.includes('PayloadOrganization')); + }); + + test('should include policy manifests in subkeys', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_subkeys')); + assert.ok(result.includes('TestPolicy')); + assert.ok(result.includes('Default Desc')); + }); + + test('should pass translations to policy manifests', () => { + const translations: LanguageTranslations = { + 'testModule': { + 'test.desc': 'Translated Description' + } + }; + + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy], translations); + + assert.ok(result.includes('Translated Description')); + }); + + test('should include VS Code specific URLs', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('https://code.visualstudio.com/')); + assert.ok(result.includes('https://code.visualstudio.com/docs/setup/enterprise')); + }); + + test('should include last modified date', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_last_modified')); + assert.ok(result.includes('')); + }); + + test('should mark manifest as unique', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_unique')); + assert.ok(result.includes('')); + }); + + test('should handle multiple policies', () => { + const policy2: Policy = { + ...mockPolicy, + name: 'TestPolicy2', + renderProfileManifest: () => ` +pfm_name +TestPolicy2 +` + }; + + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy, policy2]); + + assert.ok(result.includes('TestPolicy')); + assert.ok(result.includes('TestPolicy2')); + }); + + test('should set format version to 1', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_format_version')); + assert.ok(result.includes('1')); + }); + + test('should set interaction to combined', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_interaction')); + assert.ok(result.includes('combined')); + }); + + test('should set platform to macOS', () => { + const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]); + + assert.ok(result.includes('pfm_platforms')); + assert.ok(result.includes('macOS')); + }); + }); + + suite('renderMacOSPolicy', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + const mockPolicy: Policy = { + name: 'TestPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => ['TestPolicy', ''], + renderProfileManifest: (translations?: LanguageTranslations) => ` +pfm_name +TestPolicy +pfm_description +${translations?.['testModule']?.['test.desc'] || 'Default Desc'} +`, + renderJsonValue: () => null + }; + + test('should render complete macOS policy profile', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy], []); + + const expected = ` + + + + PayloadContent + + + PayloadDisplayName + VS Code + PayloadIdentifier + com.microsoft.vscode.uuid + PayloadType + com.microsoft.vscode + PayloadUUID + uuid + PayloadVersion + 1 + TestPolicy + + + + PayloadDescription + This profile manages VS Code. For more information see https://code.visualstudio.com/docs/setup/enterprise + PayloadDisplayName + VS Code + PayloadIdentifier + com.microsoft.vscode + PayloadOrganization + Microsoft + PayloadType + Configuration + PayloadUUID + payload-uuid + PayloadVersion + 1 + TargetDeviceType + 5 + +`; + + assert.strictEqual(result.profile, expected); + }); + + test('should include en-us manifest by default', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy], []); + + assert.strictEqual(result.manifests.length, 1); + assert.strictEqual(result.manifests[0].languageId, 'en-us'); + assert.ok(result.manifests[0].contents.includes('VS Code Managed Settings')); + }); + + test('should include translations', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const translations = [ + { languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.desc': 'Description Française' } } }, + { languageId: 'de-de', languageTranslations: { 'testModule': { 'test.desc': 'Deutsche Beschreibung' } } } + ]; + + const result = renderMacOSPolicy(product, [mockPolicy], translations); + + assert.strictEqual(result.manifests.length, 3); // en-us + 2 translations + assert.strictEqual(result.manifests[0].languageId, 'en-us'); + assert.strictEqual(result.manifests[1].languageId, 'fr-fr'); + assert.strictEqual(result.manifests[2].languageId, 'de-de'); + + assert.ok(result.manifests[1].contents.includes('Description Française')); + assert.ok(result.manifests[2].contents.includes('Deutsche Beschreibung')); + }); + + test('should handle multiple policies with correct indentation', () => { + const policy2: Policy = { + ...mockPolicy, + name: 'TestPolicy2', + renderProfile: () => ['TestPolicy2', 'test value'] + }; + + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy, policy2], []); + + assert.ok(result.profile.includes('TestPolicy')); + assert.ok(result.profile.includes('')); + assert.ok(result.profile.includes('TestPolicy2')); + assert.ok(result.profile.includes('test value')); + }); + + test('should use provided UUIDs in profile', () => { + const product = { + nameLong: 'My App', + darwinBundleIdentifier: 'com.example.app', + darwinProfilePayloadUUID: 'custom-payload-uuid', + darwinProfileUUID: 'custom-uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy], []); + + assert.ok(result.profile.includes('custom-payload-uuid')); + assert.ok(result.profile.includes('custom-uuid')); + assert.ok(result.profile.includes('com.example.app.custom-uuid')); + }); + + test('should include enterprise documentation link', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy], []); + + assert.ok(result.profile.includes('https://code.visualstudio.com/docs/setup/enterprise')); + }); + + test('should set TargetDeviceType to 5', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderMacOSPolicy(product, [mockPolicy], []); + + assert.ok(result.profile.includes('TargetDeviceType')); + assert.ok(result.profile.includes('5')); + }); + }); + + suite('renderGP', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + const mockPolicy: Policy = { + name: 'TestPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.85', + renderADMX: (regKey: string) => [ + ``, + ` `, + `` + ], + renderADMLStrings: (translations?: LanguageTranslations) => [ + `${translations?.['testModule']?.['test.policy'] || 'Test Policy'}` + ], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + + test('should render complete GP with ADMX and ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.admx); + assert.ok(result.adml); + assert.ok(Array.isArray(result.adml)); + }); + + test('should include regKey in ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'CustomRegKey' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.admx.includes('CustomRegKey')); + assert.ok(result.admx.includes('Software\\Policies\\Microsoft\\CustomRegKey')); + }); + + test('should include en-us ADML by default', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.strictEqual(result.adml.length, 1); + assert.strictEqual(result.adml[0].languageId, 'en-us'); + assert.ok(result.adml[0].contents.includes('VS Code')); + }); + + test('should include translations in ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const translations = [ + { languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.policy': 'Politique de test' } } }, + { languageId: 'de-de', languageTranslations: { 'testModule': { 'test.policy': 'Testrichtlinie' } } } + ]; + + const result = renderGP(product, [mockPolicy], translations); + + assert.strictEqual(result.adml.length, 3); // en-us + 2 translations + assert.strictEqual(result.adml[0].languageId, 'en-us'); + assert.strictEqual(result.adml[1].languageId, 'fr-fr'); + assert.strictEqual(result.adml[2].languageId, 'de-de'); + + assert.ok(result.adml[1].contents.includes('Politique de test')); + assert.ok(result.adml[2].contents.includes('Testrichtlinie')); + }); + + test('should pass versions to ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.admx.includes('Supported_1_85')); + }); + + test('should pass versions to ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.adml[0].contents.includes('VS Code >= 1.85')); + }); + + test('should pass categories to ADMX', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.admx.includes('test.category')); + }); + + test('should pass categories to ADML', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.adml[0].contents.includes('Category_test_category')); + }); + + test('should handle multiple policies', () => { + const policy2: Policy = { + ...mockPolicy, + name: 'TestPolicy2', + renderADMX: (regKey: string) => [ + ``, + ` `, + `` + ], + renderADMLStrings: () => ['Test Policy 2'] + }; + + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy, policy2], []); + + assert.ok(result.admx.includes('TestPolicy')); + assert.ok(result.admx.includes('TestPolicy2')); + assert.ok(result.adml[0].contents.includes('TestPolicy')); + assert.ok(result.adml[0].contents.includes('TestPolicy2')); + }); + + test('should include app name in ADML', () => { + const product = { + nameLong: 'My Custom App', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok(result.adml[0].contents.includes('My Custom App')); + }); + + test('should return structured result with admx and adml properties', () => { + const product = { + nameLong: 'VS Code', + darwinBundleIdentifier: 'com.microsoft.vscode', + darwinProfilePayloadUUID: 'payload-uuid', + darwinProfileUUID: 'uuid', + win32RegValueName: 'VSCode' + }; + const result = renderGP(product, [mockPolicy], []); + + assert.ok('admx' in result); + assert.ok('adml' in result); + assert.strictEqual(typeof result.admx, 'string'); + assert.ok(Array.isArray(result.adml)); + }); + }); + + suite('renderJsonPolicies', () => { + + const mockCategory: Category = { + moduleName: 'testModule', + name: { value: 'Test Category', nlsKey: 'test.category' } + }; + + test('should render boolean policy JSON value', () => { + const booleanPolicy: Policy = { + name: 'BooleanPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => false + }; + + const result = renderJsonPolicies([booleanPolicy]); + + assert.deepStrictEqual(result, { BooleanPolicy: false }); + }); + + test('should render number policy JSON value', () => { + const numberPolicy: Policy = { + name: 'NumberPolicy', + type: PolicyType.Number, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 42 + }; + + const result = renderJsonPolicies([numberPolicy]); + + assert.deepStrictEqual(result, { NumberPolicy: 42 }); + }); + + test('should render string policy JSON value', () => { + const stringPolicy: Policy = { + name: 'StringPolicy', + type: PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => '' + }; + + const result = renderJsonPolicies([stringPolicy]); + + assert.deepStrictEqual(result, { StringPolicy: '' }); + }); + + test('should render string enum policy JSON value', () => { + const stringEnumPolicy: Policy = { + name: 'StringEnumPolicy', + type: PolicyType.StringEnum, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 'auto' + }; + + const result = renderJsonPolicies([stringEnumPolicy]); + + assert.deepStrictEqual(result, { StringEnumPolicy: 'auto' }); + }); + + test('should render object policy JSON value', () => { + const objectPolicy: Policy = { + name: 'ObjectPolicy', + type: PolicyType.Object, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => '' + }; + + const result = renderJsonPolicies([objectPolicy]); + + assert.deepStrictEqual(result, { ObjectPolicy: '' }); + }); + + test('should render multiple policies', () => { + const booleanPolicy: Policy = { + name: 'BooleanPolicy', + type: PolicyType.Boolean, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => true + }; + + const numberPolicy: Policy = { + name: 'NumberPolicy', + type: PolicyType.Number, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 100 + }; + + const stringPolicy: Policy = { + name: 'StringPolicy', + type: PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => 'test-value' + }; + + const result = renderJsonPolicies([booleanPolicy, numberPolicy, stringPolicy]); + + assert.deepStrictEqual(result, { + BooleanPolicy: true, + NumberPolicy: 100, + StringPolicy: 'test-value' + }); + }); + + test('should handle empty policies array', () => { + const result = renderJsonPolicies([]); + + assert.deepStrictEqual(result, {}); + }); + + test('should handle null JSON value', () => { + const nullPolicy: Policy = { + name: 'NullPolicy', + type: PolicyType.String, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => null + }; + + const result = renderJsonPolicies([nullPolicy]); + + assert.deepStrictEqual(result, { NullPolicy: null }); + }); + + test('should handle object JSON value', () => { + const objectPolicy: Policy = { + name: 'ComplexObjectPolicy', + type: PolicyType.Object, + category: mockCategory, + minimumVersion: '1.0', + renderADMX: () => [], + renderADMLStrings: () => [], + renderADMLPresentation: () => '', + renderProfile: () => [], + renderProfileManifest: () => '', + renderJsonValue: () => ({ nested: { value: 123 } }) + }; + + const result = renderJsonPolicies([objectPolicy]); + + assert.deepStrictEqual(result, { ComplexObjectPolicy: { nested: { value: 123 } } }); + }); + }); +}); diff --git a/build/lib/test/stringEnumPolicy.test.js b/build/lib/test/stringEnumPolicy.test.js new file mode 100644 index 00000000000..d1700730544 --- /dev/null +++ b/build/lib/test/stringEnumPolicy.test.js @@ -0,0 +1,142 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const stringEnumPolicy_js_1 = require("../policies/stringEnumPolicy.js"); +const types_js_1 = require("../policies/types.js"); +suite('StringEnumPolicy', () => { + const mockCategory = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + const mockPolicy = { + key: 'test.stringenum.policy', + name: 'TestStringEnumPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'string', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' }, + enumDescriptions: [ + { key: 'test.option.one', value: 'Option One' }, + { key: 'test.option.two', value: 'Option Two' }, + { key: 'test.option.three', value: 'Option Three' } + ] + }, + enum: ['auto', 'manual', 'disabled'] + }; + test('should create StringEnumPolicy from factory method', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + assert_1.default.strictEqual(policy.name, 'TestStringEnumPolicy'); + assert_1.default.strictEqual(policy.minimumVersion, '1.0'); + assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value); + assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.StringEnum); + }); + test('should render ADMX elements correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admx = policy.renderADMX('TestKey'); + assert_1.default.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\tauto', + '\tmanual', + '\tdisabled', + '', + '\t', + '' + ]); + }); + test('should render ADML strings correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admlStrings = policy.renderADMLStrings(); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestStringEnumPolicy', + 'Test policy description', + 'Option One', + 'Option Two', + 'Option Three' + ]); + }); + test('should render ADML strings with translations', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated description', + 'test.option.one': 'Translated Option One', + 'test.option.two': 'Translated Option Two' + } + }; + const admlStrings = policy.renderADMLStrings(translations); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestStringEnumPolicy', + 'Translated description', + 'Translated Option One', + 'Translated Option Two', + 'Option Three' + ]); + }); + test('should render ADML presentation correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const presentation = policy.renderADMLPresentation(); + assert_1.default.strictEqual(presentation, ''); + }); + test('should render JSON value correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const jsonValue = policy.renderJsonValue(); + assert_1.default.strictEqual(jsonValue, 'auto'); + }); + test('should render profile value correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profileValue = policy.renderProfileValue(); + assert_1.default.strictEqual(profileValue, 'auto'); + }); + test('should render profile correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profile = policy.renderProfile(); + assert_1.default.strictEqual(profile.length, 2); + assert_1.default.strictEqual(profile[0], 'TestStringEnumPolicy'); + assert_1.default.strictEqual(profile[1], 'auto'); + }); + test('should render profile manifest value correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifestValue = policy.renderProfileManifestValue(); + assert_1.default.strictEqual(manifestValue, 'pfm_default\nauto\npfm_description\nTest policy description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n'); + }); + test('should render profile manifest value with translations', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + const manifestValue = policy.renderProfileManifestValue(translations); + assert_1.default.strictEqual(manifestValue, 'pfm_default\nauto\npfm_description\nTranslated manifest description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n'); + }); + test('should render profile manifest correctly', () => { + const policy = stringEnumPolicy_js_1.StringEnumPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifest = policy.renderProfileManifest(); + assert_1.default.strictEqual(manifest, '\npfm_default\nauto\npfm_description\nTest policy description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n\n'); + }); +}); +//# sourceMappingURL=stringEnumPolicy.test.js.map \ No newline at end of file diff --git a/build/lib/test/stringEnumPolicy.test.ts b/build/lib/test/stringEnumPolicy.test.ts new file mode 100644 index 00000000000..3ee3856afd7 --- /dev/null +++ b/build/lib/test/stringEnumPolicy.test.ts @@ -0,0 +1,184 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { StringEnumPolicy } from '../policies/stringEnumPolicy.js'; +import { LanguageTranslations, PolicyType } from '../policies/types.js'; +import { CategoryDto, PolicyDto } from '../policies/policyDto.js'; + +suite('StringEnumPolicy', () => { + const mockCategory: CategoryDto = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + + const mockPolicy: PolicyDto = { + key: 'test.stringenum.policy', + name: 'TestStringEnumPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'string', + localization: { + description: { key: 'test.policy.description', value: 'Test policy description' }, + enumDescriptions: [ + { key: 'test.option.one', value: 'Option One' }, + { key: 'test.option.two', value: 'Option Two' }, + { key: 'test.option.three', value: 'Option Three' } + ] + }, + enum: ['auto', 'manual', 'disabled'] + }; + + test('should create StringEnumPolicy from factory method', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + assert.strictEqual(policy.name, 'TestStringEnumPolicy'); + assert.strictEqual(policy.minimumVersion, '1.0'); + assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert.strictEqual(policy.category.name.value, mockCategory.name.value); + assert.strictEqual(policy.type, PolicyType.StringEnum); + }); + + test('should render ADMX elements correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admx = policy.renderADMX('TestKey'); + + assert.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\tauto', + '\tmanual', + '\tdisabled', + '', + '\t', + '' + ]); + }); + + test('should render ADML strings correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admlStrings = policy.renderADMLStrings(); + + assert.deepStrictEqual(admlStrings, [ + 'TestStringEnumPolicy', + 'Test policy description', + 'Option One', + 'Option Two', + 'Option Three' + ]); + }); + + test('should render ADML strings with translations', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated description', + 'test.option.one': 'Translated Option One', + 'test.option.two': 'Translated Option Two' + } + }; + + const admlStrings = policy.renderADMLStrings(translations); + + assert.deepStrictEqual(admlStrings, [ + 'TestStringEnumPolicy', + 'Translated description', + 'Translated Option One', + 'Translated Option Two', + 'Option Three' + ]); + }); + + test('should render ADML presentation correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const presentation = policy.renderADMLPresentation(); + + assert.strictEqual(presentation, ''); + }); + + test('should render JSON value correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const jsonValue = policy.renderJsonValue(); + + assert.strictEqual(jsonValue, 'auto'); + }); + + test('should render profile value correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profileValue = policy.renderProfileValue(); + + assert.strictEqual(profileValue, 'auto'); + }); + + test('should render profile correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profile = policy.renderProfile(); + + assert.strictEqual(profile.length, 2); + assert.strictEqual(profile[0], 'TestStringEnumPolicy'); + assert.strictEqual(profile[1], 'auto'); + }); + + test('should render profile manifest value correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifestValue = policy.renderProfileManifestValue(); + + assert.strictEqual(manifestValue, 'pfm_default\nauto\npfm_description\nTest policy description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n'); + }); + + test('should render profile manifest value with translations', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + + const manifestValue = policy.renderProfileManifestValue(translations); + + assert.strictEqual(manifestValue, 'pfm_default\nauto\npfm_description\nTranslated manifest description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n'); + }); + + test('should render profile manifest correctly', () => { + const policy = StringEnumPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifest = policy.renderProfileManifest(); + + assert.strictEqual(manifest, '\npfm_default\nauto\npfm_description\nTest policy description\npfm_name\nTestStringEnumPolicy\npfm_title\nTestStringEnumPolicy\npfm_type\nstring\npfm_range_list\n\n\tauto\n\tmanual\n\tdisabled\n\n'); + }); +}); diff --git a/build/lib/test/stringPolicy.test.js b/build/lib/test/stringPolicy.test.js new file mode 100644 index 00000000000..6919da78f88 --- /dev/null +++ b/build/lib/test/stringPolicy.test.js @@ -0,0 +1,125 @@ +"use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const assert_1 = __importDefault(require("assert")); +const stringPolicy_js_1 = require("../policies/stringPolicy.js"); +const types_js_1 = require("../policies/types.js"); +suite('StringPolicy', () => { + const mockCategory = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + const mockPolicy = { + key: 'test.string.policy', + name: 'TestStringPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'string', + default: '', + localization: { + description: { key: 'test.policy.description', value: 'Test string policy description' } + } + }; + test('should create StringPolicy from factory method', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + assert_1.default.strictEqual(policy.name, 'TestStringPolicy'); + assert_1.default.strictEqual(policy.minimumVersion, '1.0'); + assert_1.default.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert_1.default.strictEqual(policy.category.name.value, mockCategory.name.value); + assert_1.default.strictEqual(policy.type, types_js_1.PolicyType.String); + }); + test('should render ADMX elements correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admx = policy.renderADMX('TestKey'); + assert_1.default.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + test('should render ADML strings correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const admlStrings = policy.renderADMLStrings(); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestStringPolicy', + 'Test string policy description' + ]); + }); + test('should render ADML strings with translations', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + const admlStrings = policy.renderADMLStrings(translations); + assert_1.default.deepStrictEqual(admlStrings, [ + 'TestStringPolicy', + 'Translated description' + ]); + }); + test('should render ADML presentation correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const presentation = policy.renderADMLPresentation(); + assert_1.default.strictEqual(presentation, ''); + }); + test('should render JSON value correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const jsonValue = policy.renderJsonValue(); + assert_1.default.strictEqual(jsonValue, ''); + }); + test('should render profile value correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profileValue = policy.renderProfileValue(); + assert_1.default.strictEqual(profileValue, ''); + }); + test('should render profile correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const profile = policy.renderProfile(); + assert_1.default.strictEqual(profile.length, 2); + assert_1.default.strictEqual(profile[0], 'TestStringPolicy'); + assert_1.default.strictEqual(profile[1], ''); + }); + test('should render profile manifest value correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifestValue = policy.renderProfileManifestValue(); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest string policy description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring'); + }); + test('should render profile manifest value with translations', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const translations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + const manifestValue = policy.renderProfileManifestValue(translations); + assert_1.default.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring'); + }); + test('should render profile manifest correctly', () => { + const policy = stringPolicy_js_1.StringPolicy.from(mockCategory, mockPolicy); + assert_1.default.ok(policy); + const manifest = policy.renderProfileManifest(); + assert_1.default.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest string policy description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring\n'); + }); +}); +//# sourceMappingURL=stringPolicy.test.js.map \ No newline at end of file diff --git a/build/lib/test/stringPolicy.test.ts b/build/lib/test/stringPolicy.test.ts new file mode 100644 index 00000000000..a76c38c7dcb --- /dev/null +++ b/build/lib/test/stringPolicy.test.ts @@ -0,0 +1,167 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { StringPolicy } from '../policies/stringPolicy.js'; +import { LanguageTranslations, PolicyType } from '../policies/types.js'; +import { CategoryDto, PolicyDto } from '../policies/policyDto.js'; + +suite('StringPolicy', () => { + const mockCategory: CategoryDto = { + key: 'test.category', + name: { value: 'Category1', key: 'test.category' }, + }; + + const mockPolicy: PolicyDto = { + key: 'test.string.policy', + name: 'TestStringPolicy', + category: 'Category1', + minimumVersion: '1.0', + type: 'string', + default: '', + localization: { + description: { key: 'test.policy.description', value: 'Test string policy description' } + } + }; + + test('should create StringPolicy from factory method', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + assert.strictEqual(policy.name, 'TestStringPolicy'); + assert.strictEqual(policy.minimumVersion, '1.0'); + assert.strictEqual(policy.category.name.nlsKey, mockCategory.name.key); + assert.strictEqual(policy.category.name.value, mockCategory.name.value); + assert.strictEqual(policy.type, PolicyType.String); + }); + + test('should render ADMX elements correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admx = policy.renderADMX('TestKey'); + + assert.deepStrictEqual(admx, [ + '', + '\t', + '\t', + '\t', + '', + '\t', + '' + ]); + }); + + test('should render ADML strings correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const admlStrings = policy.renderADMLStrings(); + + assert.deepStrictEqual(admlStrings, [ + 'TestStringPolicy', + 'Test string policy description' + ]); + }); + + test('should render ADML strings with translations', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated description' + } + }; + + const admlStrings = policy.renderADMLStrings(translations); + + assert.deepStrictEqual(admlStrings, [ + 'TestStringPolicy', + 'Translated description' + ]); + }); + + test('should render ADML presentation correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const presentation = policy.renderADMLPresentation(); + + assert.strictEqual(presentation, ''); + }); + + test('should render JSON value correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const jsonValue = policy.renderJsonValue(); + + assert.strictEqual(jsonValue, ''); + }); + + test('should render profile value correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profileValue = policy.renderProfileValue(); + + assert.strictEqual(profileValue, ''); + }); + + test('should render profile correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const profile = policy.renderProfile(); + + assert.strictEqual(profile.length, 2); + assert.strictEqual(profile[0], 'TestStringPolicy'); + assert.strictEqual(profile[1], ''); + }); + + test('should render profile manifest value correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifestValue = policy.renderProfileManifestValue(); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTest string policy description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring'); + }); + + test('should render profile manifest value with translations', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const translations: LanguageTranslations = { + '': { + 'test.policy.description': 'Translated manifest description' + } + }; + + const manifestValue = policy.renderProfileManifestValue(translations); + + assert.strictEqual(manifestValue, 'pfm_default\n\npfm_description\nTranslated manifest description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring'); + }); + + test('should render profile manifest correctly', () => { + const policy = StringPolicy.from(mockCategory, mockPolicy); + + assert.ok(policy); + + const manifest = policy.renderProfileManifest(); + + assert.strictEqual(manifest, '\npfm_default\n\npfm_description\nTest string policy description\npfm_name\nTestStringPolicy\npfm_title\nTestStringPolicy\npfm_type\nstring\n'); + }); +}); diff --git a/build/lib/treeshaking.js b/build/lib/treeshaking.js index a679446f60b..feca811d9f9 100644 --- a/build/lib/treeshaking.js +++ b/build/lib/treeshaking.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toStringShakeLevel = toStringShakeLevel; exports.shake = shake; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const typeScriptLanguageServiceHost_1 = require("./typeScriptLanguageServiceHost"); @@ -71,16 +71,16 @@ function createTypeScriptLanguageService(ts, options) { // Add entrypoints options.entryPoints.forEach(entryPoint => { const filePath = path_1.default.join(options.sourcesRoot, entryPoint); - FILES.set(filePath, fs_1.default.readFileSync(filePath).toString()); + FILES.set(path_1.default.normalize(filePath), fs_1.default.readFileSync(filePath).toString()); }); // Add fake usage files options.inlineEntryPoints.forEach((inlineEntryPoint, index) => { - FILES.set(path_1.default.join(options.sourcesRoot, `inlineEntryPoint.${index}.ts`), inlineEntryPoint); + FILES.set(path_1.default.normalize(path_1.default.join(options.sourcesRoot, `inlineEntryPoint.${index}.ts`)), inlineEntryPoint); }); // Add additional typings options.typings.forEach((typing) => { const filePath = path_1.default.join(options.sourcesRoot, typing); - FILES.set(filePath, fs_1.default.readFileSync(filePath).toString()); + FILES.set(path_1.default.normalize(filePath), fs_1.default.readFileSync(filePath).toString()); }); const basePath = path_1.default.join(options.sourcesRoot, '..'); const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, basePath).options; diff --git a/build/lib/treeshaking.ts b/build/lib/treeshaking.ts index 9c2fcc11925..3d1e785e073 100644 --- a/build/lib/treeshaking.ts +++ b/build/lib/treeshaking.ts @@ -112,18 +112,18 @@ function createTypeScriptLanguageService(ts: typeof import('typescript'), option // Add entrypoints options.entryPoints.forEach(entryPoint => { const filePath = path.join(options.sourcesRoot, entryPoint); - FILES.set(filePath, fs.readFileSync(filePath).toString()); + FILES.set(path.normalize(filePath), fs.readFileSync(filePath).toString()); }); // Add fake usage files options.inlineEntryPoints.forEach((inlineEntryPoint, index) => { - FILES.set(path.join(options.sourcesRoot, `inlineEntryPoint.${index}.ts`), inlineEntryPoint); + FILES.set(path.normalize(path.join(options.sourcesRoot, `inlineEntryPoint.${index}.ts`)), inlineEntryPoint); }); // Add additional typings options.typings.forEach((typing) => { const filePath = path.join(options.sourcesRoot, typing); - FILES.set(filePath, fs.readFileSync(filePath).toString()); + FILES.set(path.normalize(filePath), fs.readFileSync(filePath).toString()); }); const basePath = path.join(options.sourcesRoot, '..'); diff --git a/build/lib/tsb/builder.js b/build/lib/tsb/builder.js index 1c0640a11e7..eb8e7bca1b3 100644 --- a/build/lib/tsb/builder.js +++ b/build/lib/tsb/builder.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -38,10 +42,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); exports.CancellationToken = void 0; exports.createTypeScriptBuilder = createTypeScriptBuilder; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const crypto_1 = __importDefault(require("crypto")); diff --git a/build/lib/tsb/index.js b/build/lib/tsb/index.js index af10bf8ce19..552eea5014f 100644 --- a/build/lib/tsb/index.js +++ b/build/lib/tsb/index.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); @@ -37,10 +41,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); exports.create = create; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const vinyl_1 = __importDefault(require("vinyl")); const through_1 = __importDefault(require("through")); const builder = __importStar(require("./builder")); diff --git a/build/lib/tsb/transpiler.js b/build/lib/tsb/transpiler.js index 4720ce43975..07c19c5bae2 100644 --- a/build/lib/tsb/transpiler.js +++ b/build/lib/tsb/transpiler.js @@ -1,18 +1,19 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ESBuildTranspiler = exports.TscTranspiler = void 0; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const esbuild_1 = __importDefault(require("esbuild")); const typescript_1 = __importDefault(require("typescript")); const node_worker_threads_1 = __importDefault(require("node:worker_threads")); const vinyl_1 = __importDefault(require("vinyl")); const node_os_1 = require("node:os"); +const tsconfigUtils_1 = require("../tsconfigUtils"); function transpile(tsSrc, options) { const isAmd = /\n(import|export)/m.test(tsSrc); if (!isAmd && options.compilerOptions?.module === typescript_1.default.ModuleKind.AMD) { @@ -240,8 +241,9 @@ class ESBuildTranspiler { _logFn('Transpile', `will use ESBuild to transpile source files`); this._outputFileNames = new OutputFileNameOracle(_cmdLine, configFilePath); const isExtension = configFilePath.includes('extensions'); + const target = (0, tsconfigUtils_1.getTargetStringFromTsConfig)(configFilePath); this._transformOpts = { - target: ['es2022'], + target: [target], format: isExtension ? 'cjs' : 'esm', platform: isExtension ? 'node' : undefined, loader: 'ts', diff --git a/build/lib/tsb/transpiler.ts b/build/lib/tsb/transpiler.ts index 0d8d5fdf821..f81039d70b6 100644 --- a/build/lib/tsb/transpiler.ts +++ b/build/lib/tsb/transpiler.ts @@ -8,6 +8,7 @@ import ts from 'typescript'; import threads from 'node:worker_threads'; import Vinyl from 'vinyl'; import { cpus } from 'node:os'; +import { getTargetStringFromTsConfig } from '../tsconfigUtils'; interface TranspileReq { readonly tsSrcs: string[]; @@ -311,8 +312,10 @@ export class ESBuildTranspiler implements ITranspiler { const isExtension = configFilePath.includes('extensions'); + const target = getTargetStringFromTsConfig(configFilePath); + this._transformOpts = { - target: ['es2022'], + target: [target], format: isExtension ? 'cjs' : 'esm', platform: isExtension ? 'node' : undefined, loader: 'ts', diff --git a/build/lib/tsb/utils.js b/build/lib/tsb/utils.js index 72de33b5ac7..2ea820c6e6b 100644 --- a/build/lib/tsb/utils.js +++ b/build/lib/tsb/utils.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.graph = exports.strings = void 0; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.graph = exports.strings = void 0; var strings; (function (strings) { function format(value, ...rest) { diff --git a/build/lib/tsconfigUtils.js b/build/lib/tsconfigUtils.js new file mode 100644 index 00000000000..a20e2d6f77d --- /dev/null +++ b/build/lib/tsconfigUtils.js @@ -0,0 +1,28 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.getTargetStringFromTsConfig = getTargetStringFromTsConfig; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +const path_1 = require("path"); +const typescript_1 = __importDefault(require("typescript")); +/** + * Get the target (e.g. 'ES2024') from a tsconfig.json file. + */ +function getTargetStringFromTsConfig(configFilePath) { + const parsed = typescript_1.default.readConfigFile(configFilePath, typescript_1.default.sys.readFile); + if (parsed.error) { + throw new Error(`Cannot determine target from ${configFilePath}. TS error: ${parsed.error.messageText}`); + } + const cmdLine = typescript_1.default.parseJsonConfigFileContent(parsed.config, typescript_1.default.sys, (0, path_1.dirname)(configFilePath), {}); + const resolved = typeof cmdLine.options.target !== 'undefined' ? typescript_1.default.ScriptTarget[cmdLine.options.target] : undefined; + if (!resolved) { + throw new Error(`Could not resolve target in ${configFilePath}`); + } + return resolved; +} +//# sourceMappingURL=tsconfigUtils.js.map \ No newline at end of file diff --git a/build/lib/tsconfigUtils.ts b/build/lib/tsconfigUtils.ts new file mode 100644 index 00000000000..0afb2f02ae7 --- /dev/null +++ b/build/lib/tsconfigUtils.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { dirname } from 'path'; +import ts from 'typescript'; + +/** + * Get the target (e.g. 'ES2024') from a tsconfig.json file. + */ +export function getTargetStringFromTsConfig(configFilePath: string): string { + const parsed = ts.readConfigFile(configFilePath, ts.sys.readFile); + if (parsed.error) { + throw new Error(`Cannot determine target from ${configFilePath}. TS error: ${parsed.error.messageText}`); + } + + const cmdLine = ts.parseJsonConfigFileContent(parsed.config, ts.sys, dirname(configFilePath), {}); + const resolved = typeof cmdLine.options.target !== 'undefined' ? ts.ScriptTarget[cmdLine.options.target] : undefined; + if (!resolved) { + throw new Error(`Could not resolve target in ${configFilePath}`); + } + return resolved; +} + diff --git a/build/lib/typeScriptLanguageServiceHost.js b/build/lib/typeScriptLanguageServiceHost.js index d90ad86f9be..6ba0802102d 100644 --- a/build/lib/typeScriptLanguageServiceHost.js +++ b/build/lib/typeScriptLanguageServiceHost.js @@ -1,15 +1,19 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeScriptLanguageServiceHost = void 0; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const typescript_1 = __importDefault(require("typescript")); const node_fs_1 = __importDefault(require("node:fs")); +const node_path_1 = require("node:path"); +function normalizePath(filePath) { + return (0, node_path_1.normalize)(filePath); +} /** * A TypeScript language service host */ @@ -39,6 +43,7 @@ class TypeScriptLanguageServiceHost { return '1'; } getScriptSnapshot(fileName) { + fileName = normalizePath(fileName); if (this.topLevelFiles.has(fileName)) { return this.ts.ScriptSnapshot.fromString(this.topLevelFiles.get(fileName)); } @@ -56,12 +61,14 @@ class TypeScriptLanguageServiceHost { return this.ts.getDefaultLibFilePath(options); } readFile(path, encoding) { + path = normalizePath(path); if (this.topLevelFiles.get(path)) { return this.topLevelFiles.get(path); } return typescript_1.default.sys.readFile(path, encoding); } fileExists(path) { + path = normalizePath(path); if (this.topLevelFiles.has(path)) { return true; } diff --git a/build/lib/typeScriptLanguageServiceHost.ts b/build/lib/typeScriptLanguageServiceHost.ts index faa11d44da3..f3bacd617d5 100644 --- a/build/lib/typeScriptLanguageServiceHost.ts +++ b/build/lib/typeScriptLanguageServiceHost.ts @@ -5,9 +5,14 @@ import ts from 'typescript'; import fs from 'node:fs'; +import { normalize } from 'node:path'; export type IFileMap = Map; +function normalizePath(filePath: string): string { + return normalize(filePath); +} + /** * A TypeScript language service host */ @@ -36,6 +41,8 @@ export class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost { return '1'; } getScriptSnapshot(fileName: string): ts.IScriptSnapshot { + fileName = normalizePath(fileName); + if (this.topLevelFiles.has(fileName)) { return this.ts.ScriptSnapshot.fromString(this.topLevelFiles.get(fileName)!); } else { @@ -52,12 +59,16 @@ export class TypeScriptLanguageServiceHost implements ts.LanguageServiceHost { return this.ts.getDefaultLibFilePath(options); } readFile(path: string, encoding?: string): string | undefined { + path = normalizePath(path); + if (this.topLevelFiles.get(path)) { return this.topLevelFiles.get(path); } return ts.sys.readFile(path, encoding); } fileExists(path: string): boolean { + path = normalizePath(path); + if (this.topLevelFiles.has(path)) { return true; } diff --git a/build/lib/typings/@vscode/gulp-electron.d.ts b/build/lib/typings/@vscode/gulp-electron.d.ts new file mode 100644 index 00000000000..2ae51d77518 --- /dev/null +++ b/build/lib/typings/@vscode/gulp-electron.d.ts @@ -0,0 +1,3 @@ +declare module '@vscode/gulp-electron' { + export default function electron(options: any): NodeJS.ReadWriteStream; +} diff --git a/build/lib/typings/asar.d.ts b/build/lib/typings/asar.d.ts new file mode 100644 index 00000000000..cdb5b6395c5 --- /dev/null +++ b/build/lib/typings/asar.d.ts @@ -0,0 +1,9 @@ +declare module 'asar/lib/filesystem.js' { + + export default class AsarFilesystem { + readonly header: unknown; + constructor(src: string); + insertDirectory(path: string, shouldUnpack?: boolean): unknown; + insertFile(path: string, shouldUnpack: boolean, file: { stat: { size: number; mode: number } }, options: {}): Promise; + } +} diff --git a/build/lib/typings/chromium-pickle-js.d.ts b/build/lib/typings/chromium-pickle-js.d.ts new file mode 100644 index 00000000000..e2fcd8dc096 --- /dev/null +++ b/build/lib/typings/chromium-pickle-js.d.ts @@ -0,0 +1,10 @@ +declare module 'chromium-pickle-js' { + export interface Pickle { + writeString(value: string): void; + writeUInt32(value: number): void; + + toBuffer(): Buffer; + } + + export function createEmpty(): Pickle; +} diff --git a/build/lib/typings/gulp-azure-storage.d.ts b/build/lib/typings/gulp-azure-storage.d.ts new file mode 100644 index 00000000000..4e9f560c8f2 --- /dev/null +++ b/build/lib/typings/gulp-azure-storage.d.ts @@ -0,0 +1,5 @@ +declare module 'gulp-azure-storage' { + import { ThroughStream } from 'event-stream'; + + export function upload(options: any): ThroughStream; +} diff --git a/build/lib/typings/gulp-vinyl-zip.d.ts b/build/lib/typings/gulp-vinyl-zip.d.ts new file mode 100644 index 00000000000..d28166ffa77 --- /dev/null +++ b/build/lib/typings/gulp-vinyl-zip.d.ts @@ -0,0 +1,4 @@ + +declare module 'gulp-vinyl-zip' { + export function src(): NodeJS.ReadWriteStream; +} diff --git a/build/lib/typings/vscode-gulp-watch.d.ts b/build/lib/typings/vscode-gulp-watch.d.ts new file mode 100644 index 00000000000..24316c07f16 --- /dev/null +++ b/build/lib/typings/vscode-gulp-watch.d.ts @@ -0,0 +1,3 @@ +declare module 'vscode-gulp-watch' { + export default function watch(...args: any[]): any; +} diff --git a/build/lib/util.js b/build/lib/util.js index d907b3e6322..9d2f3b13a06 100644 --- a/build/lib/util.js +++ b/build/lib/util.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; @@ -23,10 +27,6 @@ exports.rebase = rebase; exports.filter = filter; exports.streamToPromise = streamToPromise; exports.getElectronVersion = getElectronVersion; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const event_stream_1 = __importDefault(require("event-stream")); const debounce_1 = __importDefault(require("debounce")); const gulp_filter_1 = __importDefault(require("gulp-filter")); diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js index 21dc978dbfc..84b9f96fb97 100644 --- a/build/lib/watch/index.js +++ b/build/lib/watch/index.js @@ -1,11 +1,12 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.default = default_1; const watch = process.platform === 'win32' ? require('./watch-win32') : require('vscode-gulp-watch'); -module.exports = function () { - return watch.apply(null, arguments); -}; +function default_1(...args) { + return watch.apply(null, args); +} //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/lib/watch/index.ts b/build/lib/watch/index.ts index ce4bdfd75ed..c43d3f1f83e 100644 --- a/build/lib/watch/index.ts +++ b/build/lib/watch/index.ts @@ -5,6 +5,6 @@ const watch = process.platform === 'win32' ? require('./watch-win32') : require('vscode-gulp-watch'); -module.exports = function () { - return watch.apply(null, arguments); -}; +export default function (...args: any[]): any { + return watch.apply(null, args); +} diff --git a/build/lib/watch/watch-win32.js b/build/lib/watch/watch-win32.js index 4113d93526e..7b77981d620 100644 --- a/build/lib/watch/watch-win32.js +++ b/build/lib/watch/watch-win32.js @@ -1,12 +1,12 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const child_process_1 = __importDefault(require("child_process")); const fs_1 = __importDefault(require("fs")); diff --git a/build/linux/debian/calculate-deps.js b/build/linux/debian/calculate-deps.js index c9c96967f47..34276ce7705 100644 --- a/build/linux/debian/calculate-deps.js +++ b/build/linux/debian/calculate-deps.js @@ -1,13 +1,13 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generatePackageDeps = generatePackageDeps; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const child_process_1 = require("child_process"); const fs_1 = require("fs"); const os_1 = require("os"); diff --git a/build/linux/debian/dep-lists.js b/build/linux/debian/dep-lists.js index f58d0f8e866..6282d354736 100644 --- a/build/linux/debian/dep-lists.js +++ b/build/linux/debian/dep-lists.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.referenceGeneratedDepsByArch = exports.recommendedDeps = exports.additionalDeps = void 0; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.referenceGeneratedDepsByArch = exports.recommendedDeps = exports.additionalDeps = void 0; // Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/additional_deps // Additional dependencies not in the dpkg-shlibdeps output. exports.additionalDeps = [ @@ -38,7 +38,7 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', @@ -75,7 +75,7 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', @@ -114,7 +114,7 @@ exports.referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', diff --git a/build/linux/debian/dep-lists.ts b/build/linux/debian/dep-lists.ts index 5b7ccd51e09..941501b532c 100644 --- a/build/linux/debian/dep-lists.ts +++ b/build/linux/debian/dep-lists.ts @@ -38,7 +38,7 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', @@ -75,7 +75,7 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', @@ -114,7 +114,7 @@ export const referenceGeneratedDepsByArch = { 'libdbus-1-3 (>= 1.9.14)', 'libexpat1 (>= 2.1~beta3)', 'libgbm1 (>= 17.1.0~rc2)', - 'libglib2.0-0 (>= 2.37.3)', + 'libglib2.0-0 (>= 2.39.4)', 'libgtk-3-0 (>= 3.9.10)', 'libgtk-3-0 (>= 3.9.10) | libgtk-4-1', 'libnspr4 (>= 2:4.9-2~)', diff --git a/build/linux/debian/install-sysroot.js b/build/linux/debian/install-sysroot.js index 1134130d780..4a9a46e6bd6 100644 --- a/build/linux/debian/install-sysroot.js +++ b/build/linux/debian/install-sysroot.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getVSCodeSysroot = getVSCodeSysroot; exports.getChromiumSysroot = getChromiumSysroot; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ const child_process_1 = require("child_process"); const os_1 = require("os"); const fs_1 = __importDefault(require("fs")); diff --git a/build/linux/debian/types.js b/build/linux/debian/types.js index f2a80aebb7a..ce21d50e1a9 100644 --- a/build/linux/debian/types.js +++ b/build/linux/debian/types.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.isDebianArchString = isDebianArchString; function isDebianArchString(s) { diff --git a/build/linux/dependencies-generator.js b/build/linux/dependencies-generator.js index ae05d175da8..2fb859fa51d 100644 --- a/build/linux/dependencies-generator.js +++ b/build/linux/dependencies-generator.js @@ -26,7 +26,7 @@ const product = require("../../product.json"); // The reference dependencies, which one has to update when the new dependencies // are valid, are in dep-lists.ts const FAIL_BUILD_FOR_NEW_DEPENDENCIES = true; -// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/138.0.7204.251:chrome/installer/linux/BUILD.gn;l=64-80 +// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/142.0.7444.162:chrome/installer/linux/BUILD.gn;l=64-80 // and the Linux Archive build // Shared library dependencies that we already bundle. const bundledDeps = [ diff --git a/build/linux/dependencies-generator.ts b/build/linux/dependencies-generator.ts index 46c6d6c099a..abb01b9e49d 100644 --- a/build/linux/dependencies-generator.ts +++ b/build/linux/dependencies-generator.ts @@ -25,7 +25,7 @@ import product = require('../../product.json'); // are valid, are in dep-lists.ts const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true; -// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/138.0.7204.251:chrome/installer/linux/BUILD.gn;l=64-80 +// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/142.0.7444.162:chrome/installer/linux/BUILD.gn;l=64-80 // and the Linux Archive build // Shared library dependencies that we already bundle. const bundledDeps = [ diff --git a/build/linux/libcxx-fetcher.js b/build/linux/libcxx-fetcher.js index 710a8be7434..d6c998e5aea 100644 --- a/build/linux/libcxx-fetcher.js +++ b/build/linux/libcxx-fetcher.js @@ -1,14 +1,14 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadLibcxxHeaders = downloadLibcxxHeaders; exports.downloadLibcxxObjects = downloadLibcxxObjects; -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ // Can be removed once https://github.com/electron/electron-rebuild/pull/703 is available. const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); diff --git a/build/linux/rpm/calculate-deps.js b/build/linux/rpm/calculate-deps.js index b31a5aa9d5c..b19e26f1854 100644 --- a/build/linux/rpm/calculate-deps.js +++ b/build/linux/rpm/calculate-deps.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.generatePackageDeps = generatePackageDeps; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generatePackageDeps = generatePackageDeps; const child_process_1 = require("child_process"); const fs_1 = require("fs"); const dep_lists_1 = require("./dep-lists"); diff --git a/build/linux/rpm/dep-lists.js b/build/linux/rpm/dep-lists.js index 74156ebe47a..1bbef8a3261 100644 --- a/build/linux/rpm/dep-lists.js +++ b/build/linux/rpm/dep-lists.js @@ -1,10 +1,10 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.referenceGeneratedDepsByArch = exports.additionalDeps = void 0; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.referenceGeneratedDepsByArch = exports.additionalDeps = void 0; // Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/rpm/additional_deps // Additional dependencies not in the rpm find-requires output. exports.additionalDeps = [ @@ -257,7 +257,6 @@ exports.referenceGeneratedDepsByArch = { 'libgcc_s.so.1()(64bit)', 'libgcc_s.so.1(GCC_3.0)(64bit)', 'libgcc_s.so.1(GCC_3.3)(64bit)', - 'libgcc_s.so.1(GCC_4.0.0)(64bit)', 'libgcc_s.so.1(GCC_4.2.0)(64bit)', 'libgcc_s.so.1(GCC_4.5.0)(64bit)', 'libgio-2.0.so.0()(64bit)', diff --git a/build/linux/rpm/dep-lists.ts b/build/linux/rpm/dep-lists.ts index 90b97bed301..783923f34d9 100644 --- a/build/linux/rpm/dep-lists.ts +++ b/build/linux/rpm/dep-lists.ts @@ -256,7 +256,6 @@ export const referenceGeneratedDepsByArch = { 'libgcc_s.so.1()(64bit)', 'libgcc_s.so.1(GCC_3.0)(64bit)', 'libgcc_s.so.1(GCC_3.3)(64bit)', - 'libgcc_s.so.1(GCC_4.0.0)(64bit)', 'libgcc_s.so.1(GCC_4.2.0)(64bit)', 'libgcc_s.so.1(GCC_4.5.0)(64bit)', 'libgio-2.0.so.0()(64bit)', diff --git a/build/linux/rpm/types.js b/build/linux/rpm/types.js index 39b1334cc7b..a20b9c2fe02 100644 --- a/build/linux/rpm/types.js +++ b/build/linux/rpm/types.js @@ -1,4 +1,8 @@ "use strict"; +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.isRpmArchString = isRpmArchString; function isRpmArchString(s) { diff --git a/src/vscode-dts/vscode.proposed.contribSecondarySidebar.d.ts b/build/monaco-editor-playground/index-workbench.ts similarity index 81% rename from src/vscode-dts/vscode.proposed.contribSecondarySidebar.d.ts rename to build/monaco-editor-playground/index-workbench.ts index 2bdbedd01b2..2f63c6b4c6e 100644 --- a/src/vscode-dts/vscode.proposed.contribSecondarySidebar.d.ts +++ b/build/monaco-editor-playground/index-workbench.ts @@ -3,4 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -// empty placeholder declaration for the `secondarySidebar`-contribution point +import './setup-dev'; +import '../../src/vs/code/browser/workbench/workbench'; + diff --git a/build/monaco-editor-playground/index.html b/build/monaco-editor-playground/index.html new file mode 100644 index 00000000000..c3a0e36b8ef --- /dev/null +++ b/build/monaco-editor-playground/index.html @@ -0,0 +1,9 @@ + + + + +
+

Use the Playground Launch Config for a better dev experience

+ + + diff --git a/build/monaco-editor-playground/index.ts b/build/monaco-editor-playground/index.ts new file mode 100644 index 00000000000..b852612bc66 --- /dev/null +++ b/build/monaco-editor-playground/index.ts @@ -0,0 +1,22 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// +/* eslint-disable local/code-no-standalone-editor */ + +export * from '../../src/vs/editor/editor.main'; +import './style.css'; +import * as monaco from '../../src/vs/editor/editor.main'; + +globalThis.monaco = monaco; +const root = document.getElementById('sampleContent'); +if (root) { + const d = monaco.editor.createDiffEditor(root); + + d.setModel({ + modified: monaco.editor.createModel(`hello world`), + original: monaco.editor.createModel(`hello monaco`), + }); +} diff --git a/build/monaco-editor-playground/package-lock.json b/build/monaco-editor-playground/package-lock.json new file mode 100644 index 00000000000..4fd63116305 --- /dev/null +++ b/build/monaco-editor-playground/package-lock.json @@ -0,0 +1,1043 @@ +{ + "name": "@vscode/sample-source", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@vscode/sample-source", + "version": "0.0.0", + "devDependencies": { + "vite": "^7.1.11" + } + }, + "../lib": { + "name": "monaco-editor-core", + "version": "0.0.0", + "extraneous": true, + "license": "MIT", + "dependencies": { + "postcss-copy": "^7.1.0", + "postcss-copy-assets": "^0.3.1", + "rollup": "^4.35.0", + "rollup-plugin-esbuild": "^6.2.1", + "rollup-plugin-lib-style": "^2.3.2", + "rollup-plugin-postcss": "^4.0.2" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz", + "integrity": "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz", + "integrity": "sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz", + "integrity": "sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz", + "integrity": "sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz", + "integrity": "sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz", + "integrity": "sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz", + "integrity": "sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz", + "integrity": "sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz", + "integrity": "sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz", + "integrity": "sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz", + "integrity": "sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz", + "integrity": "sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz", + "integrity": "sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz", + "integrity": "sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz", + "integrity": "sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz", + "integrity": "sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz", + "integrity": "sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz", + "integrity": "sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz", + "integrity": "sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz", + "integrity": "sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/rollup": { + "version": "4.49.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.49.0.tgz", + "integrity": "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.49.0", + "@rollup/rollup-android-arm64": "4.49.0", + "@rollup/rollup-darwin-arm64": "4.49.0", + "@rollup/rollup-darwin-x64": "4.49.0", + "@rollup/rollup-freebsd-arm64": "4.49.0", + "@rollup/rollup-freebsd-x64": "4.49.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", + "@rollup/rollup-linux-arm-musleabihf": "4.49.0", + "@rollup/rollup-linux-arm64-gnu": "4.49.0", + "@rollup/rollup-linux-arm64-musl": "4.49.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", + "@rollup/rollup-linux-ppc64-gnu": "4.49.0", + "@rollup/rollup-linux-riscv64-gnu": "4.49.0", + "@rollup/rollup-linux-riscv64-musl": "4.49.0", + "@rollup/rollup-linux-s390x-gnu": "4.49.0", + "@rollup/rollup-linux-x64-gnu": "4.49.0", + "@rollup/rollup-linux-x64-musl": "4.49.0", + "@rollup/rollup-win32-arm64-msvc": "4.49.0", + "@rollup/rollup-win32-ia32-msvc": "4.49.0", + "@rollup/rollup-win32-x64-msvc": "4.49.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/vite": { + "version": "7.1.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + } + } +} diff --git a/build/monaco-editor-playground/package.json b/build/monaco-editor-playground/package.json new file mode 100644 index 00000000000..ea7b609e280 --- /dev/null +++ b/build/monaco-editor-playground/package.json @@ -0,0 +1,14 @@ +{ + "name": "@vscode/sample-source", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "vite": "^7.1.11" + } +} diff --git a/build/monaco-editor-playground/rollup-url-to-module-plugin/index.mjs b/build/monaco-editor-playground/rollup-url-to-module-plugin/index.mjs new file mode 100644 index 00000000000..8a0168bd4ac --- /dev/null +++ b/build/monaco-editor-playground/rollup-url-to-module-plugin/index.mjs @@ -0,0 +1,63 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * @type {() => import('rollup').Plugin} +*/ +export function urlToEsmPlugin() { + return { + name: 'import-meta-url', + async transform(code, id) { + if (this.environment?.mode === 'dev') { + return; + } + + // Look for `new URL(..., import.meta.url)` patterns. + const regex = /new\s+URL\s*\(\s*(['"`])(.*?)\1\s*,\s*import\.meta\.url\s*\)?/g; + + let match; + let modified = false; + let result = code; + let offset = 0; + + while ((match = regex.exec(code)) !== null) { + let path = match[2]; + + if (!path.startsWith('.') && !path.startsWith('/')) { + path = `./${path}`; + } + const resolved = await this.resolve(path, id); + + if (!resolved) { + continue; + } + + // Add the file as an entry point + const refId = this.emitFile({ + type: 'chunk', + id: resolved.id, + }); + + const start = match.index; + const end = start + match[0].length; + + const replacement = `import.meta.ROLLUP_FILE_URL_OBJ_${refId}`; + + result = result.slice(0, start + offset) + replacement + result.slice(end + offset); + offset += replacement.length - (end - start); + modified = true; + } + + if (!modified) { + return null; + } + + return { + code: result, + map: null + }; + } + }; +} diff --git a/build/monaco-editor-playground/setup-dev.ts b/build/monaco-editor-playground/setup-dev.ts new file mode 100644 index 00000000000..87505545b71 --- /dev/null +++ b/build/monaco-editor-playground/setup-dev.ts @@ -0,0 +1,15 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/// + +import { enableHotReload } from '../../src/vs/base/common/hotReload.ts'; +import { InstantiationType, registerSingleton } from '../../src/vs/platform/instantiation/common/extensions.ts'; +import { IWebWorkerService } from '../../src/vs/platform/webWorker/browser/webWorkerService.ts'; +// eslint-disable-next-line local/code-no-standalone-editor +import { StandaloneWebWorkerService } from '../../src/vs/editor/standalone/browser/services/standaloneWebWorkerService.ts'; + +enableHotReload(); +registerSingleton(IWebWorkerService, StandaloneWebWorkerService, InstantiationType.Eager); diff --git a/gulpfile.js b/build/monaco-editor-playground/style.css similarity index 74% rename from gulpfile.js rename to build/monaco-editor-playground/style.css index 4dce0234239..b9573061e51 100644 --- a/gulpfile.js +++ b/build/monaco-editor-playground/style.css @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { createRequire } from 'node:module'; - -const require = createRequire(import.meta.url); -require('./build/gulpfile'); +#sampleContent { + height: 400px; + border: 1px solid black; +} diff --git a/build/monaco-editor-playground/tsconfig.json b/build/monaco-editor-playground/tsconfig.json new file mode 100644 index 00000000000..454dc14491f --- /dev/null +++ b/build/monaco-editor-playground/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "allowImportingTsExtensions": true, + "noEmit": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "experimentalDecorators": true, + }, + "include": ["**/*.ts"] +} diff --git a/build/monaco-editor-playground/vite.config.ts b/build/monaco-editor-playground/vite.config.ts new file mode 100644 index 00000000000..ac1536cf578 --- /dev/null +++ b/build/monaco-editor-playground/vite.config.ts @@ -0,0 +1,139 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { defineConfig, Plugin } from 'vite'; +import path, { join } from 'path'; +/// @ts-ignore +import { urlToEsmPlugin } from './rollup-url-to-module-plugin/index.mjs'; +import { statSync } from 'fs'; +import { pathToFileURL } from 'url'; + +function injectBuiltinExtensionsPlugin(): Plugin { + let builtinExtensionsCache: unknown[] | null = null; + + function replaceAllOccurrences(str: string, search: string, replace: string): string { + return str.split(search).join(replace); + } + + async function loadBuiltinExtensions() { + if (!builtinExtensionsCache) { + builtinExtensionsCache = await getScannedBuiltinExtensions(path.resolve(__dirname, '../../')); + console.log(`Found ${builtinExtensionsCache!.length} built-in extensions.`); + } + return builtinExtensionsCache; + } + + function asJSON(value: unknown): string { + return escapeHtmlByReplacingCharacters(JSON.stringify(value)); + } + + function escapeHtmlByReplacingCharacters(str: string) { + if (typeof str !== 'string') { + return ''; + } + + const escapeCharacter = (match: string) => { + switch (match) { + case '&': return '&'; + case '<': return '<'; + case '>': return '>'; + case '"': return '"'; + case '\'': return '''; + case '`': return '`'; + default: return match; + } + }; + + return str.replace(/[&<>"'`]/g, escapeCharacter); + } + + const prebuiltExtensionsLocation = '.build/builtInExtensions'; + async function getScannedBuiltinExtensions(vsCodeDevLocation: string) { + // use the build utility as to not duplicate the code + const extensionsUtil = await import(pathToFileURL(path.join(vsCodeDevLocation, 'build', 'lib', 'extensions.js')).toString()); + const localExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, 'extensions')); + const prebuiltExtensions = extensionsUtil.scanBuiltinExtensions(path.join(vsCodeDevLocation, prebuiltExtensionsLocation)); + for (const ext of localExtensions) { + let browserMain = ext.packageJSON.browser; + if (browserMain) { + if (!browserMain.endsWith('.js')) { + browserMain = browserMain + '.js'; + } + const browserMainLocation = path.join(vsCodeDevLocation, 'extensions', ext.extensionPath, browserMain); + if (!fileExists(browserMainLocation)) { + console.log(`${browserMainLocation} not found. Make sure all extensions are compiled (use 'yarn watch-web').`); + } + } + } + return localExtensions.concat(prebuiltExtensions); + } + + function fileExists(path: string): boolean { + try { + return statSync(path).isFile(); + } catch (err) { + return false; + } + } + + return { + name: 'inject-builtin-extensions', + transformIndexHtml: { + order: 'pre', + async handler(html) { + const search = '{{WORKBENCH_BUILTIN_EXTENSIONS}}'; + if (html.indexOf(search) === -1) { + return html; + } + + const extensions = await loadBuiltinExtensions(); + const h = replaceAllOccurrences(html, search, asJSON(extensions)); + return h; + } + } + }; +} + +function createHotClassSupport(): Plugin { + return { + name: 'createHotClassSupport', + transform(code, id) { + if (id.endsWith('.ts')) { + if (code.includes('createHotClass')) { + code = code + `\n +if (import.meta.hot) { + import.meta.hot.accept(); +}`; + } + return code; + } + return undefined; + }, + }; +} + +export default defineConfig({ + plugins: [ + urlToEsmPlugin(), + injectBuiltinExtensionsPlugin(), + createHotClassSupport() + ], + esbuild: { + target: 'es6', // to fix property initialization issues, not needed when loading monaco-editor from npm package + }, + root: '../..', // To support /out/... paths + server: { + cors: true, + port: 5199, + origin: 'http://localhost:5199', + fs: { + allow: [ + // To allow loading from sources, not needed when loading monaco-editor from npm package + /// @ts-ignore + join(import.meta.dirname, '../../../') + ] + } + } +}); diff --git a/build/monaco-editor-playground/workbench-vite.html b/build/monaco-editor-playground/workbench-vite.html new file mode 100644 index 00000000000..99ed4e75415 --- /dev/null +++ b/build/monaco-editor-playground/workbench-vite.html @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/build/npm/dirs.js b/build/npm/dirs.js index 4965b73c4ed..935d8a8a529 100644 --- a/build/npm/dirs.js +++ b/build/npm/dirs.js @@ -9,6 +9,7 @@ const fs = require('fs'); const dirs = [ '', 'build', + 'build/monaco-editor-playground', 'extensions', 'extensions/configuration-editing', 'extensions/css-language-features', diff --git a/build/npm/gyp/custom-headers/v8-source-location.patch b/build/npm/gyp/custom-headers/v8-source-location.patch new file mode 100644 index 00000000000..545eb9a118b --- /dev/null +++ b/build/npm/gyp/custom-headers/v8-source-location.patch @@ -0,0 +1,94 @@ +--- v8-source-location.h 2025-10-28 05:57:35 ++++ v8-source-location.h 2025-11-07 03:10:02 +@@ -6,12 +6,21 @@ + #define INCLUDE_SOURCE_LOCATION_H_ + + #include +-#include + #include + + #include "v8config.h" // NOLINT(build/include_directory) + ++#if defined(__has_builtin) ++#define V8_SUPPORTS_SOURCE_LOCATION \ ++ (__has_builtin(__builtin_FUNCTION) && __has_builtin(__builtin_FILE) && \ ++ __has_builtin(__builtin_LINE)) // NOLINT ++#elif defined(V8_CC_GNU) && __GNUC__ >= 7 + #define V8_SUPPORTS_SOURCE_LOCATION 1 ++#elif defined(V8_CC_INTEL) && __ICC >= 1800 ++#define V8_SUPPORTS_SOURCE_LOCATION 1 ++#else ++#define V8_SUPPORTS_SOURCE_LOCATION 0 ++#endif + + namespace v8 { + +@@ -25,10 +34,15 @@ + * Construct source location information corresponding to the location of the + * call site. + */ ++#if V8_SUPPORTS_SOURCE_LOCATION + static constexpr SourceLocation Current( +- const std::source_location& loc = std::source_location::current()) { +- return SourceLocation(loc); ++ const char* function = __builtin_FUNCTION(), ++ const char* file = __builtin_FILE(), size_t line = __builtin_LINE()) { ++ return SourceLocation(function, file, line); + } ++#else ++ static constexpr SourceLocation Current() { return SourceLocation(); } ++#endif // V8_SUPPORTS_SOURCE_LOCATION + #ifdef DEBUG + static constexpr SourceLocation CurrentIfDebug( + const std::source_location& loc = std::source_location::current()) { +@@ -49,21 +63,21 @@ + * + * \returns the function name as cstring. + */ +- constexpr const char* Function() const { return loc_.function_name(); } ++ constexpr const char* Function() const { return function_; } + + /** + * Returns the name of the current source file represented by this object. + * + * \returns the file name as cstring. + */ +- constexpr const char* FileName() const { return loc_.file_name(); } ++ constexpr const char* FileName() const { return file_; } + + /** + * Returns the line number represented by this object. + * + * \returns the line number. + */ +- constexpr size_t Line() const { return loc_.line(); } ++ constexpr size_t Line() const { return line_; } + + /** + * Returns a human-readable string representing this object. +@@ -71,18 +85,19 @@ + * \returns a human-readable string representing source location information. + */ + std::string ToString() const { +- if (loc_.line() == 0) { ++ if (!file_) { + return {}; + } +- return std::string(loc_.function_name()) + "@" + loc_.file_name() + ":" + +- std::to_string(loc_.line()); ++ return std::string(function_) + "@" + file_ + ":" + std::to_string(line_); + } + + private: +- constexpr explicit SourceLocation(const std::source_location& loc) +- : loc_(loc) {} ++ constexpr SourceLocation(const char* function, const char* file, size_t line) ++ : function_(function), file_(file), line_(line) {} + +- std::source_location loc_; ++ const char* function_ = nullptr; ++ const char* file_ = nullptr; ++ size_t line_ = 0u; + }; + + } // namespace v8 diff --git a/build/npm/preinstall.js b/build/npm/preinstall.js index e4b47859576..79ce65dfd9a 100644 --- a/build/npm/preinstall.js +++ b/build/npm/preinstall.js @@ -2,26 +2,44 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -const nodeVersion = /^(\d+)\.(\d+)\.(\d+)/.exec(process.versions.node); -const majorNodeVersion = parseInt(nodeVersion[1]); -const minorNodeVersion = parseInt(nodeVersion[2]); -const patchNodeVersion = parseInt(nodeVersion[3]); +// @ts-check +const path = require('path'); +const fs = require('fs'); if (!process.env['VSCODE_SKIP_NODE_VERSION_CHECK']) { - if (majorNodeVersion < 22 || (majorNodeVersion === 22 && minorNodeVersion < 15) || (majorNodeVersion === 22 && minorNodeVersion === 15 && patchNodeVersion < 1)) { - console.error('\x1b[1;31m*** Please use Node.js v22.15.1 or later for development.\x1b[0;0m'); + // Get the running Node.js version + const nodeVersion = /^(\d+)\.(\d+)\.(\d+)/.exec(process.versions.node); + const majorNodeVersion = parseInt(nodeVersion[1]); + const minorNodeVersion = parseInt(nodeVersion[2]); + const patchNodeVersion = parseInt(nodeVersion[3]); + + // Get the required Node.js version from .nvmrc + const nvmrcPath = path.join(__dirname, '..', '..', '.nvmrc'); + const requiredVersion = fs.readFileSync(nvmrcPath, 'utf8').trim(); + const requiredVersionMatch = /^(\d+)\.(\d+)\.(\d+)/.exec(requiredVersion); + + if (!requiredVersionMatch) { + console.error('\x1b[1;31m*** Unable to parse required Node.js version from .nvmrc\x1b[0;0m'); + throw new Error(); + } + + const requiredMajor = parseInt(requiredVersionMatch[1]); + const requiredMinor = parseInt(requiredVersionMatch[2]); + const requiredPatch = parseInt(requiredVersionMatch[3]); + + if (majorNodeVersion < requiredMajor || + (majorNodeVersion === requiredMajor && minorNodeVersion < requiredMinor) || + (majorNodeVersion === requiredMajor && minorNodeVersion === requiredMinor && patchNodeVersion < requiredPatch)) { + console.error(`\x1b[1;31m*** Please use Node.js v${requiredVersion} or later for development. Currently using v${process.versions.node}.\x1b[0;0m`); throw new Error(); } } -if (process.env['npm_execpath'].includes('yarn')) { +if (process.env.npm_execpath?.includes('yarn')) { console.error('\x1b[1;31m*** Seems like you are using `yarn` which is not supported in this repo any more, please use `npm i` instead. ***\x1b[0;0m'); throw new Error(); } -const path = require('path'); -const fs = require('fs'); const cp = require('child_process'); const os = require('os'); @@ -32,9 +50,10 @@ if (process.platform === 'win32') { console.error('\x1b[1;31m*** set vs2022_install= (or vs2019_install for older versions)\x1b[0;0m'); throw new Error(); } - installHeaders(); } +installHeaders(); + if (process.arch !== os.arch()) { console.error(`\x1b[1;31m*** ARCHITECTURE MISMATCH: The node.js process is ${process.arch}, but your OS architecture is ${os.arch()}. ***\x1b[0;0m`); console.error(`\x1b[1;31m*** This can greatly increase the build time of vs code. ***\x1b[0;0m`); @@ -82,31 +101,52 @@ function hasSupportedVisualStudioVersion() { } function installHeaders() { - cp.execSync(`npm.cmd ${process.env['npm_command'] || 'ci'}`, { + const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'; + cp.execSync(`${npm} ${process.env.npm_command || 'ci'}`, { env: process.env, cwd: path.join(__dirname, 'gyp'), stdio: 'inherit' }); // The node gyp package got installed using the above npm command using the gyp/package.json - // file checked into our repository. So from that point it is save to construct the path + // file checked into our repository. So from that point it is safe to construct the path // to that executable - const node_gyp = path.join(__dirname, 'gyp', 'node_modules', '.bin', 'node-gyp.cmd'); - const result = cp.execFileSync(node_gyp, ['list'], { encoding: 'utf8', shell: true }); - const versions = new Set(result.split(/\n/g).filter(line => !line.startsWith('gyp info')).map(value => value)); + const node_gyp = process.platform === 'win32' + ? path.join(__dirname, 'gyp', 'node_modules', '.bin', 'node-gyp.cmd') + : path.join(__dirname, 'gyp', 'node_modules', '.bin', 'node-gyp'); const local = getHeaderInfo(path.join(__dirname, '..', '..', '.npmrc')); const remote = getHeaderInfo(path.join(__dirname, '..', '..', 'remote', '.npmrc')); - if (local !== undefined && !versions.has(local.target)) { + if (local !== undefined) { // Both disturl and target come from a file checked into our repository cp.execFileSync(node_gyp, ['install', '--dist-url', local.disturl, local.target], { shell: true }); } - if (remote !== undefined && !versions.has(remote.target)) { + if (remote !== undefined) { // Both disturl and target come from a file checked into our repository cp.execFileSync(node_gyp, ['install', '--dist-url', remote.disturl, remote.target], { shell: true }); } + + // On Linux, apply a patch to the downloaded headers + // Remove dependency on std::source_location to avoid bumping the required GCC version to 11+ + // Refs https://chromium-review.googlesource.com/c/v8/v8/+/6879784 + if (process.platform === 'linux') { + const homedir = os.homedir(); + const cachePath = process.env.XDG_CACHE_HOME || path.join(homedir, '.cache'); + const nodeGypCache = path.join(cachePath, 'node-gyp'); + const localHeaderPath = path.join(nodeGypCache, local.target, 'include', 'node'); + if (fs.existsSync(localHeaderPath)) { + console.log('Applying v8-source-location.patch to', localHeaderPath); + try { + cp.execFileSync('patch', ['-p0', '-i', path.join(__dirname, 'gyp', 'custom-headers', 'v8-source-location.patch')], { + cwd: localHeaderPath + }); + } catch (error) { + throw new Error(`Error applying v8-source-location.patch: ${error.message}`); + }; + } + } } /** @@ -114,7 +154,7 @@ function installHeaders() { * @returns {{ disturl: string; target: string } | undefined} */ function getHeaderInfo(rcFile) { - const lines = fs.readFileSync(rcFile, 'utf8').split(/\r\n?/g); + const lines = fs.readFileSync(rcFile, 'utf8').split(/\r\n|\n/g); let disturl, target; for (const line of lines) { let match = line.match(/\s*disturl=*\"(.*)\"\s*$/); diff --git a/build/package-lock.json b/build/package-lock.json index 9faa5f88112..29af501c705 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -38,7 +38,7 @@ "@types/mime": "0.0.29", "@types/minimatch": "^3.0.3", "@types/minimist": "^1.2.1", - "@types/node": "22.x", + "@types/node": "^22.18.10", "@types/p-all": "^1.0.0", "@types/pump": "^1.0.1", "@types/rimraf": "^2.0.4", @@ -47,7 +47,7 @@ "@types/vinyl": "^2.0.12", "@types/workerpool": "^6.4.0", "@types/xml2js": "0.0.33", - "@vscode/iconv-lite-umd": "0.7.0", + "@vscode/iconv-lite-umd": "0.7.1", "@vscode/ripgrep": "^1.15.13", "@vscode/vsce": "3.6.1", "ansi-colors": "^3.2.3", @@ -1781,13 +1781,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "version": "22.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.13.tgz", + "integrity": "sha512-Bo45YKIjnmFtv6I1TuC8AaHBbqXtIo+Om5fE4QiU1Tj8QR/qt+8O3BAtOimG5IFmwaWiPmB3Mv3jtYzBA4Us2A==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/normalize-package-data": { @@ -1923,10 +1923,11 @@ } }, "node_modules/@vscode/iconv-lite-umd": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz", - "integrity": "sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==", - "dev": true + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.1.tgz", + "integrity": "sha512-tK6k0DXFHW7q5+GGuGZO+phpAqpxO4WXl+BLc/8/uOk3RsM2ssAL3CQUQDb1TGfwltjsauhN6S4ghYZzs4sPFw==", + "dev": true, + "license": "MIT" }, "node_modules/@vscode/ripgrep": { "version": "1.15.14", @@ -6517,9 +6518,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, diff --git a/build/package.json b/build/package.json index 2ea36955282..0948204b038 100644 --- a/build/package.json +++ b/build/package.json @@ -32,7 +32,7 @@ "@types/mime": "0.0.29", "@types/minimatch": "^3.0.3", "@types/minimist": "^1.2.1", - "@types/node": "22.x", + "@types/node": "^22.18.10", "@types/p-all": "^1.0.0", "@types/pump": "^1.0.1", "@types/rimraf": "^2.0.4", @@ -41,7 +41,7 @@ "@types/vinyl": "^2.0.12", "@types/workerpool": "^6.4.0", "@types/xml2js": "0.0.33", - "@vscode/iconv-lite-umd": "0.7.0", + "@vscode/iconv-lite-umd": "0.7.1", "@vscode/ripgrep": "^1.15.13", "@vscode/vsce": "3.6.1", "ansi-colors": "^3.2.3", @@ -64,9 +64,13 @@ }, "type": "commonjs", "scripts": { - "compile": "cd .. && npx tsgo --project build/tsconfig.build.json", - "watch": "cd .. && npx tsgo --project build/tsconfig.build.json --watch", - "npmCheckJs": "cd .. && npx tsgo --project build/tsconfig.build.json --noEmit" + "copy-policy-dto": "node lib/policies/copyPolicyDto.js", + "prebuild-ts": "npm run copy-policy-dto", + "build-ts": "cd .. && npx tsgo --project build/tsconfig.build.json", + "compile": "npm run build-ts", + "watch": "npm run build-ts -- --watch", + "npmCheckJs": "npm run build-ts -- --noEmit", + "test": "npx mocha --ui tdd 'lib/**/*.test.js'" }, "optionalDependencies": { "tree-sitter-typescript": "^0.23.2", diff --git a/build/stylelint.js b/build/stylelint.mjs similarity index 84% rename from build/stylelint.js rename to build/stylelint.mjs index c2f0e4482a2..767fa28c2fe 100644 --- a/build/stylelint.js +++ b/build/stylelint.mjs @@ -4,19 +4,17 @@ *--------------------------------------------------------------------------------------------*/ // @ts-check -const es = require('event-stream'); -const vfs = require('vinyl-fs'); -const { stylelintFilter } = require('./filters'); -const { getVariableNameValidator } = require('./lib/stylelint/validateVariableNames'); - -module.exports = gulpstylelint; +import es from 'event-stream'; +import vfs from 'vinyl-fs'; +import { stylelintFilter } from './filters.js'; +import { getVariableNameValidator } from './lib/stylelint/validateVariableNames.js'; /** * use regex on lines * * @param {function(string, boolean):void} reporter */ -function gulpstylelint(reporter) { +export default function gulpstylelint(reporter) { const variableValidator = getVariableNameValidator(); let errorCount = 0; const monacoWorkbenchPattern = /\.monaco-workbench/; @@ -68,7 +66,8 @@ function stylelint() { .pipe(es.through(function () { /* noop, important for the stream to end */ })); } -if (require.main === module) { +const normalizeScriptPath = (/** @type {string} */ p) => p.replace(/\.(js|ts)$/, ''); +if (normalizeScriptPath(import.meta.filename) === normalizeScriptPath(process.argv[1])) { stylelint().on('error', (err) => { console.error(); console.error(err); diff --git a/build/tsconfig.json b/build/tsconfig.json index ab72dda392a..a3cf3fbe89d 100644 --- a/build/tsconfig.json +++ b/build/tsconfig.json @@ -24,9 +24,11 @@ }, "include": [ "**/*.ts", - "**/*.js" + "**/*.js", + "**/*.mjs", ], "exclude": [ - "node_modules/**" + "node_modules/**", + "monaco-editor-playground/**" ] } diff --git a/build/win32/code.iss b/build/win32/code.iss index a1847c512ec..a67faad1726 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -279,7 +279,7 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.cls\s Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.code-workspace\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.code-workspace\OpenWithProgids"; ValueType: string; ValueName: "{#RegValueName}.code-workspace"; ValueData: ""; Flags: uninsdeletevalue; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code-workspace"; ValueType: string; ValueName: ""; ValueData: "{cm:SourceFile,Code Workspace}"; Flags: uninsdeletekey; Tasks: associatewithfiles -Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles +Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code-workspace"; ValueType: string; ValueName: "AppUserModelID"; ValueData: "{#AppUserId}"; Flags: uninsdeletekey; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code-workspace\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\resources\app\resources\win32\default.ico"; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code-workspace\shell\open"; ValueType: string; ValueName: "Icon"; ValueData: """{app}\{#ExeBasename}.exe"""; Tasks: associatewithfiles Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\{#RegValueName}.code-workspace\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#ExeBasename}.exe"" ""%1"""; Tasks: associatewithfiles diff --git a/cglicenses.json b/cglicenses.json index 93e5297c9a8..8ee75c0fb34 100644 --- a/cglicenses.json +++ b/cglicenses.json @@ -70,7 +70,7 @@ }, { // Reason: The license cannot be found by the tool due to access controls on the repository - "name": "tas-client-umd", + "name": "tas-client", "fullLicenseText": [ "MIT License", "Copyright (c) 2020 - present Microsoft Corporation", diff --git a/cgmanifest.json b/cgmanifest.json index 199532ab318..130be96d127 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "54008792bf952b599e1a7416663711f6a07c8ce3" + "commitHash": "c076baf266c3ed5efb225de664cfa7b183668ad6" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "138.0.7204.251" + "version": "142.0.7444.162" }, { "component": { @@ -516,12 +516,12 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "f8fe6858549f75a4b4e9633abf39dd2038dbf496", - "tag": "22.19.0" + "commitHash": "6ac4ab19ad02803f03b54501193397563e99988e", + "tag": "22.21.1" } }, "isOnlyProductionDependency": true, - "version": "22.19.0" + "version": "22.21.1" }, { "component": { @@ -529,13 +529,13 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "9a2b4f84be2f4bcc468a63ef93520e60790b8f3c", - "tag": "37.6.0" + "commitHash": "ab85f2c2f72be1d1bb44046a0ad98ca28bdd8178", + "tag": "39.2.0" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "37.6.0" + "version": "39.2.0" }, { "component": { @@ -602,11 +602,11 @@ "git": { "name": "vscode-codicons", "repositoryUrl": "https://github.com/microsoft/vscode-codicons", - "commitHash": "ccdcf91d57d3a5a1d6b620d95d518bab4d75984d" + "commitHash": "906a02039fe8d29721f3eec1e46406be8c4bee39" } }, "license": "MIT and Creative Commons Attribution 4.0", - "version": "0.0.14" + "version": "0.0.41" }, { "component": { diff --git a/cli/ThirdPartyNotices.txt b/cli/ThirdPartyNotices.txt index 5e2b97f5823..5ca10211210 100644 --- a/cli/ThirdPartyNotices.txt +++ b/cli/ThirdPartyNotices.txt @@ -5404,7 +5404,7 @@ OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- openssl 0.10.72 - Apache-2.0 -https://github.com/sfackler/rust-openssl +https://github.com/rust-openssl/rust-openssl Copyright 2011-2017 Google Inc. 2013 Jack Lloyd @@ -5483,7 +5483,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- openssl-sys 0.9.107 - MIT -https://github.com/sfackler/rust-openssl +https://github.com/rust-openssl/rust-openssl The MIT License (MIT) @@ -8592,6 +8592,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [//]: # (crates) [`ascon‑hash`]: ./ascon-hash +[`bash‑hash`]: ./bash-hash [`belt‑hash`]: ./belt-hash [`blake2`]: ./blake2 [`fsb`]: ./fsb @@ -8635,6 +8636,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [//]: # (algorithms) [Ascon]: https://ascon.iaik.tugraz.at +[Bash]: https://apmi.bsu.by/assets/files/std/bash-spec241.pdf [BelT]: https://ru.wikipedia.org/wiki/BelT [BLAKE2]: https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2 [FSB]: https://en.wikipedia.org/wiki/Fast_syndrome-based_hash @@ -8686,6 +8688,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [//]: # (crates) [`ascon‑hash`]: ./ascon-hash +[`bash‑hash`]: ./bash-hash [`belt‑hash`]: ./belt-hash [`blake2`]: ./blake2 [`fsb`]: ./fsb @@ -8729,6 +8732,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [//]: # (algorithms) [Ascon]: https://ascon.iaik.tugraz.at +[Bash]: https://apmi.bsu.by/assets/files/std/bash-spec241.pdf [BelT]: https://ru.wikipedia.org/wiki/BelT [BLAKE2]: https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2 [FSB]: https://en.wikipedia.org/wiki/Fast_syndrome-based_hash @@ -11510,7 +11514,7 @@ ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation a --------------------------------------------------------- zbus 3.15.2 - MIT -https://github.com/dbus2/zbus/ +https://github.com/z-galaxy/zbus/ The MIT License (MIT) @@ -11544,7 +11548,7 @@ DEALINGS IN THE SOFTWARE. --------------------------------------------------------- zbus_macros 3.15.2 - MIT -https://github.com/dbus2/zbus/ +https://github.com/z-galaxy/zbus/ The MIT License (MIT) @@ -11580,33 +11584,7 @@ DEALINGS IN THE SOFTWARE. zbus_names 2.6.1 - MIT https://github.com/dbus2/zbus/ -The MIT License (MIT) - -Copyright (c) 2024 Zeeshan Ali Khan & zbus contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +LICENSE-MIT --------------------------------------------------------- --------------------------------------------------------- @@ -11902,33 +11880,7 @@ licences; see files named LICENSE.*.txt for details. zvariant 3.15.2 - MIT https://github.com/dbus2/zbus/ -The MIT License (MIT) - -Copyright (c) 2024 Zeeshan Ali Khan & zbus contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +LICENSE-MIT --------------------------------------------------------- --------------------------------------------------------- @@ -11936,33 +11888,7 @@ DEALINGS IN THE SOFTWARE. zvariant_derive 3.15.2 - MIT https://github.com/dbus2/zbus/ -The MIT License (MIT) - -Copyright (c) 2024 Zeeshan Ali Khan & zbus contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +LICENSE-MIT --------------------------------------------------------- --------------------------------------------------------- @@ -11970,31 +11896,5 @@ DEALINGS IN THE SOFTWARE. zvariant_utils 1.0.1 - MIT https://github.com/dbus2/zbus/ -The MIT License (MIT) - -Copyright (c) 2024 Zeeshan Ali Khan & zbus contributors - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. +LICENSE-MIT --------------------------------------------------------- \ No newline at end of file diff --git a/cli/src/commands/args.rs b/cli/src/commands/args.rs index 52c5af6d7d4..6301bdd3104 100644 --- a/cli/src/commands/args.rs +++ b/cli/src/commands/args.rs @@ -686,6 +686,10 @@ pub struct BaseServerArgs { /// Set the root path for extensions. #[clap(long)] pub extensions_dir: Option, + + /// Reconnection grace time in seconds. Defaults to 10800 (3 hours). + #[clap(long)] + pub reconnection_grace_time: Option, } impl BaseServerArgs { @@ -700,6 +704,10 @@ impl BaseServerArgs { if let Some(d) = &self.extensions_dir { csa.extensions_dir = Some(d.clone()); } + + if let Some(t) = self.reconnection_grace_time { + csa.reconnection_grace_time = Some(t); + } } } diff --git a/cli/src/tunnels/code_server.rs b/cli/src/tunnels/code_server.rs index cf00bc42835..bbabadcf90a 100644 --- a/cli/src/tunnels/code_server.rs +++ b/cli/src/tunnels/code_server.rs @@ -74,6 +74,8 @@ pub struct CodeServerArgs { pub connection_token: Option, pub connection_token_file: Option, pub without_connection_token: bool, + // reconnection + pub reconnection_grace_time: Option, } impl CodeServerArgs { @@ -120,6 +122,9 @@ impl CodeServerArgs { if let Some(i) = self.log { args.push(format!("--log={i}")); } + if let Some(t) = self.reconnection_grace_time { + args.push(format!("--reconnection-grace-time={t}")); + } for extension in &self.install_extensions { args.push(format!("--install-extension={extension}")); diff --git a/cli/src/update_service.rs b/cli/src/update_service.rs index 90339148188..55f1dadccdf 100644 --- a/cli/src/update_service.rs +++ b/cli/src/update_service.rs @@ -56,8 +56,15 @@ fn quality_download_segment(quality: options::Quality) -> &'static str { } } -fn get_update_endpoint() -> Result<&'static str, CodeError> { - VSCODE_CLI_UPDATE_ENDPOINT.ok_or_else(|| CodeError::UpdatesNotConfigured("no service url")) +fn get_update_endpoint() -> Result { + if let Ok(url) = std::env::var("VSCODE_CLI_UPDATE_URL") { + if !url.is_empty() { + return Ok(url); + } + } + VSCODE_CLI_UPDATE_ENDPOINT + .map(|s| s.to_string()) + .ok_or_else(|| CodeError::UpdatesNotConfigured("no service url")) } impl UpdateService { @@ -78,7 +85,7 @@ impl UpdateService { .ok_or_else(|| CodeError::UnsupportedPlatform(platform.to_string()))?; let download_url = format!( "{}/api/versions/{}/{}/{}", - update_endpoint, + &update_endpoint, version, download_segment, quality_download_segment(quality), @@ -119,7 +126,7 @@ impl UpdateService { .ok_or_else(|| CodeError::UnsupportedPlatform(platform.to_string()))?; let download_url = format!( "{}/api/latest/{}/{}", - update_endpoint, + &update_endpoint, download_segment, quality_download_segment(quality), ); @@ -156,7 +163,7 @@ impl UpdateService { let download_url = format!( "{}/commit:{}/{}/{}", - update_endpoint, + &update_endpoint, release.commit, download_segment, quality_download_segment(release.quality), diff --git a/eslint.config.js b/eslint.config.js index 6c65c69287b..f35fadddf8a 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -8,7 +8,7 @@ import path from 'path'; import tseslint from 'typescript-eslint'; import stylisticTs from '@stylistic/eslint-plugin-ts'; -import * as pluginLocal from './.eslint-plugin-local/index.js'; +import * as pluginLocal from './.eslint-plugin-local/index.ts'; import pluginJsdoc from 'eslint-plugin-jsdoc'; import pluginHeader from 'eslint-plugin-header'; @@ -75,7 +75,7 @@ export default tseslint.config( 'context' ], // non-complete list of globals that are easy to access unintentionally 'no-var': 'warn', - 'semi': 'off', + 'semi': 'warn', 'local/code-translation-remind': 'warn', 'local/code-no-native-private': 'warn', 'local/code-parameter-properties-must-have-explicit-accessibility': 'warn', @@ -89,6 +89,9 @@ export default tseslint.config( 'local/code-declare-service-brand': 'warn', 'local/code-no-reader-after-await': 'warn', 'local/code-no-observable-get-in-reactive-context': 'warn', + 'local/code-no-localized-model-description': 'warn', + 'local/code-policy-localization-key-match': 'warn', + 'local/code-no-localization-template-literals': 'error', 'local/code-no-deep-import-of-internal': ['error', { '.*Internal': true, 'searchExtTypesInternal': false }], 'local/code-layering': [ 'warn', @@ -130,7 +133,7 @@ export default tseslint.config( // TS { files: [ - '**/*.ts', + '**/*.{ts,tsx,mts,cts}', ], languageOptions: { parser: tseslint.parser, @@ -142,6 +145,8 @@ export default tseslint.config( 'jsdoc': pluginJsdoc, }, rules: { + // Disable built-in semi rules in favor of stylistic + 'semi': 'off', '@stylistic/ts/semi': 'warn', '@stylistic/ts/member-delimiter-style': 'warn', 'local/code-no-unused-expressions': [ @@ -177,125 +182,664 @@ export default tseslint.config( ] } }, - // vscode TS: strict no explicit `any` + // Disallow 'in' operator except in type predicates { files: [ - 'src/vs/base/browser/fastDomNode.ts', - 'src/vs/base/browser/globalPointerMoveMonitor.ts', - 'src/vs/base/browser/keyboardEvent.ts', - 'src/vs/base/browser/ui/mouseCursor/**', - 'src/vs/base/browser/ui/scrollbar/**', - 'src/vs/base/browser/ui/widget.ts', - 'src/vs/base/common/extpath.ts', - 'src/vs/base/common/fuzzyScorer.ts', - 'src/vs/base/common/glob.ts', - 'src/vs/base/common/path.ts', - 'src/vs/base/common/stream.ts', - 'src/vs/base/common/buffer.ts', - 'src/vs/base/common/charCode.ts', - 'src/vs/base/common/hash.ts', - 'src/vs/base/common/keybindingLabels.ts', - 'src/vs/base/common/keybindings.ts', - 'src/vs/base/common/keyCodes.ts', - 'src/vs/base/common/scrollable.ts', - 'src/vs/base/common/uint.ts', - 'src/vs/base/common/uriTransformer.ts', - 'src/vs/base/common/worker/webWorker.ts', - 'src/vs/base/node/pfs.ts', - 'src/vs/base/node/unc.ts', - 'src/vs/base/parts/contextmenu/**', - 'src/vs/editor/browser/**', - 'src/vs/editor/common/**', - 'src/vs/base/parts/sandbox/**', - 'src/vs/base/parts/storage/**', - 'src/vs/platform/auxiliaryWindow/**', - 'src/vs/platform/backup/**', - // 'src/vs/platform/configuration/**', - 'src/vs/platform/editor/**', - 'src/vs/platform/environment/**', - // 'src/vs/platform/extensionManagement/**', - // 'src/vs/platform/extensionRecommendations/**', - // 'src/vs/platform/extensionResourceLoader/**', - 'src/vs/platform/dialogs/**', - 'src/vs/platform/files/**', - 'src/vs/platform/ipc/**', - 'src/vs/platform/launch/**', - 'src/vs/platform/lifecycle/**', - // 'src/vs/platform/log/**', - 'src/vs/platform/mcp/**', - 'src/vs/platform/menubar/**', - 'src/vs/platform/native/**', - // 'src/vs/platform/policy/**', - 'src/vs/platform/sharedProcess/**', - 'src/vs/platform/state/**', - 'src/vs/platform/storage/**', - // 'src/vs/platform/userData/**', - // 'src/vs/platform/userDataProfile/**', - // 'src/vs/platform/userDataSync/**', - 'src/vs/platform/utilityProcess/**', - 'src/vs/platform/window/**', - 'src/vs/platform/windows/**', - 'src/vs/platform/workspace/**', - 'src/vs/platform/workspaces/**', - 'src/bootstrap-cli.ts', - 'src/bootstrap-esm.ts', - 'src/bootstrap-fork.ts', - 'src/bootstrap-import.ts', - 'src/bootstrap-meta.ts', - 'src/bootstrap-node.ts', - 'src/bootstrap-server.ts', - 'src/cli.ts', - 'src/main.ts', - 'src/server-cli.ts', - 'src/server-main.ts', - 'src/vs/code/**', - // 'src/vs/workbench/services/accounts/**', - 'src/vs/workbench/services/activity/**', - 'src/vs/workbench/services/auxiliaryWindow/**', - 'src/vs/workbench/services/chat/**', - // 'src/vs/workbench/services/configuration/**', - 'src/vs/workbench/services/contextmenu/**', - 'src/vs/workbench/services/dialogs/**', - 'src/vs/workbench/services/editor/**', - 'src/vs/workbench/services/environment/**', - // 'src/vs/workbench/services/extensionManagement/**', - // 'src/vs/workbench/services/extensionRecommendations/**', - // 'src/vs/workbench/services/extensions/**', - 'src/vs/workbench/services/files/**', - 'src/vs/workbench/services/filesConfiguration/**', - 'src/vs/workbench/services/history/**', - 'src/vs/workbench/services/host/**', - 'src/vs/workbench/services/label/**', - 'src/vs/workbench/services/layout/**', - 'src/vs/workbench/services/lifecycle/**', - // 'src/vs/workbench/services/log/**', - 'src/vs/workbench/services/mcp/**', - 'src/vs/workbench/services/notification/**', - // 'src/vs/workbench/services/output/**', - 'src/vs/workbench/services/path/**', - // 'src/vs/workbench/services/policies/**', - // 'src/vs/workbench/services/preferences/**', - 'src/vs/workbench/services/progress/**', - 'src/vs/workbench/services/storage/**', - 'src/vs/workbench/services/textfile/**', - 'src/vs/workbench/services/textmodelResolver/**', - 'src/vs/workbench/services/untitled/**', - // 'src/vs/workbench/services/userData/**', - // 'src/vs/workbench/services/userDataProfile/**', - // 'src/vs/workbench/services/userDataSync/**', - 'src/vs/workbench/services/utilityProcess/**', - 'src/vs/workbench/services/views/**', - 'src/vs/workbench/services/workingCopy/**', - 'src/vs/workbench/services/workspaces/**', - 'src/vs/workbench/common/**', - 'src/vs/workbench/browser/**', - 'src/vs/workbench/electron-browser/**', - 'src/vs/workbench/contrib/files/**', - 'src/vs/workbench/contrib/chat/browser/chatSetup.ts', - 'src/vs/workbench/contrib/chat/browser/chatStatus.ts', - 'src/vs/workbench/contrib/mcp/**', + '**/*.ts', + '.eslint-plugin-local/**/*.ts', // Explicitly include files under dot directories + ], + ignores: [ + 'src/bootstrap-node.ts', + 'build/lib/extensions.ts', + 'build/lib/test/render.test.ts', + 'extensions/debug-auto-launch/src/extension.ts', + 'extensions/emmet/src/updateImageSize.ts', + 'extensions/emmet/src/util.ts', + 'extensions/github-authentication/src/node/fetch.ts', + 'extensions/terminal-suggest/src/fig/figInterface.ts', + 'extensions/terminal-suggest/src/fig/fig-autocomplete-shared/mixins.ts', + 'extensions/terminal-suggest/src/fig/fig-autocomplete-shared/specMetadata.ts', + 'extensions/terminal-suggest/src/terminalSuggestMain.ts', + 'extensions/terminal-suggest/src/test/env/pathExecutableCache.test.ts', + 'extensions/tunnel-forwarding/src/extension.ts', + 'extensions/typescript-language-features/src/utils/platform.ts', + 'extensions/typescript-language-features/web/src/webServer.ts', + 'src/vs/base/browser/broadcast.ts', + 'src/vs/base/browser/canIUse.ts', + 'src/vs/base/browser/dom.ts', + 'src/vs/base/browser/markdownRenderer.ts', + 'src/vs/base/browser/touch.ts', + 'src/vs/base/common/async.ts', + 'src/vs/base/common/desktopEnvironmentInfo.ts', + 'src/vs/base/common/objects.ts', + 'src/vs/base/common/observableInternal/logging/consoleObservableLogger.ts', + 'src/vs/base/common/observableInternal/logging/debugger/devToolsLogger.ts', + 'src/vs/base/test/common/snapshot.ts', + 'src/vs/base/test/common/timeTravelScheduler.ts', + 'src/vs/editor/browser/controller/editContext/native/debugEditContext.ts', + 'src/vs/editor/browser/gpu/gpuUtils.ts', + 'src/vs/editor/browser/gpu/taskQueue.ts', + 'src/vs/editor/browser/view.ts', + 'src/vs/editor/browser/widget/diffEditor/diffEditorWidget.ts', + 'src/vs/editor/browser/widget/diffEditor/utils.ts', + 'src/vs/editor/browser/widget/multiDiffEditor/multiDiffEditorWidgetImpl.ts', + 'src/vs/editor/common/config/editorOptions.ts', + 'src/vs/editor/contrib/dropOrPasteInto/browser/copyPasteContribution.ts', + 'src/vs/editor/contrib/dropOrPasteInto/browser/copyPasteController.ts', + 'src/vs/editor/contrib/dropOrPasteInto/browser/edit.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/debugVisualization.ts', + 'src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts', + 'src/vs/platform/configuration/common/configuration.ts', + 'src/vs/platform/configuration/common/configurationModels.ts', + 'src/vs/platform/contextkey/browser/contextKeyService.ts', + 'src/vs/platform/contextkey/test/common/scanner.test.ts', + 'src/vs/platform/dataChannel/browser/forwardingTelemetryService.ts', + 'src/vs/platform/hover/browser/hoverService.ts', + 'src/vs/platform/hover/browser/hoverWidget.ts', + 'src/vs/platform/instantiation/common/instantiationService.ts', + 'src/vs/platform/mcp/common/mcpManagementCli.ts', + 'src/vs/workbench/api/browser/mainThreadChatSessions.ts', + 'src/vs/workbench/api/browser/mainThreadDebugService.ts', + 'src/vs/workbench/api/browser/mainThreadTesting.ts', + 'src/vs/workbench/api/common/extHost.api.impl.ts', + 'src/vs/workbench/api/common/extHostChatAgents2.ts', + 'src/vs/workbench/api/common/extHostChatSessions.ts', + 'src/vs/workbench/api/common/extHostDebugService.ts', + 'src/vs/workbench/api/common/extHostNotebookKernels.ts', + 'src/vs/workbench/api/common/extHostQuickOpen.ts', + 'src/vs/workbench/api/common/extHostRequireInterceptor.ts', + 'src/vs/workbench/api/common/extHostTypeConverters.ts', + 'src/vs/workbench/api/common/extHostTypes.ts', + 'src/vs/workbench/api/node/loopbackServer.ts', + 'src/vs/workbench/api/node/proxyResolver.ts', + 'src/vs/workbench/api/test/common/extHostTypeConverters.test.ts', + 'src/vs/workbench/api/test/common/testRPCProtocol.ts', + 'src/vs/workbench/api/worker/extHostExtensionService.ts', + 'src/vs/workbench/browser/parts/paneCompositeBar.ts', + 'src/vs/workbench/browser/parts/titlebar/titlebarPart.ts', + 'src/vs/workbench/browser/workbench.ts', + 'src/vs/workbench/common/notifications.ts', + 'src/vs/workbench/contrib/accessibility/browser/accessibleView.ts', + 'src/vs/workbench/contrib/chat/browser/chatAttachmentResolveService.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatAttachmentsContentPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatConfirmationWidget.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatElicitationContentPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatReferencesContentPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatTreeContentPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/toolInvocationParts/abstractToolConfirmationSubPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSession.ts', + 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingSessionStorage.ts', + 'src/vs/workbench/contrib/chat/browser/chatInlineAnchorWidget.ts', + 'src/vs/workbench/contrib/chat/browser/chatResponseAccessibleView.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions/common.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions/localChatSessionsProvider.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsTreeRenderer.ts', + 'src/vs/workbench/contrib/chat/browser/contrib/chatInputCompletions.ts', + 'src/vs/workbench/contrib/chat/common/annotations.ts', + 'src/vs/workbench/contrib/chat/common/chat.ts', + 'src/vs/workbench/contrib/chat/common/chatAgents.ts', + 'src/vs/workbench/contrib/chat/common/chatModel.ts', + 'src/vs/workbench/contrib/chat/common/chatService.ts', + 'src/vs/workbench/contrib/chat/common/chatServiceImpl.ts', + 'src/vs/workbench/contrib/chat/common/codeBlockModelCollection.ts', + 'src/vs/workbench/contrib/chat/test/common/chatModel.test.ts', + 'src/vs/workbench/contrib/chat/test/common/promptSyntax/testUtils/mockFilesystem.test.ts', + 'src/vs/workbench/contrib/chat/test/common/promptSyntax/testUtils/mockFilesystem.ts', + 'src/vs/workbench/contrib/chat/test/common/tools/manageTodoListTool.test.ts', + 'src/vs/workbench/contrib/debug/browser/breakpointsView.ts', + 'src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts', + 'src/vs/workbench/contrib/debug/browser/variablesView.ts', + 'src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts', + 'src/vs/workbench/contrib/debug/common/debugModel.ts', + 'src/vs/workbench/contrib/debug/common/debugger.ts', + 'src/vs/workbench/contrib/debug/common/replAccessibilityAnnouncer.ts', + 'src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts', + 'src/vs/workbench/contrib/editTelemetry/browser/helpers/documentWithAnnotatedEdits.ts', + 'src/vs/workbench/contrib/extensions/common/extensionQuery.ts', + 'src/vs/workbench/contrib/interactive/browser/interactiveEditorInput.ts', + 'src/vs/workbench/contrib/issue/browser/issueFormService.ts', + 'src/vs/workbench/contrib/issue/browser/issueQuickAccess.ts', + 'src/vs/workbench/contrib/markers/browser/markersView.ts', + 'src/vs/workbench/contrib/mcp/browser/mcpElicitationService.ts', + 'src/vs/workbench/contrib/mcp/common/mcpLanguageModelToolContribution.ts', + 'src/vs/workbench/contrib/mcp/common/mcpResourceFilesystem.ts', + 'src/vs/workbench/contrib/mcp/common/mcpSamplingLog.ts', + 'src/vs/workbench/contrib/mcp/common/mcpServer.ts', + 'src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.ts', + 'src/vs/workbench/contrib/mcp/test/common/mcpRegistryTypes.ts', + 'src/vs/workbench/contrib/mcp/test/common/mcpServerRequestHandler.test.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/cellOutputActions.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/chat/notebook.chat.contribution.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts', + 'src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts', + 'src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelView.ts', + 'src/vs/workbench/contrib/output/browser/outputView.ts', + 'src/vs/workbench/contrib/preferences/browser/settingsTree.ts', + 'src/vs/workbench/contrib/remoteTunnel/electron-browser/remoteTunnel.contribution.ts', + 'src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts', + 'src/vs/workbench/contrib/tasks/browser/taskTerminalStatus.ts', + 'src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts', + 'src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/taskHelpers.ts', + 'src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/monitoring/outputMonitor.ts', + 'src/vs/workbench/contrib/testing/browser/explorerProjections/listProjection.ts', + 'src/vs/workbench/contrib/testing/browser/explorerProjections/treeProjection.ts', + 'src/vs/workbench/contrib/testing/browser/testCoverageBars.ts', + 'src/vs/workbench/contrib/testing/browser/testExplorerActions.ts', + 'src/vs/workbench/contrib/testing/browser/testingOutputPeek.ts', + 'src/vs/workbench/contrib/testing/browser/testingProgressUiService.ts', + 'src/vs/workbench/contrib/testing/browser/testResultsView/testResultsTree.ts', + 'src/vs/workbench/contrib/testing/common/testCoverageService.ts', + 'src/vs/workbench/contrib/testing/common/testResultService.ts', + 'src/vs/workbench/contrib/testing/common/testingChatAgentTool.ts', + 'src/vs/workbench/contrib/testing/test/browser/testObjectTree.ts', + 'src/vs/workbench/contrib/themes/browser/themes.contribution.ts', + 'src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.contribution.ts', + 'src/vs/workbench/services/environment/electron-browser/environmentService.ts', + 'src/vs/workbench/services/keybinding/common/keybindingIO.ts', + 'src/vs/workbench/services/preferences/common/preferencesValidation.ts', + 'src/vs/workbench/services/remote/common/tunnelModel.ts', + 'src/vs/workbench/services/search/common/textSearchManager.ts', + 'src/vs/workbench/test/browser/workbenchTestServices.ts', + 'test/automation/src/playwrightDriver.ts', + '.eslint-plugin-local/**/*', + ], + plugins: { + 'local': pluginLocal, + }, + rules: { + 'local/code-no-in-operator': 'warn', + } + }, + // Strict no explicit `any` + { + files: [ + // Extensions + 'extensions/git/src/**/*.ts', + 'extensions/git-base/src/**/*.ts', + 'extensions/github/src/**/*.ts', + // vscode + 'src/**/*.ts', + ], + ignores: [ + // Extensions + 'extensions/git/src/commands.ts', + 'extensions/git/src/decorators.ts', + 'extensions/git/src/git.ts', + 'extensions/git/src/util.ts', + 'extensions/git-base/src/decorators.ts', + 'extensions/github/src/util.ts', + // vscode d.ts + 'src/vs/amdX.ts', + 'src/vs/monaco.d.ts', + 'src/vscode-dts/**', + // Base + 'src/vs/base/browser/dom.ts', + 'src/vs/base/browser/mouseEvent.ts', + 'src/vs/base/node/processes.ts', + 'src/vs/base/common/arrays.ts', + 'src/vs/base/common/async.ts', + 'src/vs/base/common/console.ts', + 'src/vs/base/common/decorators.ts', + 'src/vs/base/common/errorMessage.ts', + 'src/vs/base/common/errors.ts', + 'src/vs/base/common/event.ts', + 'src/vs/base/common/hotReload.ts', + 'src/vs/base/common/hotReloadHelpers.ts', + 'src/vs/base/common/json.ts', + 'src/vs/base/common/jsonSchema.ts', + 'src/vs/base/common/lifecycle.ts', + 'src/vs/base/common/map.ts', + 'src/vs/base/common/marshalling.ts', + 'src/vs/base/common/objects.ts', + 'src/vs/base/common/performance.ts', + 'src/vs/base/common/platform.ts', + 'src/vs/base/common/processes.ts', + 'src/vs/base/common/types.ts', + 'src/vs/base/common/uriIpc.ts', + 'src/vs/base/common/verifier.ts', + 'src/vs/base/common/observableInternal/base.ts', + 'src/vs/base/common/observableInternal/changeTracker.ts', + 'src/vs/base/common/observableInternal/set.ts', + 'src/vs/base/common/observableInternal/transaction.ts', + 'src/vs/base/common/worker/webWorkerBootstrap.ts', + 'src/vs/base/test/common/mock.ts', + 'src/vs/base/test/common/snapshot.ts', + 'src/vs/base/test/common/timeTravelScheduler.ts', + 'src/vs/base/test/common/troubleshooting.ts', + 'src/vs/base/test/common/utils.ts', + 'src/vs/base/browser/ui/breadcrumbs/breadcrumbsWidget.ts', + 'src/vs/base/browser/ui/grid/grid.ts', + 'src/vs/base/browser/ui/grid/gridview.ts', + 'src/vs/base/browser/ui/list/listPaging.ts', + 'src/vs/base/browser/ui/list/listView.ts', + 'src/vs/base/browser/ui/list/listWidget.ts', + 'src/vs/base/browser/ui/list/rowCache.ts', + 'src/vs/base/browser/ui/sash/sash.ts', + 'src/vs/base/browser/ui/table/tableWidget.ts', + 'src/vs/base/parts/ipc/common/ipc.net.ts', + 'src/vs/base/parts/ipc/common/ipc.ts', + 'src/vs/base/parts/ipc/electron-main/ipcMain.ts', + 'src/vs/base/parts/ipc/node/ipc.cp.ts', + 'src/vs/base/common/observableInternal/experimental/reducer.ts', + 'src/vs/base/common/observableInternal/experimental/utils.ts', + 'src/vs/base/common/observableInternal/logging/consoleObservableLogger.ts', + 'src/vs/base/common/observableInternal/logging/debugGetDependencyGraph.ts', + 'src/vs/base/common/observableInternal/logging/logging.ts', + 'src/vs/base/common/observableInternal/observables/baseObservable.ts', + 'src/vs/base/common/observableInternal/observables/derived.ts', + 'src/vs/base/common/observableInternal/observables/derivedImpl.ts', + 'src/vs/base/common/observableInternal/observables/observableFromEvent.ts', + 'src/vs/base/common/observableInternal/observables/observableSignalFromEvent.ts', + 'src/vs/base/common/observableInternal/reactions/autorunImpl.ts', + 'src/vs/base/common/observableInternal/utils/utils.ts', + 'src/vs/base/common/observableInternal/utils/utilsCancellation.ts', + 'src/vs/base/parts/ipc/test/node/testService.ts', + 'src/vs/base/common/observableInternal/logging/debugger/debuggerRpc.ts', + 'src/vs/base/common/observableInternal/logging/debugger/devToolsLogger.ts', + 'src/vs/base/common/observableInternal/logging/debugger/rpc.ts', + 'src/vs/base/test/browser/ui/grid/util.ts', + // Platform + 'src/vs/platform/browserElements/electron-main/nativeBrowserElementsMainService.ts', + 'src/vs/platform/commands/common/commands.ts', + 'src/vs/platform/contextkey/browser/contextKeyService.ts', + 'src/vs/platform/contextkey/common/contextkey.ts', + 'src/vs/platform/contextview/browser/contextView.ts', + 'src/vs/platform/debug/common/extensionHostDebugIpc.ts', + 'src/vs/platform/debug/electron-main/extensionHostDebugIpc.ts', + 'src/vs/platform/diagnostics/common/diagnostics.ts', + 'src/vs/platform/diagnostics/node/diagnosticsService.ts', + 'src/vs/platform/download/common/downloadIpc.ts', + 'src/vs/platform/extensions/common/extensions.ts', + 'src/vs/platform/instantiation/common/descriptors.ts', + 'src/vs/platform/instantiation/common/extensions.ts', + 'src/vs/platform/instantiation/common/instantiation.ts', + 'src/vs/platform/instantiation/common/instantiationService.ts', + 'src/vs/platform/instantiation/common/serviceCollection.ts', + 'src/vs/platform/keybinding/common/keybinding.ts', + 'src/vs/platform/keybinding/common/keybindingResolver.ts', + 'src/vs/platform/keybinding/common/keybindingsRegistry.ts', + 'src/vs/platform/keybinding/common/resolvedKeybindingItem.ts', + 'src/vs/platform/keyboardLayout/common/keyboardConfig.ts', + 'src/vs/platform/languagePacks/node/languagePacks.ts', + 'src/vs/platform/list/browser/listService.ts', + 'src/vs/platform/log/browser/log.ts', + 'src/vs/platform/log/common/log.ts', + 'src/vs/platform/log/common/logIpc.ts', + 'src/vs/platform/log/electron-main/logIpc.ts', + 'src/vs/platform/observable/common/wrapInHotClass.ts', + 'src/vs/platform/observable/common/wrapInReloadableClass.ts', + 'src/vs/platform/policy/common/policyIpc.ts', + 'src/vs/platform/profiling/common/profilingTelemetrySpec.ts', + 'src/vs/platform/quickinput/browser/quickInputActions.ts', + 'src/vs/platform/quickinput/common/quickInput.ts', + 'src/vs/platform/registry/common/platform.ts', + 'src/vs/platform/remote/browser/browserSocketFactory.ts', + 'src/vs/platform/remote/browser/remoteAuthorityResolverService.ts', + 'src/vs/platform/remote/common/remoteAgentConnection.ts', + 'src/vs/platform/remote/common/remoteAuthorityResolver.ts', + 'src/vs/platform/remote/electron-browser/electronRemoteResourceLoader.ts', + 'src/vs/platform/remote/electron-browser/remoteAuthorityResolverService.ts', + 'src/vs/platform/remoteTunnel/node/remoteTunnelService.ts', + 'src/vs/platform/request/common/request.ts', + 'src/vs/platform/request/common/requestIpc.ts', + 'src/vs/platform/request/electron-utility/requestService.ts', + 'src/vs/platform/request/node/proxy.ts', + 'src/vs/platform/telemetry/browser/errorTelemetry.ts', + 'src/vs/platform/telemetry/common/errorTelemetry.ts', + 'src/vs/platform/telemetry/common/remoteTelemetryChannel.ts', + 'src/vs/platform/telemetry/node/errorTelemetry.ts', + 'src/vs/platform/theme/common/iconRegistry.ts', + 'src/vs/platform/theme/common/tokenClassificationRegistry.ts', + 'src/vs/platform/update/common/updateIpc.ts', + 'src/vs/platform/update/electron-main/updateService.snap.ts', + 'src/vs/platform/url/common/urlIpc.ts', + 'src/vs/platform/userDataProfile/common/userDataProfileIpc.ts', + 'src/vs/platform/userDataProfile/electron-main/userDataProfileStorageIpc.ts', + 'src/vs/platform/userDataSync/common/abstractSynchronizer.ts', + 'src/vs/platform/userDataSync/common/extensionsMerge.ts', + 'src/vs/platform/userDataSync/common/extensionsSync.ts', + 'src/vs/platform/userDataSync/common/globalStateMerge.ts', + 'src/vs/platform/userDataSync/common/globalStateSync.ts', + 'src/vs/platform/userDataSync/common/settingsMerge.ts', + 'src/vs/platform/userDataSync/common/settingsSync.ts', + 'src/vs/platform/userDataSync/common/userDataSync.ts', + 'src/vs/platform/userDataSync/common/userDataSyncIpc.ts', + 'src/vs/platform/userDataSync/common/userDataSyncServiceIpc.ts', + 'src/vs/platform/webview/common/webviewManagerService.ts', + 'src/vs/platform/instantiation/test/common/instantiationServiceMock.ts', + 'src/vs/platform/keybinding/test/common/mockKeybindingService.ts', + // Editor + 'src/vs/editor/standalone/browser/standaloneEditor.ts', + 'src/vs/editor/standalone/browser/standaloneLanguages.ts', + 'src/vs/editor/standalone/browser/standaloneServices.ts', + 'src/vs/editor/test/browser/testCodeEditor.ts', + 'src/vs/editor/test/common/testTextModel.ts', + 'src/vs/editor/contrib/bracketMatching/browser/bracketMatching.ts', + 'src/vs/editor/contrib/codeAction/browser/codeAction.ts', + 'src/vs/editor/contrib/codeAction/browser/codeActionCommands.ts', + 'src/vs/editor/contrib/codeAction/common/types.ts', + 'src/vs/editor/contrib/colorPicker/browser/colorDetector.ts', + 'src/vs/editor/contrib/diffEditorBreadcrumbs/browser/contribution.ts', + 'src/vs/editor/contrib/dropOrPasteInto/browser/dropIntoEditorContribution.ts', + 'src/vs/editor/contrib/find/browser/findController.ts', + 'src/vs/editor/contrib/find/browser/findModel.ts', + 'src/vs/editor/contrib/find/browser/findWidgetSearchHistory.ts', + 'src/vs/editor/contrib/find/browser/replaceWidgetHistory.ts', + 'src/vs/editor/contrib/folding/browser/folding.ts', + 'src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts', + 'src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts', + 'src/vs/editor/contrib/hover/browser/hoverActions.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/structuredLogger.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/utils.ts', + 'src/vs/editor/contrib/smartSelect/browser/smartSelect.ts', + 'src/vs/editor/contrib/stickyScroll/browser/stickyScrollModelProvider.ts', + 'src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts', + 'src/vs/editor/contrib/wordHighlighter/browser/wordHighlighter.ts', + 'src/vs/editor/standalone/common/monarch/monarchCommon.ts', + 'src/vs/editor/standalone/common/monarch/monarchCompile.ts', + 'src/vs/editor/standalone/common/monarch/monarchLexer.ts', + 'src/vs/editor/standalone/common/monarch/monarchTypes.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/controller/commands.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/model/typingSpeed.ts', + 'src/vs/editor/contrib/inlineCompletions/test/browser/utils.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/debugVisualization.ts', + 'src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/utils/utils.ts', + // Workbench + 'src/vs/workbench/api/browser/mainThreadChatSessions.ts', + 'src/vs/workbench/api/common/extHost.api.impl.ts', + 'src/vs/workbench/api/common/extHost.protocol.ts', + 'src/vs/workbench/api/common/extHostChatSessions.ts', + 'src/vs/workbench/api/common/extHostCodeInsets.ts', + 'src/vs/workbench/api/common/extHostCommands.ts', + 'src/vs/workbench/api/common/extHostConsoleForwarder.ts', + 'src/vs/workbench/api/common/extHostDataChannels.ts', + 'src/vs/workbench/api/common/extHostDebugService.ts', + 'src/vs/workbench/api/common/extHostExtensionActivator.ts', + 'src/vs/workbench/api/common/extHostExtensionService.ts', + 'src/vs/workbench/api/common/extHostFileSystemConsumer.ts', + 'src/vs/workbench/api/common/extHostFileSystemEventService.ts', + 'src/vs/workbench/api/common/extHostLanguageFeatures.ts', + 'src/vs/workbench/api/common/extHostLanguageModelTools.ts', + 'src/vs/workbench/api/common/extHostMcp.ts', + 'src/vs/workbench/api/common/extHostMemento.ts', + 'src/vs/workbench/api/common/extHostMessageService.ts', + 'src/vs/workbench/api/common/extHostNotebookDocument.ts', + 'src/vs/workbench/api/common/extHostNotebookDocumentSaveParticipant.ts', + 'src/vs/workbench/api/common/extHostRequireInterceptor.ts', + 'src/vs/workbench/api/common/extHostRpcService.ts', + 'src/vs/workbench/api/common/extHostSCM.ts', + 'src/vs/workbench/api/common/extHostSearch.ts', + 'src/vs/workbench/api/common/extHostStatusBar.ts', + 'src/vs/workbench/api/common/extHostStoragePaths.ts', + 'src/vs/workbench/api/common/extHostTelemetry.ts', + 'src/vs/workbench/api/common/extHostTesting.ts', + 'src/vs/workbench/api/common/extHostTextEditor.ts', + 'src/vs/workbench/api/common/extHostTimeline.ts', + 'src/vs/workbench/api/common/extHostTreeViews.ts', + 'src/vs/workbench/api/common/extHostTypeConverters.ts', + 'src/vs/workbench/api/common/extHostTypes.ts', + 'src/vs/workbench/api/common/extHostTypes/es5ClassCompat.ts', + 'src/vs/workbench/api/common/extHostTypes/location.ts', + 'src/vs/workbench/api/common/extHostWebview.ts', + 'src/vs/workbench/api/common/extHostWebviewMessaging.ts', + 'src/vs/workbench/api/common/extHostWebviewPanels.ts', + 'src/vs/workbench/api/common/extHostWebviewView.ts', + 'src/vs/workbench/api/common/extHostWorkspace.ts', + 'src/vs/workbench/api/common/extensionHostMain.ts', + 'src/vs/workbench/api/common/shared/tasks.ts', + 'src/vs/workbench/api/node/extHostAuthentication.ts', + 'src/vs/workbench/api/node/extHostCLIServer.ts', + 'src/vs/workbench/api/node/extHostConsoleForwarder.ts', + 'src/vs/workbench/api/node/extHostDownloadService.ts', + 'src/vs/workbench/api/node/extHostExtensionService.ts', + 'src/vs/workbench/api/node/extHostMcpNode.ts', + 'src/vs/workbench/api/node/extensionHostProcess.ts', + 'src/vs/workbench/api/node/proxyResolver.ts', + 'src/vs/workbench/api/test/common/testRPCProtocol.ts', + 'src/vs/workbench/api/worker/extHostConsoleForwarder.ts', + 'src/vs/workbench/api/worker/extHostExtensionService.ts', + 'src/vs/workbench/api/worker/extensionHostWorker.ts', + 'src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts', + 'src/vs/workbench/contrib/accessibilitySignals/browser/commands.ts', + 'src/vs/workbench/contrib/authentication/browser/actions/manageTrustedMcpServersForAccountAction.ts', + 'src/vs/workbench/contrib/bulkEdit/browser/bulkCellEdits.ts', + 'src/vs/workbench/contrib/bulkEdit/browser/bulkTextEdits.ts', + 'src/vs/workbench/contrib/bulkEdit/browser/opaqueEdits.ts', + 'src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts', + 'src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPreview.ts', + 'src/vs/workbench/contrib/chat/browser/actions/chatCodeblockActions.ts', + 'src/vs/workbench/contrib/chat/browser/actions/chatContextActions.ts', + 'src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatConfirmationWidget.ts', + 'src/vs/workbench/contrib/chat/browser/chatContentParts/chatMultiDiffContentPart.ts', + 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingActions.ts', + 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingEditorActions.ts', + 'src/vs/workbench/contrib/chat/browser/chatEditing/chatEditingServiceImpl.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions.contribution.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions/common.ts', + 'src/vs/workbench/contrib/chat/browser/chatSessions/view/sessionsTreeRenderer.ts', + 'src/vs/workbench/contrib/chat/browser/contrib/chatDynamicVariables.ts', + 'src/vs/workbench/contrib/chat/common/chatModel.ts', + 'src/vs/workbench/contrib/chat/common/chatModes.ts', + 'src/vs/workbench/contrib/chat/common/chatService.ts', + 'src/vs/workbench/contrib/chat/common/chatServiceImpl.ts', + 'src/vs/workbench/contrib/chat/common/chatSessionsService.ts', + 'src/vs/workbench/contrib/chat/common/chatWidgetHistoryService.ts', + 'src/vs/workbench/contrib/chat/common/languageModelToolsService.ts', + 'src/vs/workbench/contrib/chat/common/languageModels.ts', + 'src/vs/workbench/contrib/chat/common/promptSyntax/service/promptsServiceImpl.ts', + 'src/vs/workbench/contrib/chat/common/tools/manageTodoListTool.ts', + 'src/vs/workbench/contrib/chat/test/common/languageModels.ts', + 'src/vs/workbench/contrib/chat/test/common/mockLanguageModelToolsService.ts', + 'src/vs/workbench/contrib/chat/test/common/mockPromptsService.ts', + 'src/vs/workbench/contrib/codeEditor/browser/inspectEditorTokens/inspectEditorTokens.ts', + 'src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts', + 'src/vs/workbench/contrib/codeEditor/electron-browser/selectionClipboard.ts', + 'src/vs/workbench/contrib/commands/common/commands.contribution.ts', + 'src/vs/workbench/contrib/comments/browser/commentNode.ts', + 'src/vs/workbench/contrib/comments/browser/commentsAccessibleView.ts', + 'src/vs/workbench/contrib/comments/browser/commentsTreeViewer.ts', + 'src/vs/workbench/contrib/comments/browser/commentsView.ts', + 'src/vs/workbench/contrib/comments/browser/reactionsAction.ts', + 'src/vs/workbench/contrib/customEditor/browser/customEditorInputFactory.ts', + 'src/vs/workbench/contrib/customEditor/browser/customEditors.ts', + 'src/vs/workbench/contrib/customEditor/common/customEditor.ts', + 'src/vs/workbench/contrib/debug/browser/debugActionViewItems.ts', + 'src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts', + 'src/vs/workbench/contrib/debug/browser/debugCommands.ts', + 'src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts', + 'src/vs/workbench/contrib/debug/browser/debugEditorActions.ts', + 'src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts', + 'src/vs/workbench/contrib/debug/browser/debugHover.ts', + 'src/vs/workbench/contrib/debug/browser/debugService.ts', + 'src/vs/workbench/contrib/debug/browser/debugSession.ts', + 'src/vs/workbench/contrib/debug/browser/rawDebugSession.ts', + 'src/vs/workbench/contrib/debug/browser/repl.ts', + 'src/vs/workbench/contrib/debug/browser/replViewer.ts', + 'src/vs/workbench/contrib/debug/browser/variablesView.ts', + 'src/vs/workbench/contrib/debug/browser/watchExpressionsView.ts', + 'src/vs/workbench/contrib/debug/common/abstractDebugAdapter.ts', + 'src/vs/workbench/contrib/debug/common/debugger.ts', + 'src/vs/workbench/contrib/debug/common/replModel.ts', + 'src/vs/workbench/contrib/debug/test/common/mockDebug.ts', + 'src/vs/workbench/contrib/editSessions/common/workspaceStateSync.ts', + 'src/vs/workbench/contrib/editTelemetry/browser/helpers/documentWithAnnotatedEdits.ts', + 'src/vs/workbench/contrib/editTelemetry/browser/helpers/utils.ts', + 'src/vs/workbench/contrib/editTelemetry/browser/telemetry/arcTelemetrySender.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionEditor.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts', + 'src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionsActions.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionsActivationProgress.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionsViewer.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionsViews.ts', + 'src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts', + 'src/vs/workbench/contrib/extensions/common/extensions.ts', + 'src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts', + 'src/vs/workbench/contrib/inlineChat/browser/inlineChatActions.ts', + 'src/vs/workbench/contrib/inlineChat/browser/inlineChatController.ts', + 'src/vs/workbench/contrib/inlineChat/browser/inlineChatStrategies.ts', + 'src/vs/workbench/contrib/issue/browser/issueReporterModel.ts', + 'src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.ts', + 'src/vs/workbench/contrib/markdown/browser/markdownSettingRenderer.ts', + 'src/vs/workbench/contrib/markers/browser/markers.contribution.ts', + 'src/vs/workbench/contrib/markers/browser/markersTable.ts', + 'src/vs/workbench/contrib/markers/browser/markersView.ts', + 'src/vs/workbench/contrib/mergeEditor/browser/commands/commands.ts', + 'src/vs/workbench/contrib/mergeEditor/browser/utils.ts', + 'src/vs/workbench/contrib/mergeEditor/browser/view/editorGutter.ts', + 'src/vs/workbench/contrib/mergeEditor/browser/view/mergeEditor.ts', + 'src/vs/workbench/contrib/notebook/browser/contrib/clipboard/notebookClipboard.ts', + 'src/vs/workbench/contrib/notebook/browser/contrib/find/notebookFind.ts', + 'src/vs/workbench/contrib/notebook/browser/contrib/layout/layoutActions.ts', + 'src/vs/workbench/contrib/notebook/browser/contrib/profile/notebookProfile.ts', + 'src/vs/workbench/contrib/notebook/browser/contrib/troubleshoot/layout.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/chat/cellChatActions.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/coreActions.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/editActions.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/notebookIndentationActions.ts', + 'src/vs/workbench/contrib/notebook/browser/controller/sectionActions.ts', + 'src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts', + 'src/vs/workbench/contrib/notebook/browser/diff/inlineDiff/notebookDeletedCellDecorator.ts', + 'src/vs/workbench/contrib/notebook/browser/notebookBrowser.ts', + 'src/vs/workbench/contrib/notebook/browser/outputEditor/notebookOutputEditor.ts', + 'src/vs/workbench/contrib/notebook/browser/services/notebookEditorServiceImpl.ts', + 'src/vs/workbench/contrib/notebook/browser/view/notebookCellList.ts', + 'src/vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView.ts', + 'src/vs/workbench/contrib/notebook/browser/view/renderers/webviewMessages.ts', + 'src/vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts', + 'src/vs/workbench/contrib/notebook/browser/viewModel/markupCellViewModel.ts', + 'src/vs/workbench/contrib/notebook/browser/viewParts/notebookEditorStickyScroll.ts', + 'src/vs/workbench/contrib/notebook/browser/viewParts/notebookHorizontalTracker.ts', + 'src/vs/workbench/contrib/notebook/browser/viewParts/notebookKernelQuickPickStrategy.ts', + 'src/vs/workbench/contrib/notebook/browser/viewParts/notebookViewZones.ts', + 'src/vs/workbench/contrib/notebook/common/model/notebookCellTextModel.ts', + 'src/vs/workbench/contrib/notebook/common/model/notebookMetadataTextModel.ts', + 'src/vs/workbench/contrib/notebook/common/model/notebookTextModel.ts', + 'src/vs/workbench/contrib/notebook/common/notebookCommon.ts', + 'src/vs/workbench/contrib/notebook/common/notebookEditorModelResolverServiceImpl.ts', + 'src/vs/workbench/contrib/notebook/common/notebookRange.ts', + 'src/vs/workbench/contrib/notebook/test/browser/testNotebookEditor.ts', + 'src/vs/workbench/contrib/performance/electron-browser/startupProfiler.ts', + 'src/vs/workbench/contrib/preferences/browser/keybindingsEditor.ts', + 'src/vs/workbench/contrib/preferences/browser/preferences.contribution.ts', + 'src/vs/workbench/contrib/preferences/browser/preferencesRenderers.ts', + 'src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts', + 'src/vs/workbench/contrib/preferences/browser/settingsTree.ts', + 'src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts', + 'src/vs/workbench/contrib/remote/browser/tunnelView.ts', + 'src/vs/workbench/contrib/search/browser/AISearch/aiSearchModel.ts', + 'src/vs/workbench/contrib/search/browser/AISearch/aiSearchModelBase.ts', + 'src/vs/workbench/contrib/search/browser/notebookSearch/notebookSearchModel.ts', + 'src/vs/workbench/contrib/search/browser/notebookSearch/notebookSearchModelBase.ts', + 'src/vs/workbench/contrib/search/browser/notebookSearch/searchNotebookHelpers.ts', + 'src/vs/workbench/contrib/search/browser/replace.ts', + 'src/vs/workbench/contrib/search/browser/replaceService.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsCopy.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsFind.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsNav.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsRemoveReplace.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsTextQuickAccess.ts', + 'src/vs/workbench/contrib/search/browser/searchActionsTopBar.ts', + 'src/vs/workbench/contrib/search/browser/searchMessage.ts', + 'src/vs/workbench/contrib/search/browser/searchResultsView.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/fileMatch.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/folderMatch.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/searchModel.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/searchResult.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/searchTreeCommon.ts', + 'src/vs/workbench/contrib/search/browser/searchTreeModel/textSearchHeading.ts', + 'src/vs/workbench/contrib/search/browser/searchView.ts', + 'src/vs/workbench/contrib/search/browser/searchWidget.ts', + 'src/vs/workbench/contrib/search/common/cacheState.ts', + 'src/vs/workbench/contrib/search/test/browser/mockSearchTree.ts', + 'src/vs/workbench/contrib/searchEditor/browser/searchEditor.contribution.ts', + 'src/vs/workbench/contrib/searchEditor/browser/searchEditorActions.ts', + 'src/vs/workbench/contrib/searchEditor/browser/searchEditorInput.ts', + 'src/vs/workbench/contrib/snippets/browser/commands/configureSnippets.ts', + 'src/vs/workbench/contrib/snippets/browser/commands/insertSnippet.ts', + 'src/vs/workbench/contrib/snippets/browser/snippetsFile.ts', + 'src/vs/workbench/contrib/snippets/browser/snippetsService.ts', + 'src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts', + 'src/vs/workbench/contrib/tasks/browser/runAutomaticTasks.ts', + 'src/vs/workbench/contrib/tasks/browser/task.contribution.ts', + 'src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts', + 'src/vs/workbench/contrib/tasks/common/jsonSchema_v1.ts', + 'src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts', + 'src/vs/workbench/contrib/tasks/common/problemMatcher.ts', + 'src/vs/workbench/contrib/tasks/common/taskConfiguration.ts', + 'src/vs/workbench/contrib/tasks/common/taskSystem.ts', + 'src/vs/workbench/contrib/tasks/common/tasks.ts', + 'src/vs/workbench/contrib/testing/common/storedValue.ts', + 'src/vs/workbench/contrib/testing/common/testItemCollection.ts', + 'src/vs/workbench/contrib/testing/test/browser/testObjectTree.ts', + 'src/vs/workbench/contrib/typeHierarchy/browser/typeHierarchy.contribution.ts', + 'src/vs/workbench/contrib/typeHierarchy/common/typeHierarchy.ts', + 'src/vs/workbench/contrib/webview/browser/overlayWebview.ts', + 'src/vs/workbench/contrib/webview/browser/webview.ts', + 'src/vs/workbench/contrib/webview/browser/webviewElement.ts', + 'src/vs/workbench/contrib/webviewPanel/browser/webviewEditor.ts', + 'src/vs/workbench/contrib/webviewPanel/browser/webviewEditorInputSerializer.ts', + 'src/vs/workbench/contrib/webviewPanel/browser/webviewWorkbenchService.ts', + 'src/vs/workbench/contrib/webviewView/browser/webviewViewPane.ts', + 'src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStarted.ts', + 'src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedAccessibleView.ts', + 'src/vs/workbench/contrib/welcomeGettingStarted/browser/gettingStartedService.ts', + 'src/vs/workbench/contrib/welcomeWalkthrough/browser/walkThroughPart.ts', + 'src/vs/workbench/services/authentication/common/authentication.ts', + 'src/vs/workbench/services/authentication/test/browser/authenticationQueryServiceMocks.ts', + 'src/vs/workbench/services/commands/common/commandService.ts', + 'src/vs/workbench/services/configurationResolver/common/configurationResolver.ts', + 'src/vs/workbench/services/configurationResolver/common/configurationResolverExpression.ts', + 'src/vs/workbench/services/extensions/common/extensionHostManager.ts', + 'src/vs/workbench/services/extensions/common/extensionsRegistry.ts', + 'src/vs/workbench/services/extensions/common/lazyPromise.ts', + 'src/vs/workbench/services/extensions/common/polyfillNestedWorker.protocol.ts', + 'src/vs/workbench/services/extensions/common/rpcProtocol.ts', + 'src/vs/workbench/services/extensions/worker/polyfillNestedWorker.ts', + 'src/vs/workbench/services/keybinding/browser/keybindingService.ts', + 'src/vs/workbench/services/keybinding/browser/keyboardLayoutService.ts', + 'src/vs/workbench/services/keybinding/common/keybindingEditing.ts', + 'src/vs/workbench/services/keybinding/common/keymapInfo.ts', + 'src/vs/workbench/services/language/common/languageService.ts', + 'src/vs/workbench/services/outline/browser/outline.ts', + 'src/vs/workbench/services/outline/browser/outlineService.ts', + 'src/vs/workbench/services/preferences/common/preferences.ts', + 'src/vs/workbench/services/preferences/common/preferencesModels.ts', + 'src/vs/workbench/services/preferences/common/preferencesValidation.ts', + 'src/vs/workbench/services/remote/common/tunnelModel.ts', + 'src/vs/workbench/services/search/common/replace.ts', + 'src/vs/workbench/services/search/common/search.ts', + 'src/vs/workbench/services/search/common/searchExtConversionTypes.ts', + 'src/vs/workbench/services/search/common/searchExtTypes.ts', + 'src/vs/workbench/services/search/node/fileSearch.ts', + 'src/vs/workbench/services/search/node/rawSearchService.ts', + 'src/vs/workbench/services/search/node/ripgrepTextSearchEngine.ts', + 'src/vs/workbench/services/textMate/common/TMGrammarFactory.ts', + 'src/vs/workbench/services/themes/browser/fileIconThemeData.ts', + 'src/vs/workbench/services/themes/browser/productIconThemeData.ts', + 'src/vs/workbench/services/themes/common/colorThemeData.ts', + 'src/vs/workbench/services/themes/common/plistParser.ts', + 'src/vs/workbench/services/themes/common/themeExtensionPoints.ts', + 'src/vs/workbench/services/themes/common/workbenchThemeService.ts', + 'src/vs/workbench/test/browser/workbenchTestServices.ts', + 'src/vs/workbench/test/common/workbenchTestServices.ts', + 'src/vs/workbench/test/electron-browser/workbenchTestServices.ts', + 'src/vs/workbench/workbench.web.main.internal.ts', + 'src/vs/workbench/workbench.web.main.ts', + // Server + 'src/vs/server/node/remoteAgentEnvironmentImpl.ts', + 'src/vs/server/node/remoteExtensionHostAgentServer.ts', + 'src/vs/server/node/remoteExtensionsScanner.ts', + // Tests + '**/*.test.ts', + '**/*.integrationTest.ts' ], - ignores: ['**/*.test.ts', '**/*.integrationTest.ts'], languageOptions: { parser: tseslint.parser, }, @@ -306,7 +850,7 @@ export default tseslint.config( '@typescript-eslint/no-explicit-any': [ 'warn', { - 'ignoreRestArgs': false + 'fixToUnknown': false } ] } @@ -323,10 +867,10 @@ export default tseslint.config( 'local': pluginLocal, }, rules: { + 'local/code-no-dangerous-type-assertions': 'off', 'local/code-must-use-super-dispose': 'off', 'local/code-no-test-only': 'error', 'local/code-no-test-async-suite': 'warn', - 'local/code-no-unexternalized-strings': 'off', 'local/code-must-use-result': [ 'warn', [ @@ -700,6 +1244,34 @@ export default tseslint.config( { 'selector': `MemberExpression[object.name='document'][property.name='execCommand']`, 'message': 'Use .document.execCommand to support multi-window scenarios. Resolve targetWindow with DOM.getWindow(element) or DOM.getActiveWindow() or use the predefined mainWindow constant.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'querySelector\']', + 'message': 'querySelector should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'querySelectorAll\']', + 'message': 'querySelectorAll should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'getElementById\']', + 'message': 'getElementById should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'getElementsByClassName\']', + 'message': 'getElementsByClassName should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'getElementsByTagName\']', + 'message': 'getElementsByTagName should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'getElementsByName\']', + 'message': 'getElementsByName should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' + }, + { + 'selector': 'CallExpression[callee.property.name=\'getElementsByTagNameNS\']', + 'message': 'getElementsByTagNameNS should not be used as relying on selectors is very fragile. Use dom.ts h() to build your elements and access them directly.' } ], 'no-restricted-globals': [ @@ -960,7 +1532,7 @@ export default tseslint.config( 'readline', 'stream', 'string_decoder', - 'tas-client-umd', + 'tas-client', 'tls', 'undici', 'undici-types', @@ -1049,7 +1621,7 @@ export default tseslint.config( 'vs/base/~', 'vs/base/parts/*/~', 'vs/platform/*/~', - 'tas-client-umd', // node module allowed even in /common/ + 'tas-client', // node module allowed even in /common/ '@microsoft/1ds-core-js', // node module allowed even in /common/ '@microsoft/1ds-post-js', // node module allowed even in /common/ '@xterm/headless' // node module allowed even in /common/ @@ -1167,7 +1739,7 @@ export default tseslint.config( 'when': 'test', 'pattern': 'vs/workbench/contrib/*/~' }, // TODO@layers - 'tas-client-umd', // node module allowed even in /common/ + 'tas-client', // node module allowed even in /common/ 'vscode-textmate', // node module allowed even in /common/ '@vscode/vscode-languagedetection', // node module allowed even in /common/ '@vscode/tree-sitter-wasm', // type import @@ -1221,6 +1793,7 @@ export default tseslint.config( // terminalContrib is one extra folder deep 'vs/workbench/contrib/terminalContrib/*/~', 'vscode-notebook-renderer', // Type only import + '@vscode/tree-sitter-wasm', // type import { 'when': 'hasBrowser', 'pattern': '@xterm/xterm' diff --git a/extensions/csharp/cgmanifest.json b/extensions/csharp/cgmanifest.json index de6d5f6d89c..61e941c3488 100644 --- a/extensions/csharp/cgmanifest.json +++ b/extensions/csharp/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "dotnet/csharp-tmLanguage", "repositoryUrl": "https://github.com/dotnet/csharp-tmLanguage", - "commitHash": "c32388ec18690abefb37cbaffa687a338c87d016" + "commitHash": "965478e687f08d3b2ee4fe17104d3f41638bdca2" } }, "license": "MIT", diff --git a/extensions/csharp/syntaxes/csharp.tmLanguage.json b/extensions/csharp/syntaxes/csharp.tmLanguage.json index 007fb719459..b360a96cb65 100644 --- a/extensions/csharp/syntaxes/csharp.tmLanguage.json +++ b/extensions/csharp/syntaxes/csharp.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/dotnet/csharp-tmLanguage/commit/c32388ec18690abefb37cbaffa687a338c87d016", + "version": "https://github.com/dotnet/csharp-tmLanguage/commit/965478e687f08d3b2ee4fe17104d3f41638bdca2", "name": "C#", "scopeName": "source.cs", "patterns": [ @@ -5238,6 +5238,9 @@ }, { "include": "#preprocessor-pragma-checksum" + }, + { + "include": "#preprocessor-app-directive" } ] }, @@ -5447,6 +5450,129 @@ } } }, + "preprocessor-app-directive": { + "begin": "\\s*(:)\\s*", + "beginCaptures": { + "1": { + "name": "punctuation.separator.colon.cs" + } + }, + "end": "(?=$)", + "patterns": [ + { + "include": "#preprocessor-app-directive-package" + }, + { + "include": "#preprocessor-app-directive-property" + }, + { + "include": "#preprocessor-app-directive-project" + }, + { + "include": "#preprocessor-app-directive-sdk" + }, + { + "include": "#preprocessor-app-directive-generic" + } + ] + }, + "preprocessor-app-directive-package": { + "match": "\\b(package)\\b\\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\\s*", + "captures": { + "1": { + "name": "keyword.preprocessor.package.cs" + }, + "2": { + "patterns": [ + { + "include": "#preprocessor-app-directive-package-name" + } + ] + }, + "3": { + "name": "punctuation.separator.at.cs" + }, + "4": { + "name": "string.unquoted.preprocessor.message.cs" + } + } + }, + "preprocessor-app-directive-property": { + "match": "\\b(property)\\b\\s*([_[:alpha:]][_[:alnum:]]*)?(=)?(.*)?\\s*", + "captures": { + "1": { + "name": "keyword.preprocessor.property.cs" + }, + "2": { + "name": "entity.name.variable.preprocessor.symbol.cs" + }, + "3": { + "name": "punctuation.separator.equals.cs" + }, + "4": { + "name": "string.unquoted.preprocessor.message.cs" + } + } + }, + "preprocessor-app-directive-project": { + "match": "\\b(project)\\b\\s*(.*)?\\s*", + "captures": { + "1": { + "name": "keyword.preprocessor.project.cs" + }, + "2": { + "name": "string.unquoted.preprocessor.message.cs" + } + } + }, + "preprocessor-app-directive-sdk": { + "match": "\\b(sdk)\\b\\s*([_[:alpha:]][_.[:alnum:]]*)?(@)?(.*)?\\s*", + "captures": { + "1": { + "name": "keyword.preprocessor.sdk.cs" + }, + "2": { + "patterns": [ + { + "include": "#preprocessor-app-directive-package-name" + } + ] + }, + "3": { + "name": "punctuation.separator.at.cs" + }, + "4": { + "name": "string.unquoted.preprocessor.message.cs" + } + } + }, + "preprocessor-app-directive-package-name": { + "patterns": [ + { + "match": "(\\.)([_[:alpha:]][_[:alnum:]]*)", + "captures": { + "1": { + "name": "punctuation.dot.cs" + }, + "2": { + "name": "entity.name.variable.preprocessor.symbol.cs" + } + } + }, + { + "name": "entity.name.variable.preprocessor.symbol.cs", + "match": "[_[:alpha:]][_[:alnum:]]*" + } + ] + }, + "preprocessor-app-directive-generic": { + "match": "\\b(.*)?\\s*", + "captures": { + "1": { + "name": "string.unquoted.preprocessor.message.cs" + } + } + }, "preprocessor-expression": { "patterns": [ { diff --git a/extensions/css-language-features/client/src/cssClient.ts b/extensions/css-language-features/client/src/cssClient.ts index 5f2bbd8dbd1..49bacd90a5c 100644 --- a/extensions/css-language-features/client/src/cssClient.ts +++ b/extensions/css-language-features/client/src/cssClient.ts @@ -83,8 +83,9 @@ export async function startClient(context: ExtensionContext, newLanguageClient: } return r; } - // eslint-disable-next-line local/code-no-any-casts - const isThenable = (obj: ProviderResult): obj is Thenable => obj && (obj)['then']; + function isThenable(obj: unknown): obj is Thenable { + return !!obj && typeof (obj as unknown as Thenable).then === 'function'; + } const r = next(document, position, context, token); if (isThenable(r)) { diff --git a/extensions/css-language-features/server/src/cssServer.ts b/extensions/css-language-features/server/src/cssServer.ts index c3ab75519c3..b46e20bb7c1 100644 --- a/extensions/css-language-features/server/src/cssServer.ts +++ b/extensions/css-language-features/server/src/cssServer.ts @@ -68,16 +68,15 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { - // eslint-disable-next-line local/code-no-any-casts - const initializationOptions = params.initializationOptions as any || {}; + const initializationOptions = params.initializationOptions || {}; - // eslint-disable-next-line local/code-no-any-casts - workspaceFolders = (params).workspaceFolders; - if (!Array.isArray(workspaceFolders)) { + if (!Array.isArray(params.workspaceFolders)) { workspaceFolders = []; if (params.rootPath) { workspaceFolders.push({ name: '', uri: URI.file(params.rootPath).toString(true) }); } + } else { + workspaceFolders = params.workspaceFolders; } requestService = getRequestService(initializationOptions?.handledSchemas || ['file'], connection, runtime); @@ -168,11 +167,10 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) // The settings have changed. Is send on server activation as well. connection.onDidChangeConfiguration(change => { - // eslint-disable-next-line local/code-no-any-casts - updateConfiguration(change.settings as any); + updateConfiguration(change.settings as { [languageId: string]: LanguageSettings }); }); - function updateConfiguration(settings: any) { + function updateConfiguration(settings: { [languageId: string]: LanguageSettings }) { for (const languageId in languageServices) { languageServices[languageId].configure(settings[languageId]); } diff --git a/extensions/debug-auto-launch/src/extension.ts b/extensions/debug-auto-launch/src/extension.ts index 7d06c56d47f..a17b47ecf7d 100644 --- a/extensions/debug-auto-launch/src/extension.ts +++ b/extensions/debug-auto-launch/src/extension.ts @@ -33,6 +33,8 @@ const TEXT_STATE_DESCRIPTION = { [State.Smart]: vscode.l10n.t("Auto attach when running scripts that aren't in a node_modules folder"), [State.OnlyWithFlag]: vscode.l10n.t('Only auto attach when the `--inspect` flag is given') }; + +const TEXT_TOGGLE_TITLE = vscode.l10n.t('Toggle Auto Attach'); const TEXT_TOGGLE_WORKSPACE = vscode.l10n.t('Toggle auto attach in this workspace'); const TEXT_TOGGLE_GLOBAL = vscode.l10n.t('Toggle auto attach on this machine'); const TEXT_TEMP_DISABLE = vscode.l10n.t('Temporarily disable auto attach in this session'); @@ -134,7 +136,8 @@ async function toggleAutoAttachSetting(context: vscode.ExtensionContext, scope?: quickPick.activeItems = isTemporarilyDisabled ? [items[0]] : quickPick.items.filter(i => 'state' in i && i.state === current); - quickPick.title = isGlobalScope ? TEXT_TOGGLE_GLOBAL : TEXT_TOGGLE_WORKSPACE; + quickPick.title = TEXT_TOGGLE_TITLE; + quickPick.placeholder = isGlobalScope ? TEXT_TOGGLE_GLOBAL : TEXT_TOGGLE_WORKSPACE; quickPick.buttons = [ { iconPath: new vscode.ThemeIcon(isGlobalScope ? 'folder' : 'globe'), diff --git a/extensions/docker/cgmanifest.json b/extensions/docker/cgmanifest.json index ddc1abe35f2..942ba14ebd8 100644 --- a/extensions/docker/cgmanifest.json +++ b/extensions/docker/cgmanifest.json @@ -6,13 +6,13 @@ "git": { "name": "language-docker", "repositoryUrl": "https://github.com/moby/moby", - "commitHash": "c2029cb2574647e4bc28ed58486b8e85883eedb9", - "tag": "28.0.0" + "commitHash": "bea959c7b793b32a893820b97c4eadc7c87fabb0", + "tag": "28.3.3" } }, "license": "Apache-2.0", "description": "The file syntaxes/docker.tmLanguage was included from https://github.com/moby/moby/blob/master/contrib/syntax/textmate/Docker.tmbundle/Syntaxes/Dockerfile.tmLanguage.", - "version": "28.0.0" + "version": "28.3.3" } ], "version": 1 diff --git a/extensions/dotenv/.vscodeignore b/extensions/dotenv/.vscodeignore new file mode 100644 index 00000000000..0a622e7e300 --- /dev/null +++ b/extensions/dotenv/.vscodeignore @@ -0,0 +1,2 @@ +test/** +cgmanifest.json diff --git a/extensions/dotenv/cgmanifest.json b/extensions/dotenv/cgmanifest.json new file mode 100644 index 00000000000..637e505549b --- /dev/null +++ b/extensions/dotenv/cgmanifest.json @@ -0,0 +1,40 @@ +{ + "registrations": [ + { + "component": { + "type": "git", + "git": { + "name": "dotenv-org/dotenv-vscode", + "repositoryUrl": "https://github.com/dotenv-org/dotenv-vscode", + "commitHash": "e7e41baa5b23e01c1ff0567a4e596c24860e7def" + } + }, + "licenseDetail": [ + "MIT License", + "", + "Copyright (c) 2022 Scott Motte", + "", + "Permission is hereby granted, free of charge, to any person obtaining a copy", + "of this software and associated documentation files (the \"Software\"), to deal", + "in the Software without restriction, including without limitation the rights", + "to use, copy, modify, merge, publish, distribute, sublicense, and/or sell", + "copies of the Software, and to permit persons to whom the Software is", + "furnished to do so, subject to the following conditions:", + "", + "The above copyright notice and this permission notice shall be included in all", + "copies or substantial portions of the Software.", + "", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR", + "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,", + "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", + "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER", + "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,", + "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE", + "SOFTWARE." + ], + "license": "MIT License", + "version": "0.26.0" + } + ], + "version": 1 +} \ No newline at end of file diff --git a/extensions/dotenv/language-configuration.json b/extensions/dotenv/language-configuration.json new file mode 100644 index 00000000000..77e01182ddd --- /dev/null +++ b/extensions/dotenv/language-configuration.json @@ -0,0 +1,24 @@ +{ + "comments": { + "lineComment": "#" + }, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +} diff --git a/extensions/dotenv/package.json b/extensions/dotenv/package.json new file mode 100644 index 00000000000..2adbc86ff36 --- /dev/null +++ b/extensions/dotenv/package.json @@ -0,0 +1,48 @@ +{ + "name": "dotenv", + "displayName": "%displayName%", + "description": "%description%", + "version": "1.0.0", + "publisher": "vscode", + "license": "MIT", + "engines": { + "vscode": "*" + }, + "scripts": { + "update-grammar": "node ../node_modules/vscode-grammar-updater/bin dotenv-org/dotenv-vscode syntaxes/dotenv.tmLanguage.json ./syntaxes/dotenv.tmLanguage.json" + }, + "categories": ["Programming Languages"], + "contributes": { + "languages": [ + { + "id": "dotenv", + "extensions": [ + ".env" + ], + "filenames": [ + ".env", + ".flaskenv", + "user-dirs.dirs" + ], + "filenamePatterns": [ + ".env.*" + ], + "aliases": [ + "Dotenv" + ], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "dotenv", + "scopeName": "source.dotenv", + "path": "./syntaxes/dotenv.tmLanguage.json" + } + ] + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/vscode.git" + } +} diff --git a/extensions/dotenv/package.nls.json b/extensions/dotenv/package.nls.json new file mode 100644 index 00000000000..acebc955157 --- /dev/null +++ b/extensions/dotenv/package.nls.json @@ -0,0 +1,4 @@ +{ + "displayName": "Dotenv Language Basics", + "description": "Provides syntax highlighting and bracket matching in dotenv files." +} diff --git a/extensions/dotenv/syntaxes/dotenv.tmLanguage.json b/extensions/dotenv/syntaxes/dotenv.tmLanguage.json new file mode 100644 index 00000000000..1cf105b0c18 --- /dev/null +++ b/extensions/dotenv/syntaxes/dotenv.tmLanguage.json @@ -0,0 +1,127 @@ +{ + "information_for_contributors": [ + "This file has been converted from https://github.com/dotenv-org/dotenv-vscode/blob/master/syntaxes/dotenv.tmLanguage.json", + "If you want to provide a fix or improvement, please create a pull request against the original repository.", + "Once accepted there, we are happy to receive an update request." + ], + "version": "https://github.com/dotenv-org/dotenv-vscode/commit/e7e41baa5b23e01c1ff0567a4e596c24860e7def", + "scopeName": "source.dotenv", + "patterns": [ + { + "comment": "Full Line Comment", + "match": "^\\s?(#.*$)\\n", + "captures": { + "1": { + "patterns": [ + { + "include": "#line-comment" + } + ] + } + } + }, + { + "comment": "ENV entry", + "match": "^\\s?(.*?)\\s?(\\=)(.*)$", + "captures": { + "1": { + "patterns": [ + { + "include": "#key" + } + ] + }, + "2": { + "name": "keyword.operator.assignment.dotenv" + }, + "3": { + "name": "property.value.dotenv", + "patterns": [ + { + "include": "#line-comment" + }, + { + "include": "#double-quoted-string" + }, + { + "include": "#single-quoted-string" + }, + { + "include": "#interpolation" + } + ] + } + } + } + ], + "repository": { + "variable": { + "comment": "env variable", + "match": "[a-zA-Z_]+[a-zA-Z0-9_]*" + }, + "line-comment": { + "comment": "Comment", + "match": "#.*$", + "name": "comment.line.dotenv" + }, + "interpolation": { + "comment": "Interpolation (variable substitution)", + "match": "(\\$\\{)(.*)(\\})", + "captures": { + "1": { + "name": "keyword.interpolation.begin.dotenv" + }, + "2": { + "name": "variable.interpolation.dotenv" + }, + "3": { + "name": "keyword.interpolation.end.dotenv" + } + } + }, + "escape-characters": { + "comment": "Escape characters", + "match": "\\\\[nrtfb\"'\\\\]|\\\\u[0123456789ABCDEF]{4}", + "name": "constant.character.escape.dotenv" + }, + "double-quoted-string": { + "comment": "Double Quoted String", + "match": "\"(.*)\"", + "name": "string.quoted.double.dotenv", + "captures": { + "1": { + "patterns": [ + { + "include": "#interpolation" + }, + { + "include": "#escape-characters" + } + ] + } + } + }, + "single-quoted-string": { + "comment": "Single Quoted String", + "match": "'(.*)'", + "name": "string.quoted.single.dotenv" + }, + "key": { + "comment": "Key", + "match": "(export\\s)?(.*)", + "captures": { + "1": { + "name": "keyword.key.export.dotenv" + }, + "2": { + "name": "variable.key.dotenv", + "patterns": [ + { + "include": "#variable" + } + ] + } + } + } + } +} \ No newline at end of file diff --git a/extensions/emmet/src/test/completion.test.ts b/extensions/emmet/src/test/completion.test.ts index 4f74ba92e25..bf61f338f21 100644 --- a/extensions/emmet/src/test/completion.test.ts +++ b/extensions/emmet/src/test/completion.test.ts @@ -41,14 +41,14 @@ suite('Tests for completion in CSS embedded in HTML', () => { { label: 'widows: ;', documentation: `widows: |;` } ]); } catch (e) { - assert.strictEqual(e.message, "Didn't find completion item with label widows: ;"); + assert.strictEqual(e.message, `Didn't find completion item with label widows: ;`); } try { await testCompletionProvider('css', `.foo { wid| }`, [ { label: 'widows: ;', documentation: `widows: |;` } ]); } catch (e) { - assert.strictEqual(e.message, "Didn't find completion item with label widows: ;"); + assert.strictEqual(e.message, `Didn't find completion item with label widows: ;`); } await testCompletionProvider('css', `.foo { wido| }`, [ { label: 'widows: ;', documentation: `widows: |;` } diff --git a/extensions/extension-editing/src/extensionLinter.ts b/extensions/extension-editing/src/extensionLinter.ts index be7eea1a49b..187100b563f 100644 --- a/extensions/extension-editing/src/extensionLinter.ts +++ b/extensions/extension-editing/src/extensionLinter.ts @@ -33,7 +33,7 @@ const dataUrlsNotValid = l10n.t("Data URLs are not a valid image source."); const relativeUrlRequiresHttpsRepository = l10n.t("Relative image URLs require a repository with HTTPS protocol to be specified in the package.json."); const relativeBadgeUrlRequiresHttpsRepository = l10n.t("Relative badge URLs require a repository with HTTPS protocol to be specified in this package.json."); const apiProposalNotListed = l10n.t("This proposal cannot be used because for this extension the product defines a fixed set of API proposals. You can test your extension but before publishing you MUST reach out to the VS Code team."); -const bumpEngineForImplicitActivationEvents = l10n.t("This activation event can be removed for extensions targeting engine version ^1.75 as VS Code will generate these automatically from your package.json contribution declarations."); +const bumpEngineForImplicitActivationEvents = l10n.t("This activation event can be removed for extensions targeting engine version ^1.75.0 as VS Code will generate these automatically from your package.json contribution declarations."); const starActivation = l10n.t("Using '*' activation is usually a bad idea as it impacts performance."); const parsingErrorHeader = l10n.t("Error parsing the when-clause:"); diff --git a/extensions/git-base/languages/ignore.language-configuration.json b/extensions/git-base/languages/ignore.language-configuration.json index ad8b8ee5cd8..03e8ed3611c 100644 --- a/extensions/git-base/languages/ignore.language-configuration.json +++ b/extensions/git-base/languages/ignore.language-configuration.json @@ -8,7 +8,6 @@ { "open": "(", "close": ")" }, { "open": "'", "close": "'", "notIn": ["string", "comment"] }, { "open": "\"", "close": "\"", "notIn": ["string"] }, - { "open": "`", "close": "`", "notIn": ["string", "comment"] }, - { "open": "/**", "close": " */", "notIn": ["string"] } + { "open": "`", "close": "`", "notIn": ["string", "comment"] } ] } diff --git a/extensions/git-base/src/api/api1.ts b/extensions/git-base/src/api/api1.ts index 049951c62e8..19038bc1eec 100644 --- a/extensions/git-base/src/api/api1.ts +++ b/extensions/git-base/src/api/api1.ts @@ -14,8 +14,7 @@ export class ApiImpl implements API { constructor(private _model: Model) { } pickRemoteSource(options: PickRemoteSourceOptions): Promise { - // eslint-disable-next-line local/code-no-any-casts - return pickRemoteSource(this._model, options as any); + return pickRemoteSource(this._model, options); } getRemoteSourceActions(url: string): Promise { @@ -31,12 +30,11 @@ export function registerAPICommands(extension: GitBaseExtensionImpl): Disposable const disposables: Disposable[] = []; disposables.push(commands.registerCommand('git-base.api.getRemoteSources', (opts?: PickRemoteSourceOptions) => { - if (!extension.model) { + if (!extension.model || !opts) { return; } - // eslint-disable-next-line local/code-no-any-casts - return pickRemoteSource(extension.model, opts as any); + return pickRemoteSource(extension.model, opts); })); return Disposable.from(...disposables); diff --git a/extensions/git-base/src/extension.ts b/extensions/git-base/src/extension.ts index 17ffb89f82d..453d8f7850f 100644 --- a/extensions/git-base/src/extension.ts +++ b/extensions/git-base/src/extension.ts @@ -3,14 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionContext } from 'vscode'; +import { ExtensionContext, languages } from 'vscode'; import { registerAPICommands } from './api/api1'; import { GitBaseExtensionImpl } from './api/extension'; import { Model } from './model'; +import { GitCommitFoldingProvider } from './foldingProvider'; export function activate(context: ExtensionContext): GitBaseExtensionImpl { const apiImpl = new GitBaseExtensionImpl(new Model()); context.subscriptions.push(registerAPICommands(apiImpl)); + // Register folding provider for git-commit language + context.subscriptions.push( + languages.registerFoldingRangeProvider('git-commit', new GitCommitFoldingProvider()) + ); + return apiImpl; } diff --git a/extensions/git-base/src/foldingProvider.ts b/extensions/git-base/src/foldingProvider.ts new file mode 100644 index 00000000000..b1c1cc45171 --- /dev/null +++ b/extensions/git-base/src/foldingProvider.ts @@ -0,0 +1,92 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +export class GitCommitFoldingProvider implements vscode.FoldingRangeProvider { + + provideFoldingRanges( + document: vscode.TextDocument, + _context: vscode.FoldingContext, + _token: vscode.CancellationToken + ): vscode.ProviderResult { + const ranges: vscode.FoldingRange[] = []; + + let commentBlockStart: number | undefined; + let currentDiffStart: number | undefined; + + for (let i = 0; i < document.lineCount; i++) { + const line = document.lineAt(i); + const lineText = line.text; + + // Check for comment lines (lines starting with #) + if (lineText.startsWith('#')) { + // Close any active diff block when we encounter a comment + if (currentDiffStart !== undefined) { + // Only create fold if there are at least 2 lines + if (i - currentDiffStart > 1) { + ranges.push(new vscode.FoldingRange(currentDiffStart, i - 1)); + } + currentDiffStart = undefined; + } + + if (commentBlockStart === undefined) { + commentBlockStart = i; + } + } else { + // End of comment block + if (commentBlockStart !== undefined) { + // Only create fold if there are at least 2 lines + if (i - commentBlockStart > 1) { + ranges.push(new vscode.FoldingRange( + commentBlockStart, + i - 1, + vscode.FoldingRangeKind.Comment + )); + } + commentBlockStart = undefined; + } + } + + // Check for diff sections (lines starting with "diff --git") + if (lineText.startsWith('diff --git ')) { + // If there's a previous diff block, close it + if (currentDiffStart !== undefined) { + // Only create fold if there are at least 2 lines + if (i - currentDiffStart > 1) { + ranges.push(new vscode.FoldingRange(currentDiffStart, i - 1)); + } + } + // Start new diff block + currentDiffStart = i; + } + } + + // Handle end-of-document cases + + // If comment block extends to end of document + if (commentBlockStart !== undefined) { + if (document.lineCount - commentBlockStart > 1) { + ranges.push(new vscode.FoldingRange( + commentBlockStart, + document.lineCount - 1, + vscode.FoldingRangeKind.Comment + )); + } + } + + // If diff block extends to end of document + if (currentDiffStart !== undefined) { + if (document.lineCount - currentDiffStart > 1) { + ranges.push(new vscode.FoldingRange( + currentDiffStart, + document.lineCount - 1 + )); + } + } + + return ranges; + } +} diff --git a/extensions/git-base/src/remoteSource.ts b/extensions/git-base/src/remoteSource.ts index eb86b27367a..9c6f1b02fa4 100644 --- a/extensions/git-base/src/remoteSource.ts +++ b/extensions/git-base/src/remoteSource.ts @@ -123,6 +123,7 @@ export async function getRemoteSourceActions(model: Model, url: string): Promise return remoteSourceActions; } +export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions): Promise; export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch?: false | undefined }): Promise; export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions & { branch: true }): Promise; export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions = {}): Promise { diff --git a/extensions/git-base/src/test/foldingProvider.test.ts b/extensions/git-base/src/test/foldingProvider.test.ts new file mode 100644 index 00000000000..69f7d35bf18 --- /dev/null +++ b/extensions/git-base/src/test/foldingProvider.test.ts @@ -0,0 +1,258 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'mocha'; +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { GitCommitFoldingProvider } from '../foldingProvider'; + +suite('GitCommitFoldingProvider', () => { + + function createMockDocument(content: string): vscode.TextDocument { + const lines = content.split('\n'); + return { + lineCount: lines.length, + lineAt: (index: number) => ({ + text: lines[index] || '', + lineNumber: index + }), + } as vscode.TextDocument; + } + + const mockContext: vscode.FoldingContext = {} as vscode.FoldingContext; + const mockToken: vscode.CancellationToken = { isCancellationRequested: false } as vscode.CancellationToken; + + test('empty document returns no folding ranges', () => { + const provider = new GitCommitFoldingProvider(); + const doc = createMockDocument(''); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken); + + assert.strictEqual(Array.isArray(ranges) ? ranges.length : 0, 0); + }); + + test('single line document returns no folding ranges', () => { + const provider = new GitCommitFoldingProvider(); + const doc = createMockDocument('commit message'); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken); + + assert.strictEqual(Array.isArray(ranges) ? ranges.length : 0, 0); + }); + + test('single comment line returns no folding ranges', () => { + const provider = new GitCommitFoldingProvider(); + const doc = createMockDocument('# Comment'); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken); + + assert.strictEqual(Array.isArray(ranges) ? ranges.length : 0, 0); + }); + + test('two comment lines create one folding range', () => { + const provider = new GitCommitFoldingProvider(); + const content = '# Comment 1\n# Comment 2'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 1); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + }); + + test('multiple comment lines create one folding range', () => { + const provider = new GitCommitFoldingProvider(); + const content = '# Comment 1\n# Comment 2\n# Comment 3\n# Comment 4'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 3); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + }); + + test('comment block followed by content', () => { + const provider = new GitCommitFoldingProvider(); + const content = '# Comment 1\n# Comment 2\nCommit message'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 1); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + }); + + test('comment block at end of document', () => { + const provider = new GitCommitFoldingProvider(); + const content = 'Commit message\n\n# Comment 1\n# Comment 2'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 2); + assert.strictEqual(ranges[0].end, 3); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + }); + + test('multiple separated comment blocks', () => { + const provider = new GitCommitFoldingProvider(); + const content = '# Comment 1\n# Comment 2\n\nCommit message\n\n# Comment 3\n# Comment 4'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 2); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 1); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + assert.strictEqual(ranges[1].start, 5); + assert.strictEqual(ranges[1].end, 6); + assert.strictEqual(ranges[1].kind, vscode.FoldingRangeKind.Comment); + }); + + test('single diff line returns no folding ranges', () => { + const provider = new GitCommitFoldingProvider(); + const doc = createMockDocument('diff --git a/file.txt b/file.txt'); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken); + + assert.strictEqual(Array.isArray(ranges) ? ranges.length : 0, 0); + }); + + test('diff block with content creates folding range', () => { + const provider = new GitCommitFoldingProvider(); + const content = 'diff --git a/file.txt b/file.txt\nindex 1234..5678\n--- a/file.txt\n+++ b/file.txt'; + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 3); + assert.strictEqual(ranges[0].kind, undefined); // Diff blocks don't have a specific kind + }); + + test('multiple diff blocks', () => { + const provider = new GitCommitFoldingProvider(); + const content = [ + 'diff --git a/file1.txt b/file1.txt', + '--- a/file1.txt', + '+++ b/file1.txt', + 'diff --git a/file2.txt b/file2.txt', + '--- a/file2.txt', + '+++ b/file2.txt' + ].join('\n'); + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 2); + assert.strictEqual(ranges[0].start, 0); + assert.strictEqual(ranges[0].end, 2); + assert.strictEqual(ranges[1].start, 3); + assert.strictEqual(ranges[1].end, 5); + }); + + test('diff block at end of document', () => { + const provider = new GitCommitFoldingProvider(); + const content = [ + 'Commit message', + '', + 'diff --git a/file.txt b/file.txt', + '--- a/file.txt', + '+++ b/file.txt' + ].join('\n'); + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 1); + assert.strictEqual(ranges[0].start, 2); + assert.strictEqual(ranges[0].end, 4); + }); + + test('realistic git commit message with comments and verbose diff', () => { + const provider = new GitCommitFoldingProvider(); + const content = [ + 'Add folding support for git commit messages', + '', + '# Please enter the commit message for your changes. Lines starting', + '# with \'#\' will be ignored, and an empty message aborts the commit.', + '#', + '# On branch main', + '# Changes to be committed:', + '#\tmodified: extension.ts', + '#\tnew file: foldingProvider.ts', + '#', + '# ------------------------ >8 ------------------------', + '# Do not modify or remove the line above.', + '# Everything below it will be ignored.', + 'diff --git a/extensions/git-base/src/extension.ts b/extensions/git-base/src/extension.ts', + 'index 17ffb89..453d8f7 100644', + '--- a/extensions/git-base/src/extension.ts', + '+++ b/extensions/git-base/src/extension.ts', + '@@ -3,14 +3,20 @@', + ' * Licensed under the MIT License.', + '-import { ExtensionContext } from \'vscode\';', + '+import { ExtensionContext, languages } from \'vscode\';', + 'diff --git a/extensions/git-base/src/foldingProvider.ts b/extensions/git-base/src/foldingProvider.ts', + 'new file mode 100644', + 'index 0000000..2c4a9c3', + '--- /dev/null', + '+++ b/extensions/git-base/src/foldingProvider.ts' + ].join('\n'); + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + // Should have one comment block and two diff blocks + assert.strictEqual(ranges.length, 3); + + // Comment block (lines 2-12) + assert.strictEqual(ranges[0].start, 2); + assert.strictEqual(ranges[0].end, 12); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + + // First diff block (lines 13-20) + assert.strictEqual(ranges[1].start, 13); + assert.strictEqual(ranges[1].end, 20); + assert.strictEqual(ranges[1].kind, undefined); + + // Second diff block (lines 21-25) + assert.strictEqual(ranges[2].start, 21); + assert.strictEqual(ranges[2].end, 25); + assert.strictEqual(ranges[2].kind, undefined); + }); + + test('mixed comment and diff content', () => { + const provider = new GitCommitFoldingProvider(); + const content = [ + 'Fix bug in parser', + '', + '# Comment 1', + '# Comment 2', + '', + 'diff --git a/file.txt b/file.txt', + '--- a/file.txt', + '+++ b/file.txt', + '', + '# Comment 3', + '# Comment 4' + ].join('\n'); + const doc = createMockDocument(content); + const ranges = provider.provideFoldingRanges(doc, mockContext, mockToken) as vscode.FoldingRange[]; + + assert.strictEqual(ranges.length, 3); + + // First comment block + assert.strictEqual(ranges[0].start, 2); + assert.strictEqual(ranges[0].end, 3); + assert.strictEqual(ranges[0].kind, vscode.FoldingRangeKind.Comment); + + // Diff block + assert.strictEqual(ranges[1].start, 5); + assert.strictEqual(ranges[1].end, 8); + assert.strictEqual(ranges[1].kind, undefined); + + // Second comment block + assert.strictEqual(ranges[2].start, 9); + assert.strictEqual(ranges[2].end, 10); + assert.strictEqual(ranges[2].kind, vscode.FoldingRangeKind.Comment); + }); +}); diff --git a/extensions/git/package.json b/extensions/git/package.json index 03013a0f90f..79e40433e56 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -16,6 +16,8 @@ "contribMergeEditorMenus", "contribMultiDiffEditorMenus", "contribDiffEditorGutterToolBarMenus", + "contribSourceControlArtifactGroupMenu", + "contribSourceControlArtifactMenu", "contribSourceControlHistoryItemMenu", "contribSourceControlHistoryTitleMenu", "contribSourceControlInputBoxMenu", @@ -26,6 +28,7 @@ "quickInputButtonLocation", "quickPickSortByLabel", "scmActionButton", + "scmArtifactProvider", "scmHistoryProvider", "scmMultiDiffEditor", "scmProviderOptions", @@ -547,6 +550,7 @@ { "command": "git.createTag", "title": "%command.createTag%", + "icon": "$(plus)", "category": "Git", "enablement": "!operationInProgress" }, @@ -568,6 +572,12 @@ "category": "Git", "enablement": "!operationInProgress" }, + { + "command": "git.createWorktreeWithDefaults", + "title": "Create Worktree With Defaults", + "category": "Git", + "enablement": "!operationInProgress" + }, { "command": "git.deleteWorktree", "title": "%command.deleteWorktree%", @@ -998,6 +1008,87 @@ "command": "git.blame.toggleStatusBarItem", "title": "%command.blameToggleStatusBarItem%", "category": "Git" + }, + { + "command": "git.graph.compareRef", + "title": "%command.graphCompareRef%", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.graph.compareWithRemote", + "title": "%command.graphCompareWithRemote%", + "category": "Git", + "enablement": "!operationInProgress && scmCurrentHistoryItemRefHasRemote" + }, + { + "command": "git.graph.compareWithMergeBase", + "title": "%command.graphCompareWithMergeBase%", + "category": "Git", + "enablement": "!operationInProgress && scmCurrentHistoryItemRefHasBase" + }, + { + "command": "git.repositories.checkout", + "title": "%command.graphCheckout%", + "icon": "$(target)", + "category": "Git", + "enablement": "!operationInProgress && !scmArtifactIsHistoryItemRef" + }, + { + "command": "git.repositories.checkoutDetached", + "title": "%command.graphCheckoutDetached%", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.compareRef", + "title": "%command.graphCompareRef%", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.createBranch", + "title": "%command.branch%", + "icon": "$(plus)", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.createTag", + "title": "%command.createTag%", + "icon": "$(plus)", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.merge", + "title": "%command.merge2%", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.rebase", + "title": "%command.rebase2%", + "category": "Git", + "enablement": "!operationInProgress" + }, + { + "command": "git.repositories.deleteBranch", + "title": "%command.deleteRef%", + "category": "Git", + "enablement": "!operationInProgress && !scmArtifactIsHistoryItemRef" + }, + { + "command": "git.repositories.deleteTag", + "title": "%command.deleteRef%", + "category": "Git", + "enablement": "!operationInProgress && !scmArtifactIsHistoryItemRef" + }, + { + "command": "git.repositories.createFrom", + "title": "%command.createFrom%", + "category": "Git", + "enablement": "!operationInProgress" } ], "continueEditSession": [ @@ -1594,6 +1685,10 @@ "command": "git.graph.deleteBranch", "when": "false" }, + { + "command": "git.graph.compareRef", + "when": "false" + }, { "command": "git.graph.deleteTag", "when": "false" @@ -1602,6 +1697,14 @@ "command": "git.graph.cherryPick", "when": "false" }, + { + "command": "git.graph.compareWithMergeBase", + "when": "false" + }, + { + "command": "git.graph.compareWithRemote", + "when": "false" + }, { "command": "git.diff.stageHunk", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && diffEditorOriginalUri =~ /^git\\:.*%22ref%22%3A%22~%22%7D$/" @@ -1609,6 +1712,46 @@ { "command": "git.diff.stageSelection", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && diffEditorOriginalUri =~ /^git\\:.*%22ref%22%3A%22~%22%7D$/" + }, + { + "command": "git.repositories.checkout", + "when": "false" + }, + { + "command": "git.repositories.checkoutDetached", + "when": "false" + }, + { + "command": "git.repositories.compareRef", + "when": "false" + }, + { + "command": "git.repositories.createBranch", + "when": "false" + }, + { + "command": "git.repositories.createTag", + "when": "false" + }, + { + "command": "git.repositories.merge", + "when": "false" + }, + { + "command": "git.repositories.rebase", + "when": "false" + }, + { + "command": "git.repositories.deleteBranch", + "when": "false" + }, + { + "command": "git.repositories.deleteTag", + "when": "false" + }, + { + "command": "git.repositories.createFrom", + "when": "false" } ], "scm/title": [ @@ -1693,13 +1836,85 @@ "when": "scmProvider == git" } ], - "scm/sourceControl/title": [ + "scm/repositories/title": [ { "command": "git.reopenClosedRepositories", "group": "navigation@1", "when": "git.closedRepositoryCount > 0" } ], + "scm/repository": [ + { + "command": "git.pull", + "group": "1_header@1", + "when": "scmProvider == git" + }, + { + "command": "git.push", + "group": "1_header@2", + "when": "scmProvider == git" + }, + { + "command": "git.clone", + "group": "1_header@3", + "when": "scmProvider == git" + }, + { + "command": "git.checkout", + "group": "1_header@4", + "when": "scmProvider == git" + }, + { + "command": "git.fetch", + "group": "1_header@5", + "when": "scmProvider == git" + }, + { + "submenu": "git.commit", + "group": "2_main@1", + "when": "scmProvider == git" + }, + { + "submenu": "git.changes", + "group": "2_main@2", + "when": "scmProvider == git" + }, + { + "submenu": "git.pullpush", + "group": "2_main@3", + "when": "scmProvider == git" + }, + { + "submenu": "git.branch", + "group": "2_main@4", + "when": "scmProvider == git" + }, + { + "submenu": "git.remotes", + "group": "2_main@5", + "when": "scmProvider == git" + }, + { + "submenu": "git.stash", + "group": "2_main@6", + "when": "scmProvider == git" + }, + { + "submenu": "git.tags", + "group": "2_main@7", + "when": "scmProvider == git" + }, + { + "submenu": "git.worktrees", + "group": "2_main@8", + "when": "scmProvider == git" + }, + { + "command": "git.showOutput", + "group": "3_footer", + "when": "scmProvider == git" + } + ], "scm/sourceControl": [ { "command": "git.close", @@ -1727,6 +1942,65 @@ "when": "scmProvider == git && scmProviderContext == worktree" } ], + "scm/artifactGroup/context": [ + { + "command": "git.repositories.createBranch", + "group": "inline@1", + "when": "scmProvider == git && scmArtifactGroup == branches" + }, + { + "command": "git.repositories.createTag", + "group": "inline@1", + "when": "scmProvider == git && scmArtifactGroup == tags" + } + ], + "scm/artifact/context": [ + { + "command": "git.repositories.checkout", + "group": "inline@1", + "when": "scmProvider == git" + }, + { + "command": "git.repositories.checkout", + "group": "1_checkout@1", + "when": "scmProvider == git" + }, + { + "command": "git.repositories.checkoutDetached", + "group": "1_checkout@2", + "when": "scmProvider == git" + }, + { + "command": "git.repositories.merge", + "group": "2_modify@1", + "when": "scmProvider == git && scmArtifactGroupId == branches" + }, + { + "command": "git.repositories.rebase", + "group": "2_modify@2", + "when": "scmProvider == git && scmArtifactGroupId == branches" + }, + { + "command": "git.repositories.createFrom", + "group": "3_modify@1", + "when": "scmProvider == git && scmArtifactGroupId == branches" + }, + { + "command": "git.repositories.deleteBranch", + "group": "3_modify@2", + "when": "scmProvider == git && scmArtifactGroupId == branches" + }, + { + "command": "git.repositories.deleteTag", + "group": "3_modify@1", + "when": "scmProvider == git && scmArtifactGroupId == tags" + }, + { + "command": "git.repositories.compareRef", + "group": "4_compare@1", + "when": "scmProvider == git" + } + ], "scm/resourceGroup/context": [ { "command": "git.stageAllMerge", @@ -2171,6 +2445,21 @@ "when": "scmProvider == git", "group": "4_modify@1" }, + { + "command": "git.graph.compareWithRemote", + "when": "scmProvider == git", + "group": "5_compare@1" + }, + { + "command": "git.graph.compareWithMergeBase", + "when": "scmProvider == git", + "group": "5_compare@2" + }, + { + "command": "git.graph.compareRef", + "when": "scmProvider == git", + "group": "5_compare@3" + }, { "command": "git.copyCommitId", "when": "scmProvider == git && !listMultiSelection", @@ -2210,6 +2499,11 @@ "group": "navigation", "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && isInNotebookTextDiffEditor && resourceScheme =~ /^git$|^file$/" }, + { + "command": "git.openFile", + "group": "navigation", + "when": "config.git.enabled && !git.missing && gitOpenRepositoryCount != 0 && !isInDiffEditor && !isInNotebookTextDiffEditor && resourceScheme == git" + }, { "command": "git.openChange", "group": "navigation@2", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index ae4159e566d..4d037b40220 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -74,8 +74,11 @@ "command.cherryPick": "Cherry Pick...", "command.cherryPickAbort": "Abort Cherry Pick", "command.merge": "Merge...", + "command.merge2": "Merge", "command.mergeAbort": "Abort Merge", "command.rebase": "Rebase Branch...", + "command.rebase2": "Rebase", + "command.createFrom": "Create from...", "command.createTag": "Create Tag...", "command.deleteTag": "Delete Tag...", "command.migrateWorktreeChanges": "Migrate Worktree Changes...", @@ -137,6 +140,10 @@ "command.graphCherryPick": "Cherry Pick", "command.graphDeleteBranch": "Delete Branch", "command.graphDeleteTag": "Delete Tag", + "command.graphCompareRef": "Compare with...", + "command.graphCompareWithMergeBase": "Compare with Merge Base", + "command.graphCompareWithRemote": "Compare with Remote", + "command.deleteRef": "Delete", "command.blameToggleEditorDecoration": "Toggle Git Blame Editor Decoration", "command.blameToggleStatusBarItem": "Toggle Git Blame Status Bar Item", "command.api.getRepositories": "Get Repositories", diff --git a/extensions/git/src/api/api1.ts b/extensions/git/src/api/api1.ts index 2be6cec8dea..466a0e6510f 100644 --- a/extensions/git/src/api/api1.ts +++ b/extensions/git/src/api/api1.ts @@ -7,7 +7,7 @@ import { Model } from '../model'; import { Repository as BaseRepository, Resource } from '../repository'; -import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, ForcePushMode, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, RefType, CredentialsProvider, BranchQuery, PushErrorHandler, PublishEvent, FetchOptions, RemoteSourceProvider, RemoteSourcePublisher, PostCommitCommandsProvider, RefQuery, BranchProtectionProvider, InitOptions, SourceControlHistoryItemDetailsProvider, GitErrorCodes } from './git'; +import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, ForcePushMode, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, RefType, CredentialsProvider, BranchQuery, PushErrorHandler, PublishEvent, FetchOptions, RemoteSourceProvider, RemoteSourcePublisher, PostCommitCommandsProvider, RefQuery, BranchProtectionProvider, InitOptions, SourceControlHistoryItemDetailsProvider, GitErrorCodes, CloneOptions, CommitShortStat } from './git'; import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands, CancellationToken } from 'vscode'; import { combinedDisposable, filterEvent, mapEvent } from '../util'; import { toGitUri } from '../uri'; @@ -15,6 +15,7 @@ import { GitExtensionImpl } from './extension'; import { GitBaseApi } from '../git-base'; import { PickRemoteSourceOptions } from '../typings/git-base'; import { OperationKind, OperationResult } from '../operation'; +import { CloneManager } from '../cloneManager'; class ApiInputBox implements InputBox { #inputBox: SourceControlInputBox; @@ -162,6 +163,10 @@ export class ApiRepository implements Repository { return this.#repository.diffWithHEAD(path); } + diffWithHEADShortStats(path?: string): Promise { + return this.#repository.diffWithHEADShortStats(path); + } + diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; diffWith(ref: string, path?: string): Promise { @@ -174,6 +179,10 @@ export class ApiRepository implements Repository { return this.#repository.diffIndexWithHEAD(path); } + diffIndexWithHEADShortStats(path?: string): Promise { + return this.#repository.diffIndexWithHEADShortStats(path); + } + diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffIndexWith(ref: string, path?: string): Promise { @@ -331,10 +340,12 @@ export class ApiGit implements Git { export class ApiImpl implements API { #model: Model; + #cloneManager: CloneManager; readonly git: ApiGit; - constructor(model: Model) { - this.#model = model; + constructor(privates: { model: Model; cloneManager: CloneManager }) { + this.#model = privates.model; + this.#cloneManager = privates.cloneManager; this.git = new ApiGit(this.#model); } @@ -392,6 +403,11 @@ export class ApiImpl implements API { } } + async getRepositoryWorkspace(uri: Uri): Promise { + const workspaces = this.#model.repositoryCache.get(uri.toString()); + return workspaces ? workspaces.map(r => Uri.file(r.workspacePath)) : null; + } + async init(root: Uri, options?: InitOptions): Promise { const path = root.fsPath; await this.#model.git.init(path, options); @@ -399,6 +415,12 @@ export class ApiImpl implements API { return this.getRepository(root) || null; } + async clone(uri: Uri, options?: CloneOptions): Promise { + const parentPath = options?.parentPath?.fsPath; + const result = await this.#cloneManager.clone(uri.toString(), { parentPath, recursive: options?.recursive, ref: options?.ref, postCloneAction: options?.postCloneAction }); + return result ? Uri.file(result) : null; + } + async openRepository(root: Uri): Promise { if (root.scheme !== 'file') { return null; diff --git a/extensions/git/src/api/extension.ts b/extensions/git/src/api/extension.ts index d381ebc7f64..a716fa00dae 100644 --- a/extensions/git/src/api/extension.ts +++ b/extensions/git/src/api/extension.ts @@ -7,14 +7,15 @@ import { Model } from '../model'; import { GitExtension, Repository, API } from './git'; import { ApiRepository, ApiImpl } from './api1'; import { Event, EventEmitter } from 'vscode'; +import { CloneManager } from '../cloneManager'; -function deprecated(original: any, context: ClassMemberDecoratorContext) { - if (context.kind !== 'method') { +function deprecated(original: unknown, context: ClassMemberDecoratorContext) { + if (typeof original !== 'function' || context.kind !== 'method') { throw new Error('not supported'); } const key = context.name.toString(); - return function (this: any, ...args: any[]): any { + return function (this: unknown, ...args: unknown[]) { console.warn(`Git extension API method '${key}' is deprecated.`); return original.apply(this, args); }; @@ -28,6 +29,7 @@ export class GitExtensionImpl implements GitExtension { readonly onDidChangeEnablement: Event = this._onDidChangeEnablement.event; private _model: Model | undefined = undefined; + private _cloneManager: CloneManager | undefined = undefined; set model(model: Model | undefined) { this._model = model; @@ -46,10 +48,15 @@ export class GitExtensionImpl implements GitExtension { return this._model; } - constructor(model?: Model) { - if (model) { + set cloneManager(cloneManager: CloneManager | undefined) { + this._cloneManager = cloneManager; + } + + constructor(privates?: { model: Model; cloneManager: CloneManager }) { + if (privates) { this.enabled = true; - this._model = model; + this._model = privates.model; + this._cloneManager = privates.cloneManager; } } @@ -72,7 +79,7 @@ export class GitExtensionImpl implements GitExtension { } getAPI(version: number): API { - if (!this._model) { + if (!this._model || !this._cloneManager) { throw new Error('Git model not found'); } @@ -80,6 +87,6 @@ export class GitExtensionImpl implements GitExtension { throw new Error(`No API version ${version} found.`); } - return new ApiImpl(this._model); + return new ApiImpl({ model: this._model, cloneManager: this._cloneManager }); } } diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index fdfb8b397bc..6ba850dd7f6 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -183,6 +183,19 @@ export interface InitOptions { defaultBranch?: string; } +export interface CloneOptions { + parentPath?: Uri; + /** + * ref is only used if the repository cache is missed. + */ + ref?: string; + recursive?: boolean; + /** + * If no postCloneAction is provided, then the users setting for git.openAfterClone is used. + */ + postCloneAction?: 'none'; +} + export interface RefQuery { readonly contains?: string; readonly count?: number; @@ -224,10 +237,12 @@ export interface Repository { diff(cached?: boolean): Promise; diffWithHEAD(): Promise; diffWithHEAD(path: string): Promise; + diffWithHEADShortStats(path?: string): Promise; diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; diffIndexWithHEAD(): Promise; diffIndexWithHEAD(path: string): Promise; + diffIndexWithHEADShortStats(path?: string): Promise; diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffBlobs(object1: string, object2: string): Promise; @@ -249,7 +264,7 @@ export interface Repository { getMergeBase(ref1: string, ref2: string): Promise; - tag(name: string, upstream: string): Promise; + tag(name: string, message: string, ref?: string | undefined): Promise; deleteTag(name: string): Promise; status(): Promise; @@ -365,8 +380,15 @@ export interface API { toGitUri(uri: Uri, ref: string): Uri; getRepository(uri: Uri): Repository | null; getRepositoryRoot(uri: Uri): Promise; + getRepositoryWorkspace(uri: Uri): Promise; init(root: Uri, options?: InitOptions): Promise; - openRepository(root: Uri): Promise + /** + * Checks the cache of known cloned repositories, and clones if the repository is not found. + * Make sure to pass `postCloneAction` 'none' if you want to have the uri where you can find the repository returned. + * @returns The URI of a folder or workspace file which, when opened, will open the cloned repository. + */ + clone(uri: Uri, options?: CloneOptions): Promise; + openRepository(root: Uri): Promise; registerRemoteSourcePublisher(publisher: RemoteSourcePublisher): Disposable; registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable; diff --git a/extensions/git/src/artifactProvider.ts b/extensions/git/src/artifactProvider.ts new file mode 100644 index 00000000000..8c56210e062 --- /dev/null +++ b/extensions/git/src/artifactProvider.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LogOutputChannel, SourceControlArtifactProvider, SourceControlArtifactGroup, SourceControlArtifact, Event, EventEmitter, ThemeIcon, l10n, workspace, Uri, Disposable } from 'vscode'; +import { dispose, fromNow, IDisposable } from './util'; +import { Repository } from './repository'; +import { Ref, RefType } from './api/git'; + +function getArtifactDescription(ref: Ref, shortCommitLength: number): string { + const segments: string[] = []; + if (ref.commitDetails?.commitDate) { + segments.push(fromNow(ref.commitDetails.commitDate)); + } + if (ref.commit) { + segments.push(ref.commit.substring(0, shortCommitLength)); + } + if (ref.commitDetails?.message) { + segments.push(ref.commitDetails.message.split('\n')[0]); + } + + return segments.join(' \u2022 '); +} + +/** + * Sorts refs like a directory tree: refs with more path segments (directories) appear first + * and are sorted alphabetically, while refs at the same level (files) maintain insertion order. + * Refs without '/' maintain their insertion order and appear after refs with '/'. + */ +function sortRefByName(refA: Ref, refB: Ref): number { + const nameA = refA.name ?? ''; + const nameB = refB.name ?? ''; + + const lastSlashA = nameA.lastIndexOf('/'); + const lastSlashB = nameB.lastIndexOf('/'); + + // Neither ref has a slash, maintain insertion order + if (lastSlashA === -1 && lastSlashB === -1) { + return 0; + } + + // Ref with a slash comes first + if (lastSlashA !== -1 && lastSlashB === -1) { + return -1; + } else if (lastSlashA === -1 && lastSlashB !== -1) { + return 1; + } + + // Both have slashes + // Get directory segments + const segmentsA = nameA.substring(0, lastSlashA).split('/'); + const segmentsB = nameB.substring(0, lastSlashB).split('/'); + + // Compare directory segments + for (let index = 0; index < Math.min(segmentsA.length, segmentsB.length); index++) { + const result = segmentsA[index].localeCompare(segmentsB[index]); + if (result !== 0) { + return result; + } + } + + // Directory with more segments comes first + if (segmentsA.length !== segmentsB.length) { + return segmentsB.length - segmentsA.length; + } + + // Insertion order + return 0; +} + +export class GitArtifactProvider implements SourceControlArtifactProvider, IDisposable { + private readonly _onDidChangeArtifacts = new EventEmitter(); + readonly onDidChangeArtifacts: Event = this._onDidChangeArtifacts.event; + + private readonly _groups: SourceControlArtifactGroup[]; + private readonly _disposables: Disposable[] = []; + + constructor( + private readonly repository: Repository, + private readonly logger: LogOutputChannel + ) { + this._groups = [ + { id: 'branches', name: l10n.t('Branches'), icon: new ThemeIcon('git-branch') }, + { id: 'tags', name: l10n.t('Tags'), icon: new ThemeIcon('tag') } + ]; + + this._disposables.push(this._onDidChangeArtifacts); + this._disposables.push(repository.historyProvider.onDidChangeHistoryItemRefs(e => { + const groups = new Set(); + for (const ref of e.added.concat(e.modified).concat(e.removed)) { + if (ref.id.startsWith('refs/heads/')) { + groups.add('branches'); + } else if (ref.id.startsWith('refs/tags/')) { + groups.add('tags'); + } + } + + this._onDidChangeArtifacts.fire(Array.from(groups)); + })); + } + + provideArtifactGroups(): SourceControlArtifactGroup[] { + return this._groups; + } + + async provideArtifacts(group: string): Promise { + const config = workspace.getConfiguration('git', Uri.file(this.repository.root)); + const shortCommitLength = config.get('commitShortHashLength', 7); + + try { + if (group === 'branches') { + const refs = await this.repository + .getRefs({ pattern: 'refs/heads', includeCommitDetails: true }); + + return refs.sort(sortRefByName).map(r => ({ + id: `refs/heads/${r.name}`, + name: r.name ?? r.commit ?? '', + description: getArtifactDescription(r, shortCommitLength), + icon: this.repository.HEAD?.type === RefType.Head && r.name === this.repository.HEAD?.name + ? new ThemeIcon('target') + : new ThemeIcon('git-branch') + })); + } else if (group === 'tags') { + const refs = await this.repository + .getRefs({ pattern: 'refs/tags', includeCommitDetails: true }); + + return refs.sort(sortRefByName).map(r => ({ + id: `refs/tags/${r.name}`, + name: r.name ?? r.commit ?? '', + description: getArtifactDescription(r, shortCommitLength), + icon: this.repository.HEAD?.type === RefType.Tag && r.name === this.repository.HEAD?.name + ? new ThemeIcon('target') + : new ThemeIcon('tag') + })); + } + } catch (err) { + this.logger.error(`[GitArtifactProvider][provideArtifacts] Error while providing artifacts for group '${group}': `, err); + return []; + } + + return []; + } + + dispose(): void { + dispose(this._disposables); + } +} diff --git a/extensions/git/src/askpass-main.ts b/extensions/git/src/askpass-main.ts index cb93adf2821..21402fbaf34 100644 --- a/extensions/git/src/askpass-main.ts +++ b/extensions/git/src/askpass-main.ts @@ -6,7 +6,7 @@ import * as fs from 'fs'; import { IPCClient } from './ipc/ipcClient'; -function fatal(err: any): void { +function fatal(err: unknown): void { console.error('Missing or invalid credentials.'); console.error(err); process.exit(1); diff --git a/extensions/git/src/blame.ts b/extensions/git/src/blame.ts index f5814370251..cb0c00204e3 100644 --- a/extensions/git/src/blame.ts +++ b/extensions/git/src/blame.ts @@ -196,7 +196,9 @@ export class GitBlameController { } satisfies BlameInformationTemplateTokens; return template.replace(/\$\{(.+?)\}/g, (_, token) => { - return token in templateTokens ? templateTokens[token as keyof BlameInformationTemplateTokens] : `\${${token}}`; + return templateTokens.hasOwnProperty(token) + ? templateTokens[token as keyof BlameInformationTemplateTokens] + : `\${${token}}`; }); } @@ -260,7 +262,7 @@ export class GitBlameController { arguments: ['git.blame'] }] satisfies Command[]); - return getHistoryItemHover(commitAvatar, authorName, authorEmail, authorDate, message, commitInformation?.shortStat, commands); + return getHistoryItemHover(commitAvatar, authorName, authorEmail, authorDate, message, commitInformation?.shortStat, undefined, commands); } private _onDidChangeConfiguration(e?: ConfigurationChangeEvent): void { diff --git a/extensions/git/src/cache.ts b/extensions/git/src/cache.ts index df0c0df5561..ad2db75edc8 100644 --- a/extensions/git/src/cache.ts +++ b/extensions/git/src/cache.ts @@ -132,7 +132,7 @@ class LinkedMap implements Map { return item.value; } - forEach(callbackfn: (value: V, key: K, map: LinkedMap) => void, thisArg?: any): void { + forEach(callbackfn: (value: V, key: K, map: LinkedMap) => void, thisArg?: unknown): void { const state = this._state; let current = this._head; while (current) { diff --git a/extensions/git/src/cloneManager.ts b/extensions/git/src/cloneManager.ts new file mode 100644 index 00000000000..49d57d8763c --- /dev/null +++ b/extensions/git/src/cloneManager.ts @@ -0,0 +1,243 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as fs from 'fs'; +import * as os from 'os'; +import { pickRemoteSource } from './remoteSource'; +import { l10n, workspace, window, Uri, ProgressLocation, commands } from 'vscode'; +import { RepositoryCache, RepositoryCacheInfo } from './repositoryCache'; +import TelemetryReporter from '@vscode/extension-telemetry'; +import { Model } from './model'; + +type ApiPostCloneAction = 'none'; +enum PostCloneAction { Open, OpenNewWindow, AddToWorkspace, None } + +export interface CloneOptions { + parentPath?: string; + ref?: string; + recursive?: boolean; + postCloneAction?: ApiPostCloneAction; +} + +export class CloneManager { + constructor(private readonly model: Model, + private readonly telemetryReporter: TelemetryReporter, + private readonly repositoryCache: RepositoryCache) { } + + async clone(url?: string, options: CloneOptions = {}) { + if (!url || typeof url !== 'string') { + url = await pickRemoteSource({ + providerLabel: provider => l10n.t('Clone from {0}', provider.name), + urlLabel: l10n.t('Clone from URL') + }); + } + + if (!url) { + /* __GDPR__ + "clone" : { + "owner": "lszomoru", + "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } + } + */ + this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_URL' }); + return; + } + + url = url.trim().replace(/^git\s+clone\s+/, ''); + + const cachedRepository = this.repositoryCache.get(url); + if (cachedRepository && (cachedRepository.length > 0)) { + return this.tryOpenExistingRepository(cachedRepository, url, options.postCloneAction, options.parentPath, options.ref); + } + return this.cloneRepository(url, options.parentPath, options); + } + + private async cloneRepository(url: string, parentPath?: string, options: { recursive?: boolean; ref?: string; postCloneAction?: ApiPostCloneAction } = {}): Promise { + if (!parentPath) { + const config = workspace.getConfiguration('git'); + let defaultCloneDirectory = config.get('defaultCloneDirectory') || os.homedir(); + defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir()); + + const uris = await window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + defaultUri: Uri.file(defaultCloneDirectory), + title: l10n.t('Choose a folder to clone {0} into', url), + openLabel: l10n.t('Select as Repository Destination') + }); + + if (!uris || uris.length === 0) { + /* __GDPR__ + "clone" : { + "owner": "lszomoru", + "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } + } + */ + this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_directory' }); + return; + } + + const uri = uris[0]; + parentPath = uri.fsPath; + } + + try { + const opts = { + location: ProgressLocation.Notification, + title: l10n.t('Cloning git repository "{0}"...', url), + cancellable: true + }; + + const repositoryPath = await window.withProgress( + opts, + (progress, token) => this.model.git.clone(url!, { parentPath: parentPath!, progress, recursive: options.recursive, ref: options.ref }, token) + ); + + await this.doPostCloneAction(repositoryPath, options.postCloneAction); + + return repositoryPath; + } catch (err) { + if (/already exists and is not an empty directory/.test(err && err.stderr || '')) { + /* __GDPR__ + "clone" : { + "owner": "lszomoru", + "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } + } + */ + this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'directory_not_empty' }); + } else if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) { + return; + } else { + /* __GDPR__ + "clone" : { + "owner": "lszomoru", + "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } + } + */ + this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'error' }); + } + + throw err; + } + } + + private async doPostCloneAction(target: string, postCloneAction?: ApiPostCloneAction): Promise { + const config = workspace.getConfiguration('git'); + const openAfterClone = config.get<'always' | 'alwaysNewWindow' | 'whenNoFolderOpen' | 'prompt'>('openAfterClone'); + + let action: PostCloneAction | undefined = undefined; + + if (postCloneAction && postCloneAction === 'none') { + action = PostCloneAction.None; + } else { + if (openAfterClone === 'always') { + action = PostCloneAction.Open; + } else if (openAfterClone === 'alwaysNewWindow') { + action = PostCloneAction.OpenNewWindow; + } else if (openAfterClone === 'whenNoFolderOpen' && !workspace.workspaceFolders) { + action = PostCloneAction.Open; + } + } + + if (action === undefined) { + let message = l10n.t('Would you like to open the repository?'); + const open = l10n.t('Open'); + const openNewWindow = l10n.t('Open in New Window'); + const choices = [open, openNewWindow]; + + const addToWorkspace = l10n.t('Add to Workspace'); + if (workspace.workspaceFolders) { + message = l10n.t('Would you like to open the repository, or add it to the current workspace?'); + choices.push(addToWorkspace); + } + + const result = await window.showInformationMessage(message, { modal: true }, ...choices); + + action = result === open ? PostCloneAction.Open + : result === openNewWindow ? PostCloneAction.OpenNewWindow + : result === addToWorkspace ? PostCloneAction.AddToWorkspace : undefined; + } + + /* __GDPR__ + "clone" : { + "owner": "lszomoru", + "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" }, + "openFolder": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true, "comment": "Indicates whether the folder is opened following the clone operation" } + } + */ + this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'success' }, { openFolder: action === PostCloneAction.Open || action === PostCloneAction.OpenNewWindow ? 1 : 0 }); + + const uri = Uri.file(target); + + if (action === PostCloneAction.Open) { + commands.executeCommand('vscode.openFolder', uri, { forceReuseWindow: true }); + } else if (action === PostCloneAction.AddToWorkspace) { + workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri }); + } else if (action === PostCloneAction.OpenNewWindow) { + commands.executeCommand('vscode.openFolder', uri, { forceNewWindow: true }); + } + } + + private async chooseExistingRepository(url: string, existingCachedRepositories: RepositoryCacheInfo[], ref: string | undefined, parentPath?: string, postCloneAction?: ApiPostCloneAction): Promise { + try { + const items: { label: string; description?: string; item?: RepositoryCacheInfo }[] = existingCachedRepositories.map(knownFolder => { + const isWorkspace = knownFolder.workspacePath.endsWith('.code-workspace'); + const label = isWorkspace ? l10n.t('Workspace: {0}', path.basename(knownFolder.workspacePath, '.code-workspace')) : path.basename(knownFolder.workspacePath); + return { label, description: knownFolder.workspacePath, item: knownFolder }; + }); + const cloneAgain = { label: l10n.t('Clone again') }; + items.push(cloneAgain); + const placeHolder = l10n.t('Open Existing Repository Clone'); + const pick = await window.showQuickPick(items, { placeHolder, canPickMany: false }); + if (pick === cloneAgain) { + return (await this.cloneRepository(url, parentPath, { ref, postCloneAction })) ?? undefined; + } + if (!pick?.item) { + return undefined; + } + return pick.item.workspacePath; + } catch { + return undefined; + } + } + + private async tryOpenExistingRepository(cachedRepository: RepositoryCacheInfo[], url: string, postCloneAction?: ApiPostCloneAction, parentPath?: string, ref?: string): Promise { + // Gather existing folders/workspace files (ignore ones that no longer exist) + const existingCachedRepositories: RepositoryCacheInfo[] = (await Promise.all(cachedRepository.map(async folder => { + const stat = await fs.promises.stat(folder.workspacePath).catch(() => undefined); + if (stat) { + return folder; + } + return undefined; + } + ))).filter((folder): folder is RepositoryCacheInfo => folder !== undefined); + + if (!existingCachedRepositories.length) { + // fallback to clone + return (await this.cloneRepository(url, parentPath, { ref, postCloneAction }) ?? undefined); + } + + // First, find the cached repo that exists in the current workspace + const matchingInCurrentWorkspace = existingCachedRepositories?.find(cachedRepo => { + return workspace.workspaceFolders?.some(workspaceFolder => workspaceFolder.uri.fsPath === cachedRepo.workspacePath); + }); + + if (matchingInCurrentWorkspace) { + return matchingInCurrentWorkspace.workspacePath; + } + + let repoForWorkspace: string | undefined = (existingCachedRepositories.length === 1 ? existingCachedRepositories[0].workspacePath : undefined); + if (!repoForWorkspace) { + repoForWorkspace = await this.chooseExistingRepository(url, existingCachedRepositories, ref, parentPath, postCloneAction); + } + if (repoForWorkspace) { + await this.doPostCloneAction(repoForWorkspace, postCloneAction); + return repoForWorkspace; + } + return; + } +} diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 35621e5d982..79a3184bd36 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -5,20 +5,21 @@ import * as os from 'os'; import * as path from 'path'; -import { Command, commands, Disposable, MessageOptions, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation, languages } from 'vscode'; +import { Command, commands, Disposable, MessageOptions, Position, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, Selection, TextDocumentContentProvider, InputBoxValidationSeverity, TabInputText, TabInputTextMerge, QuickPickItemKind, TextDocument, LogOutputChannel, l10n, Memento, UIKind, QuickInputButton, ThemeIcon, SourceControlHistoryItem, SourceControl, InputBoxValidationMessage, Tab, TabInputNotebook, QuickInputButtonLocation, languages, SourceControlArtifact } from 'vscode'; import TelemetryReporter from '@vscode/extension-telemetry'; import { uniqueNamesGenerator, adjectives, animals, colors, NumberDictionary } from '@joaomoreno/unique-names-generator'; import { ForcePushMode, GitErrorCodes, RefType, Status, CommitOptions, RemoteSourcePublisher, Remote, Branch, Ref } from './api/git'; -import { Git, Stash, Worktree } from './git'; +import { Git, GitError, Stash, Worktree } from './git'; import { Model } from './model'; import { GitResourceGroup, Repository, Resource, ResourceGroupType } from './repository'; import { DiffEditorSelectionHunkToolbarContext, LineChange, applyLineChanges, getIndexDiffInformation, getModifiedRange, getWorkingTreeDiffInformation, intersectDiffWithRange, invertLineChange, toLineChanges, toLineRanges, compareLineChanges } from './staging'; import { fromGitUri, toGitUri, isGitUri, toMergeUris, toMultiFileDiffEditorUris } from './uri'; -import { DiagnosticSeverityConfig, dispose, fromNow, grep, isDefined, isDescendant, isLinuxSnap, isRemote, isWindows, pathEquals, relativePath, subject, toDiagnosticSeverity, truncate } from './util'; +import { DiagnosticSeverityConfig, dispose, fromNow, getHistoryItemDisplayName, grep, isDefined, isDescendant, isLinuxSnap, isRemote, isWindows, pathEquals, relativePath, subject, toDiagnosticSeverity, truncate } from './util'; import { GitTimelineItem } from './timelineProvider'; import { ApiRepository } from './api/api1'; import { getRemoteSourceActions, pickRemoteSource } from './remoteSource'; import { RemoteSourceAction } from './typings/git-base'; +import { CloneManager } from './cloneManager'; abstract class CheckoutCommandItem implements QuickPickItem { abstract get label(): string; @@ -115,7 +116,7 @@ class RefItem implements QuickPickItem { case RefType.Head: return `refs/heads/${this.ref.name}`; case RefType.RemoteHead: - return `refs/remotes/${this.ref.remote}/${this.ref.name}`; + return `refs/remotes/${this.ref.name}`; case RefType.Tag: return `refs/tags/${this.ref.name}`; } @@ -123,6 +124,7 @@ class RefItem implements QuickPickItem { get refName(): string | undefined { return this.ref.name; } get refRemote(): string | undefined { return this.ref.remote; } get shortCommit(): string { return (this.ref.commit || '').substring(0, this.shortCommitLength); } + get commitMessage(): string | undefined { return this.ref.commitDetails?.message; } private _buttons?: QuickInputButton[]; get buttons(): QuickInputButton[] | undefined { return this._buttons; } @@ -363,8 +365,8 @@ interface ScmCommand { const Commands: ScmCommand[] = []; function command(commandId: string, options: ScmCommandOptions = {}): Function { - return (value: any, context: ClassMethodDecoratorContext) => { - if (context.kind !== 'method') { + return (value: unknown, context: ClassMethodDecoratorContext) => { + if (typeof value !== 'function' || context.kind !== 'method') { throw new Error('not supported'); } const key = context.name.toString(); @@ -681,10 +683,11 @@ class CommandErrorOutputTextDocumentContentProvider implements TextDocumentConte } } -async function evaluateDiagnosticsCommitHook(repository: Repository, options: CommitOptions): Promise { +async function evaluateDiagnosticsCommitHook(repository: Repository, options: CommitOptions, logger: LogOutputChannel): Promise { const config = workspace.getConfiguration('git', Uri.file(repository.root)); const enabled = config.get('diagnosticsCommitHook.enabled', false) === true; const sourceSeverity = config.get>('diagnosticsCommitHook.sources', { '*': 'error' }); + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Diagnostics Commit Hook: enabled=${enabled}, sources=${JSON.stringify(sourceSeverity)}`); if (!enabled) { return true; @@ -710,23 +713,27 @@ async function evaluateDiagnosticsCommitHook(repository: Repository, options: Co for (const resource of resources) { const unresolvedDiagnostics = languages.getDiagnostics(resource) .filter(d => { + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Evaluating diagnostic for ${resource.fsPath}: source='${d.source}', severity='${d.severity}'`); + // No source or ignored source if (!d.source || (Object.keys(sourceSeverity).includes(d.source) && sourceSeverity[d.source] === 'none')) { + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Ignoring diagnostic for ${resource.fsPath}: source='${d.source}', severity='${d.severity}'`); return false; } // Source severity - if (Object.keys(sourceSeverity).includes(d.source) && - d.severity <= toDiagnosticSeverity(sourceSeverity[d.source])) { + if (Object.keys(sourceSeverity).includes(d.source) && d.severity <= toDiagnosticSeverity(sourceSeverity[d.source])) { + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Found unresolved diagnostic for ${resource.fsPath}: source='${d.source}', severity='${d.severity}'`); return true; } // Wildcard severity - if (Object.keys(sourceSeverity).includes('*') && - d.severity <= toDiagnosticSeverity(sourceSeverity['*'])) { + if (Object.keys(sourceSeverity).includes('*') && d.severity <= toDiagnosticSeverity(sourceSeverity['*'])) { + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Found unresolved diagnostic for ${resource.fsPath}: source='${d.source}', severity='${d.severity}'`); return true; } + logger.trace(`[CommandCenter][evaluateDiagnosticsCommitHook] Ignoring diagnostic for ${resource.fsPath}: source='${d.source}', severity='${d.severity}'`); return false; }); @@ -774,7 +781,8 @@ export class CommandCenter { private model: Model, private globalState: Memento, private logger: LogOutputChannel, - private telemetryReporter: TelemetryReporter + private telemetryReporter: TelemetryReporter, + private cloneManager: CloneManager ) { this.disposables = Commands.map(({ commandId, key, method, options }) => { const command = this.createCommand(commandId, key, method, options); @@ -862,23 +870,32 @@ export class CommandCenter { } try { - const [head, rebaseOrMergeHead, diffBetween] = await Promise.all([ + const [head, rebaseOrMergeHead, oursDiff, theirsDiff] = await Promise.all([ repo.getCommit('HEAD'), isRebasing ? repo.getCommit('REBASE_HEAD') : repo.getCommit('MERGE_HEAD'), - await repo.diffBetween(isRebasing ? 'REBASE_HEAD' : 'MERGE_HEAD', 'HEAD') + await repo.diffBetween(isRebasing ? 'REBASE_HEAD' : 'MERGE_HEAD', 'HEAD'), + await repo.diffBetween('HEAD', isRebasing ? 'REBASE_HEAD' : 'MERGE_HEAD') ]); - const diffFile = diffBetween?.find(diff => diff.uri.fsPath === uri.fsPath); + + const oursDiffFile = oursDiff?.find(diff => diff.uri.fsPath === uri.fsPath); + const theirsDiffFile = theirsDiff?.find(diff => diff.uri.fsPath === uri.fsPath); // ours (current branch and commit) current.detail = head.refNames.map(s => s.replace(/^HEAD ->/, '')).join(', '); current.description = '$(git-commit) ' + head.hash.substring(0, 7); - current.uri = toGitUri(uri, head.hash); + if (theirsDiffFile) { + // use the original uri in case the file was renamed by theirs + current.uri = toGitUri(theirsDiffFile.originalUri, head.hash); + } else { + current.uri = toGitUri(uri, head.hash); + } // theirs incoming.detail = rebaseOrMergeHead.refNames.join(', '); incoming.description = '$(git-commit) ' + rebaseOrMergeHead.hash.substring(0, 7); - if (diffFile) { - incoming.uri = toGitUri(diffFile.originalUri, rebaseOrMergeHead.hash); + if (oursDiffFile) { + // use the original uri in case the file was renamed by ours + incoming.uri = toGitUri(oursDiffFile.originalUri, rebaseOrMergeHead.hash); } else { incoming.uri = toGitUri(uri, rebaseOrMergeHead.hash); } @@ -935,144 +952,6 @@ export class CommandCenter { } } - async cloneRepository(url?: string, parentPath?: string, options: { recursive?: boolean; ref?: string } = {}): Promise { - if (!url || typeof url !== 'string') { - url = await pickRemoteSource({ - providerLabel: provider => l10n.t('Clone from {0}', provider.name), - urlLabel: l10n.t('Clone from URL') - }); - } - - if (!url) { - /* __GDPR__ - "clone" : { - "owner": "lszomoru", - "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } - } - */ - this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_URL' }); - return; - } - - url = url.trim().replace(/^git\s+clone\s+/, ''); - - if (!parentPath) { - const config = workspace.getConfiguration('git'); - let defaultCloneDirectory = config.get('defaultCloneDirectory') || os.homedir(); - defaultCloneDirectory = defaultCloneDirectory.replace(/^~/, os.homedir()); - - const uris = await window.showOpenDialog({ - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - defaultUri: Uri.file(defaultCloneDirectory), - title: l10n.t('Choose a folder to clone {0} into', url), - openLabel: l10n.t('Select as Repository Destination') - }); - - if (!uris || uris.length === 0) { - /* __GDPR__ - "clone" : { - "owner": "lszomoru", - "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } - } - */ - this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'no_directory' }); - return; - } - - const uri = uris[0]; - parentPath = uri.fsPath; - } - - try { - const opts = { - location: ProgressLocation.Notification, - title: l10n.t('Cloning git repository "{0}"...', url), - cancellable: true - }; - - const repositoryPath = await window.withProgress( - opts, - (progress, token) => this.git.clone(url!, { parentPath: parentPath!, progress, recursive: options.recursive, ref: options.ref }, token) - ); - - const config = workspace.getConfiguration('git'); - const openAfterClone = config.get<'always' | 'alwaysNewWindow' | 'whenNoFolderOpen' | 'prompt'>('openAfterClone'); - - enum PostCloneAction { Open, OpenNewWindow, AddToWorkspace } - let action: PostCloneAction | undefined = undefined; - - if (openAfterClone === 'always') { - action = PostCloneAction.Open; - } else if (openAfterClone === 'alwaysNewWindow') { - action = PostCloneAction.OpenNewWindow; - } else if (openAfterClone === 'whenNoFolderOpen' && !workspace.workspaceFolders) { - action = PostCloneAction.Open; - } - - if (action === undefined) { - let message = l10n.t('Would you like to open the cloned repository?'); - const open = l10n.t('Open'); - const openNewWindow = l10n.t('Open in New Window'); - const choices = [open, openNewWindow]; - - const addToWorkspace = l10n.t('Add to Workspace'); - if (workspace.workspaceFolders) { - message = l10n.t('Would you like to open the cloned repository, or add it to the current workspace?'); - choices.push(addToWorkspace); - } - - const result = await window.showInformationMessage(message, { modal: true }, ...choices); - - action = result === open ? PostCloneAction.Open - : result === openNewWindow ? PostCloneAction.OpenNewWindow - : result === addToWorkspace ? PostCloneAction.AddToWorkspace : undefined; - } - - /* __GDPR__ - "clone" : { - "owner": "lszomoru", - "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" }, - "openFolder": { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true, "comment": "Indicates whether the folder is opened following the clone operation" } - } - */ - this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'success' }, { openFolder: action === PostCloneAction.Open || action === PostCloneAction.OpenNewWindow ? 1 : 0 }); - - const uri = Uri.file(repositoryPath); - - if (action === PostCloneAction.Open) { - commands.executeCommand('vscode.openFolder', uri, { forceReuseWindow: true }); - } else if (action === PostCloneAction.AddToWorkspace) { - workspace.updateWorkspaceFolders(workspace.workspaceFolders!.length, 0, { uri }); - } else if (action === PostCloneAction.OpenNewWindow) { - commands.executeCommand('vscode.openFolder', uri, { forceNewWindow: true }); - } - } catch (err) { - if (/already exists and is not an empty directory/.test(err && err.stderr || '')) { - /* __GDPR__ - "clone" : { - "owner": "lszomoru", - "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } - } - */ - this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'directory_not_empty' }); - } else if (/Cancelled/i.test(err && (err.message || err.stderr || ''))) { - return; - } else { - /* __GDPR__ - "clone" : { - "owner": "lszomoru", - "outcome" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The outcome of the git operation" } - } - */ - this.telemetryReporter.sendTelemetryEvent('clone', { outcome: 'error' }); - } - - throw err; - } - } - private getRepositoriesWithRemote(repositories: Repository[]) { return repositories.reduce<(QuickPickItem & { repository: Repository })[]>((items, repository) => { const remote = repository.remotes.find((r) => r.name === repository.HEAD?.upstream?.remote); @@ -1145,12 +1024,12 @@ export class CommandCenter { @command('git.clone') async clone(url?: string, parentPath?: string, options?: { ref?: string }): Promise { - await this.cloneRepository(url, parentPath, options); + await this.cloneManager.clone(url, { parentPath, ...options }); } @command('git.cloneRecursive') async cloneRecursive(url?: string, parentPath?: string): Promise { - await this.cloneRepository(url, parentPath, { recursive: true }); + await this.cloneManager.clone(url, { parentPath, recursive: true }); } @command('git.init') @@ -1825,7 +1704,7 @@ export class CommandCenter { const resources = [ ...repository.workingTreeGroup.resourceStates, ...repository.untrackedGroup.resourceStates] - .filter(r => r.multiFileDiffEditorModifiedUri?.toString() === uri.toString()) + .filter(r => r.multiFileDiffEditorModifiedUri?.toString() === uri.toString() || r.multiDiffEditorOriginalUri?.toString() === uri.toString()) .map(r => r.resourceUri); if (resources.length === 0) { @@ -2136,7 +2015,7 @@ export class CommandCenter { } const resources = repository.indexGroup.resourceStates - .filter(r => r.multiFileDiffEditorModifiedUri?.toString() === uri.toString()) + .filter(r => r.multiFileDiffEditorModifiedUri?.toString() === uri.toString() || r.multiDiffEditorOriginalUri?.toString() === uri.toString()) .map(r => r.resourceUri); if (resources.length === 0) { @@ -2539,7 +2418,7 @@ export class CommandCenter { } // Diagnostics commit hook - const diagnosticsResult = await evaluateDiagnosticsCommitHook(repository, opts); + const diagnosticsResult = await evaluateDiagnosticsCommitHook(repository, opts, this.logger); if (!diagnosticsResult) { return; } @@ -3231,6 +3110,108 @@ export class CommandCenter { await this._deleteBranch(repository, remoteName, refName, { remote: true }); } + @command('git.graph.compareWithRemote', { repository: true }) + async compareWithRemote(repository: Repository, historyItem?: SourceControlHistoryItem): Promise { + if (!historyItem || !repository.historyProvider.currentHistoryItemRemoteRef) { + return; + } + + await this._openChangesBetweenRefs( + repository, + { + id: repository.historyProvider.currentHistoryItemRemoteRef.revision, + displayId: repository.historyProvider.currentHistoryItemRemoteRef.name + }, + { + id: historyItem.id, + displayId: getHistoryItemDisplayName(historyItem) + }); + } + + @command('git.graph.compareWithMergeBase', { repository: true }) + async compareWithMergeBase(repository: Repository, historyItem?: SourceControlHistoryItem): Promise { + if (!historyItem || !repository.historyProvider.currentHistoryItemBaseRef) { + return; + } + + await this._openChangesBetweenRefs( + repository, + { + id: repository.historyProvider.currentHistoryItemBaseRef.revision, + displayId: repository.historyProvider.currentHistoryItemBaseRef.name + }, + { + id: historyItem.id, + displayId: getHistoryItemDisplayName(historyItem) + }); + } + + @command('git.graph.compareRef', { repository: true }) + async compareRef(repository: Repository, historyItem?: SourceControlHistoryItem): Promise { + if (!repository || !historyItem) { + return; + } + + const config = workspace.getConfiguration('git'); + const showRefDetails = config.get('showReferenceDetails') === true; + + const getRefPicks = async () => { + const refs = await repository.getRefs({ includeCommitDetails: showRefDetails }); + const processors = [ + new RefProcessor(RefType.Head, BranchItem), + new RefProcessor(RefType.RemoteHead, BranchItem), + new RefProcessor(RefType.Tag, BranchItem) + ]; + + const itemsProcessor = new RefItemsProcessor(repository, processors); + return itemsProcessor.processRefs(refs); + }; + + const placeHolder = l10n.t('Select a reference to compare with'); + const sourceRef = await this.pickRef(getRefPicks(), placeHolder); + + if (!(sourceRef instanceof BranchItem) || !sourceRef.ref.commit) { + return; + } + + await this._openChangesBetweenRefs( + repository, + { + id: sourceRef.ref.commit, + displayId: sourceRef.ref.name + }, + { + id: historyItem.id, + displayId: getHistoryItemDisplayName(historyItem) + }); + } + + private async _openChangesBetweenRefs(repository: Repository, ref1: { id: string | undefined; displayId: string | undefined }, ref2: { id: string | undefined; displayId: string | undefined }): Promise { + if (!repository || !ref1.id || !ref2.id) { + return; + } + + try { + const changes = await repository.diffBetween2(ref1.id, ref2.id); + + if (changes.length === 0) { + window.showInformationMessage(l10n.t('There are no changes between "{0}" and "{1}".', ref1.displayId ?? ref1.id, ref2.displayId ?? ref2.id)); + return; + } + + const multiDiffSourceUri = Uri.from({ scheme: 'git-ref-compare', path: `${repository.root}/${ref1.id}..${ref2.id}` }); + const resources = changes.map(change => toMultiFileDiffEditorUris(change, ref1.id!, ref2.id!)); + + await commands.executeCommand('_workbench.openMultiDiffEditor', { + multiDiffSourceUri, + title: `${ref1.displayId ?? ref1.id} \u2194 ${ref2.displayId ?? ref2.id}`, + resources + }); + } catch (err) { + window.showErrorMessage(l10n.t('Failed to open changes between "{0}" and "{1}": {2}', ref1.displayId ?? ref1.id, ref2.displayId ?? ref2.id, err.message)); + } + } + @command('git.deleteRemoteBranch', { repository: true }) async deleteRemoteBranch(repository: Repository): Promise { await this._deleteBranch(repository, undefined, undefined, { remote: true }); @@ -3391,24 +3372,7 @@ export class CommandCenter { @command('git.createTag', { repository: true }) async createTag(repository: Repository, historyItem?: SourceControlHistoryItem): Promise { - const inputTagName = await window.showInputBox({ - placeHolder: l10n.t('Tag name'), - prompt: l10n.t('Please provide a tag name'), - ignoreFocusOut: true - }); - - if (!inputTagName) { - return; - } - - const inputMessage = await window.showInputBox({ - placeHolder: l10n.t('Message'), - prompt: l10n.t('Please provide a message to annotate the tag'), - ignoreFocusOut: true - }); - - const name = inputTagName.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$/g, '-'); - await repository.tag({ name, message: inputMessage, ref: historyItem?.id }); + await this._createTag(repository, historyItem?.id); } @command('git.deleteTag', { repository: true }) @@ -3433,23 +3397,33 @@ export class CommandCenter { } @command('git.migrateWorktreeChanges', { repository: true, repositoryFilter: ['repository', 'submodule'] }) - async migrateWorktreeChanges(repository: Repository): Promise { - const worktreePicks = async (): Promise => { + async migrateWorktreeChanges(repository: Repository, worktreeUri?: Uri): Promise { + let worktreeRepository: Repository | undefined; + if (worktreeUri !== undefined) { + worktreeRepository = this.model.getRepository(worktreeUri); + } else { const worktrees = await repository.getWorktrees(); - return worktrees.length === 0 - ? [{ label: l10n.t('$(info) This repository has no worktrees.') }] - : worktrees.map(worktree => new WorktreeItem(worktree)); - }; + if (worktrees.length === 1) { + worktreeRepository = this.model.getRepository(worktrees[0].path); + } else { + const worktreePicks = async (): Promise => { + return worktrees.length === 0 + ? [{ label: l10n.t('$(info) This repository has no worktrees.') }] + : worktrees.map(worktree => new WorktreeItem(worktree)); + }; - const placeHolder = l10n.t('Select a worktree to migrate changes from'); - const choice = await this.pickRef(worktreePicks(), placeHolder); + const placeHolder = l10n.t('Select a worktree to migrate changes from'); + const choice = await this.pickRef(worktreePicks(), placeHolder); - if (!choice || !(choice instanceof WorktreeItem)) { - return; + if (!choice || !(choice instanceof WorktreeItem)) { + return; + } + + worktreeRepository = this.model.getRepository(choice.worktree.path); + } } - const worktreeRepository = this.model.getRepository(choice.worktree.path); - if (!worktreeRepository) { + if (!worktreeRepository || worktreeRepository.kind !== 'worktree') { return; } @@ -3488,12 +3462,15 @@ export class CommandCenter { return; } - const message = l10n.t('Proceed with migrating changes to the current repository?'); - const detail = l10n.t('This will apply the worktree\'s changes to this repository and discard changes in the worktree.\nThis is IRREVERSIBLE!'); - const proceed = l10n.t('Proceed'); - const pick = await window.showWarningMessage(message, { modal: true, detail }, proceed); - if (pick !== proceed) { - return; + if (worktreeUri === undefined) { + // Non-interactive migration, do not show confirmation dialog + const message = l10n.t('Proceed with migrating changes to the current repository?'); + const detail = l10n.t('This will apply the worktree\'s changes to this repository and discard changes in the worktree.\nThis is IRREVERSIBLE!'); + const proceed = l10n.t('Proceed'); + const pick = await window.showWarningMessage(message, { modal: true, detail }, proceed); + if (pick !== proceed) { + return; + } } await worktreeRepository.createStash(undefined, true); @@ -3535,10 +3512,87 @@ export class CommandCenter { }); } - @command('git.createWorktree') - async createWorktree(repository: any): Promise { - repository = this.model.getRepository(repository); + @command('git.createWorktreeWithDefaults', { repository: true, repositoryFilter: ['repository'] }) + async createWorktreeWithDefaults( + repository: Repository, + commitish: string = 'HEAD' + ): Promise { + const config = workspace.getConfiguration('git'); + const branchPrefix = config.get('branchPrefix', ''); + // Generate branch name if not provided + let branch = await this.generateRandomBranchName(repository, '-'); + if (!branch) { + // Fallback to timestamp-based name if random generation fails + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + branch = `${branchPrefix}worktree-${timestamp}`; + } + + // Ensure branch name starts with prefix if configured + if (branchPrefix && !branch.startsWith(branchPrefix)) { + branch = branchPrefix + branch; + } + + // Create worktree name from branch name + const worktreeName = branch.startsWith(branchPrefix) + ? branch.substring(branchPrefix.length).replace(/\//g, '-') + : branch.replace(/\//g, '-'); + + // Determine default worktree path + const defaultWorktreeRoot = this.globalState.get(`${CommandCenter.WORKTREE_ROOT_KEY}:${repository.root}`); + const defaultWorktreePath = defaultWorktreeRoot + ? path.join(defaultWorktreeRoot, worktreeName) + : path.join(path.dirname(repository.root), `${path.basename(repository.root)}.worktrees`, worktreeName); + + // Check if worktree already exists at this path + const existingWorktree = repository.worktrees.find(worktree => + pathEquals(path.normalize(worktree.path), path.normalize(defaultWorktreePath)) + ); + + if (existingWorktree) { + // Generate unique path by appending a number + let counter = 1; + let uniquePath = `${defaultWorktreePath}-${counter}`; + while (repository.worktrees.some(wt => pathEquals(path.normalize(wt.path), path.normalize(uniquePath)))) { + counter++; + uniquePath = `${defaultWorktreePath}-${counter}`; + } + const finalWorktreePath = uniquePath; + + try { + await repository.addWorktree({ path: finalWorktreePath, branch, commitish }); + + // Update worktree root in global state + const worktreeRoot = path.dirname(finalWorktreePath); + if (worktreeRoot !== defaultWorktreeRoot) { + this.globalState.update(`${CommandCenter.WORKTREE_ROOT_KEY}:${repository.root}`, worktreeRoot); + } + + return finalWorktreePath; + } catch (err) { + // Return undefined on failure + return undefined; + } + } + + try { + await repository.addWorktree({ path: defaultWorktreePath, branch, commitish }); + + // Update worktree root in global state + const worktreeRoot = path.dirname(defaultWorktreePath); + if (worktreeRoot !== defaultWorktreeRoot) { + this.globalState.update(`${CommandCenter.WORKTREE_ROOT_KEY}:${repository.root}`, worktreeRoot); + } + + return defaultWorktreePath; + } catch (err) { + // Return undefined on failure + return undefined; + } + } + + @command('git.createWorktree', { repository: true }) + async createWorktree(repository?: Repository): Promise { if (!repository) { // Single repository/submodule/worktree if (this.model.repositories.length === 1) { @@ -3730,9 +3784,9 @@ export class CommandCenter { this.globalState.update(`${CommandCenter.WORKTREE_ROOT_KEY}:${repository.root}`, worktreeRoot); } } catch (err) { - if (err.gitErrorCode === GitErrorCodes.WorktreeAlreadyExists) { + if (err instanceof GitError && err.gitErrorCode === GitErrorCodes.WorktreeAlreadyExists) { await this.handleWorktreeAlreadyExists(err); - } else if (err.gitErrorCode === GitErrorCodes.WorktreeBranchAlreadyUsed) { + } else if (err instanceof GitError && err.gitErrorCode === GitErrorCodes.WorktreeBranchAlreadyUsed) { await this.handleWorktreeBranchAlreadyUsed(err); } else { throw err; @@ -3742,8 +3796,8 @@ export class CommandCenter { } } - private async handleWorktreeBranchAlreadyUsed(err: any): Promise { - const match = err.stderr.match(/fatal: '([^']+)' is already used by worktree at '([^']+)'/); + private async handleWorktreeBranchAlreadyUsed(err: GitError): Promise { + const match = err.stderr?.match(/fatal: '([^']+)' is already used by worktree at '([^']+)'/); if (!match) { return; @@ -3754,8 +3808,8 @@ export class CommandCenter { await this.handleWorktreeConflict(path, message); } - private async handleWorktreeAlreadyExists(err: any): Promise { - const match = err.stderr.match(/fatal: '([^']+)'/); + private async handleWorktreeAlreadyExists(err: GitError): Promise { + const match = err.stderr?.match(/fatal: '([^']+)'/); if (!match) { return; @@ -3799,11 +3853,11 @@ export class CommandCenter { return; } - // Dispose worktree repository - this.model.disposeRepository(repository); - try { await mainRepository.deleteWorktree(repository.root); + + // Dispose worktree repository + this.model.disposeRepository(repository); } catch (err) { if (err.gitErrorCode === GitErrorCodes.WorktreeContainsChanges) { const forceDelete = l10n.t('Force Delete'); @@ -3811,8 +3865,9 @@ export class CommandCenter { const choice = await window.showWarningMessage(message, { modal: true }, forceDelete); if (choice === forceDelete) { await mainRepository.deleteWorktree(repository.root, { force: true }); - } else { - await this.model.openRepository(repository.root); + + // Dispose worktree repository + this.model.disposeRepository(repository); } return; @@ -4858,7 +4913,7 @@ export class CommandCenter { else if (item.previousRef === 'HEAD' && item.ref === '~') { title = l10n.t('{0} (Index)', basename); } else { - title = l10n.t('{0} ({1}) ↔ {0} ({2})', basename, item.shortPreviousRef, item.shortRef); + title = l10n.t('{0} ({1}) \u2194 {0} ({2})', basename, item.shortPreviousRef, item.shortRef); } return { @@ -4901,7 +4956,7 @@ export class CommandCenter { const commit = await repository.getCommit(item.ref); const commitParentId = commit.parents.length > 0 ? commit.parents[0] : await repository.getEmptyTree(); - const changes = await repository.diffTrees(commitParentId, commit.hash); + const changes = await repository.diffBetween2(commitParentId, commit.hash); const resources = changes.map(c => toMultiFileDiffEditorUris(c, commitParentId, commit.hash)); const title = `${item.shortRef} - ${subject(commit.message)}`; @@ -4975,7 +5030,7 @@ export class CommandCenter { } - const title = l10n.t('{0} ↔ {1}', leftTitle, rightTitle); + const title = l10n.t('{0} \u2194 {1}', leftTitle, rightTitle); await commands.executeCommand('vscode.diff', selected.ref === '' ? uri : toGitUri(uri, selected.ref), item.ref === '' ? uri : toGitUri(uri, item.ref), title); } @@ -5175,7 +5230,7 @@ export class CommandCenter { const multiDiffSourceUri = Uri.from({ scheme: 'scm-history-item', path: `${repository.root}/${historyItemParentId}..${historyItemId}` }); - const changes = await repository.diffTrees(historyItemParentId, historyItemId); + const changes = await repository.diffBetween2(historyItemParentId, historyItemId); const resources = changes.map(c => toMultiFileDiffEditorUris(c, historyItemParentId, historyItemId)); const reveal = revealUri ? { modifiedUri: toGitUri(revealUri, historyItemId) } : undefined; @@ -5208,6 +5263,162 @@ export class CommandCenter { config.update(setting, !enabled, true); } + @command('git.repositories.createBranch', { repository: true }) + async artifactGroupCreateBranch(repository: Repository): Promise { + if (!repository) { + return; + } + + await this._branch(repository, undefined, false); + } + + @command('git.repositories.createTag', { repository: true }) + async artifactGroupCreateTag(repository: Repository): Promise { + if (!repository) { + return; + } + + await this._createTag(repository); + } + + @command('git.repositories.checkout', { repository: true }) + async artifactCheckout(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + await this._checkout(repository, { treeish: artifact.name }); + } + + @command('git.repositories.checkoutDetached', { repository: true }) + async artifactCheckoutDetached(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + await this._checkout(repository, { treeish: artifact.name, detached: true }); + } + + @command('git.repositories.merge', { repository: true }) + async artifactMerge(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + await repository.merge(artifact.id); + } + + @command('git.repositories.rebase', { repository: true }) + async artifactRebase(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + await repository.rebase(artifact.id); + } + + @command('git.repositories.createFrom', { repository: true }) + async artifactCreateFrom(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + await this._branch(repository, undefined, false, artifact.id); + } + + @command('git.repositories.compareRef', { repository: true }) + async artifactCompareWith(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + const config = workspace.getConfiguration('git'); + const showRefDetails = config.get('showReferenceDetails') === true; + + const getRefPicks = async () => { + const refs = await repository.getRefs({ includeCommitDetails: showRefDetails }); + const processors = [ + new RefProcessor(RefType.Head, BranchItem), + new RefProcessor(RefType.RemoteHead, BranchItem), + new RefProcessor(RefType.Tag, BranchItem) + ]; + + const itemsProcessor = new RefItemsProcessor(repository, processors); + return itemsProcessor.processRefs(refs); + }; + + const placeHolder = l10n.t('Select a reference to compare with'); + const sourceRef = await this.pickRef(getRefPicks(), placeHolder); + + if (!(sourceRef instanceof BranchItem) || !sourceRef.ref.commit) { + return; + } + + await this._openChangesBetweenRefs( + repository, + { + id: sourceRef.ref.commit, + displayId: sourceRef.ref.name + }, + { + id: artifact.id, + displayId: artifact.name + }); + } + + private async _createTag(repository: Repository, ref?: string): Promise { + const inputTagName = await window.showInputBox({ + placeHolder: l10n.t('Tag name'), + prompt: l10n.t('Please provide a tag name'), + ignoreFocusOut: true + }); + + if (!inputTagName) { + return; + } + + const inputMessage = await window.showInputBox({ + placeHolder: l10n.t('Message'), + prompt: l10n.t('Please provide a message to annotate the tag'), + ignoreFocusOut: true + }); + + const name = inputTagName.replace(/^\.|\/\.|\.\.|~|\^|:|\/$|\.lock$|\.lock\/|\\|\*|\s|^\s*$|\.$/g, '-'); + await repository.tag({ name, message: inputMessage, ref }); + } + + @command('git.repositories.deleteBranch', { repository: true }) + async artifactDeleteBranch(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + const message = l10n.t('Are you sure you want to delete branch "{0}"? This action will permanently remove the branch reference from the repository.', artifact.name); + const yes = l10n.t('Delete Branch'); + const result = await window.showWarningMessage(message, { modal: true }, yes); + if (result !== yes) { + return; + } + + await this._deleteBranch(repository, undefined, artifact.name, { remote: false }); + } + + @command('git.repositories.deleteTag', { repository: true }) + async artifactDeleteTag(repository: Repository, artifact: SourceControlArtifact): Promise { + if (!repository || !artifact) { + return; + } + + const message = l10n.t('Are you sure you want to delete tag "{0}"? This action will permanently remove the tag reference from the repository.', artifact.name); + const yes = l10n.t('Delete Tag'); + const result = await window.showWarningMessage(message, { modal: true }, yes); + if (result !== yes) { + return; + } + + await repository.deleteTag(artifact.name); + } + private createCommand(id: string, key: string, method: Function, options: ScmCommandOptions): (...args: any[]) => any { const result = (...args: any[]) => { let result: Promise; diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts index 763d4aaa751..b8b5fc26723 100644 --- a/extensions/git/src/decorationProvider.ts +++ b/extensions/git/src/decorationProvider.ts @@ -32,7 +32,7 @@ class GitIgnoreDecorationProvider implements FileDecorationProvider { private disposables: Disposable[] = []; constructor(private model: Model) { - const onDidChangeRepository = anyEvent( + const onDidChangeRepository = anyEvent( filterEvent(workspace.onDidSaveTextDocument, e => /\.gitignore$|\.git\/info\/exclude$/.test(e.uri.path)), model.onDidOpenRepository, model.onDidCloseRepository @@ -257,7 +257,7 @@ class GitIncomingChangesFileDecorationProvider implements FileDecorationProvider return []; } - const changes = await this.repository.diffBetween(ancestor, currentHistoryItemRemoteRef.id); + const changes = await this.repository.diffBetween2(ancestor, currentHistoryItemRemoteRef.id); return changes; } catch (err) { return []; diff --git a/extensions/git/src/decorators.ts b/extensions/git/src/decorators.ts index cd1c7d72d3b..0e59a849ed2 100644 --- a/extensions/git/src/decorators.ts +++ b/extensions/git/src/decorators.ts @@ -6,8 +6,8 @@ import { done } from './util'; function decorate(decorator: (fn: Function, key: string) => Function): Function { - return function (original: any, context: ClassMethodDecoratorContext) { - if (context.kind === 'method' || context.kind === 'getter' || context.kind === 'setter') { + return function (original: unknown, context: ClassMethodDecoratorContext) { + if (typeof original === 'function' && (context.kind === 'method' || context.kind === 'getter' || context.kind === 'setter')) { return decorator(original, context.name.toString()); } throw new Error('not supported'); diff --git a/extensions/git/src/git-editor-main.ts b/extensions/git/src/git-editor-main.ts index eb4da4a40b5..80615b56e5a 100644 --- a/extensions/git/src/git-editor-main.ts +++ b/extensions/git/src/git-editor-main.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IPCClient } from './ipc/ipcClient'; -function fatal(err: any): void { +function fatal(err: unknown): void { console.error(err); process.exit(1); } diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index bb3685a53e4..44654bd4897 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -117,7 +117,7 @@ function findGitDarwin(onValidate: (path: string) => boolean): Promise { } // must check if XCode is installed - cp.exec('xcode-select -p', (err: any) => { + cp.exec('xcode-select -p', (err) => { if (err && err.code === 2) { // git is not installed, and launching /usr/bin/git // will prompt the user to install it @@ -1620,7 +1620,7 @@ export class Repository { diffWithHEAD(path?: string | undefined): Promise; async diffWithHEAD(path?: string | undefined): Promise { if (!path) { - return await this.diffFiles(false); + return await this.diffFiles(undefined, { cached: false }); } const args = ['diff', '--', this.sanitizeRelativePath(path)]; @@ -1628,12 +1628,16 @@ export class Repository { return result.stdout; } + async diffWithHEADShortStats(path?: string): Promise { + return this.diffFilesShortStat(undefined, { cached: false, path }); + } + diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; diffWith(ref: string, path?: string | undefined): Promise; async diffWith(ref: string, path?: string): Promise { if (!path) { - return await this.diffFiles(false, ref); + return await this.diffFiles(ref, { cached: false }); } const args = ['diff', ref, '--', this.sanitizeRelativePath(path)]; @@ -1646,7 +1650,7 @@ export class Repository { diffIndexWithHEAD(path?: string | undefined): Promise; async diffIndexWithHEAD(path?: string): Promise { if (!path) { - return await this.diffFiles(true); + return await this.diffFiles(undefined, { cached: true }); } const args = ['diff', '--cached', '--', this.sanitizeRelativePath(path)]; @@ -1654,12 +1658,16 @@ export class Repository { return result.stdout; } + async diffIndexWithHEADShortStats(path?: string): Promise { + return this.diffFilesShortStat(undefined, { cached: true, path }); + } + diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffIndexWith(ref: string, path?: string | undefined): Promise; async diffIndexWith(ref: string, path?: string): Promise { if (!path) { - return await this.diffFiles(true, ref); + return await this.diffFiles(ref, { cached: true }); } const args = ['diff', '--cached', ref, '--', this.sanitizeRelativePath(path)]; @@ -1679,7 +1687,7 @@ export class Repository { async diffBetween(ref1: string, ref2: string, path?: string): Promise { const range = `${ref1}...${ref2}`; if (!path) { - return await this.diffFiles(false, range); + return await this.diffFiles(range, { cached: false }); } const args = ['diff', range, '--', this.sanitizeRelativePath(path)]; @@ -1688,8 +1696,51 @@ export class Repository { return result.stdout.trim(); } - async diffBetweenShortStat(ref1: string, ref2: string): Promise<{ files: number; insertions: number; deletions: number }> { - const args = ['diff', '--shortstat', `${ref1}...${ref2}`]; + async diffBetween2(ref1: string, ref2: string, options: { similarityThreshold?: number }): Promise { + return await this.diffFiles(`${ref1}...${ref2}`, { cached: false, similarityThreshold: options.similarityThreshold }); + } + + private async diffFiles(ref: string | undefined, options: { cached: boolean; similarityThreshold?: number }): Promise { + const args = ['diff', '--name-status', '-z', '--diff-filter=ADMR']; + + if (options.cached) { + args.push('--cached'); + } + + if (options.similarityThreshold) { + args.push(`--find-renames=${options.similarityThreshold}%`); + } + + if (ref) { + args.push(ref); + } + + args.push('--'); + + const gitResult = await this.exec(args); + if (gitResult.exitCode) { + return []; + } + + return parseGitChanges(this.repositoryRoot, gitResult.stdout); + } + + private async diffFilesShortStat(ref: string | undefined, options: { cached: boolean; path?: string }): Promise { + const args = ['diff', '--shortstat']; + + if (options.cached) { + args.push('--cached'); + } + + if (ref !== undefined) { + args.push(ref); + } + + args.push('--'); + + if (options.path) { + args.push(this.sanitizeRelativePath(options.path)); + } const result = await this.exec(args); if (result.exitCode) { @@ -1699,23 +1750,6 @@ export class Repository { return parseGitDiffShortStat(result.stdout.trim()); } - private async diffFiles(cached: boolean, ref?: string): Promise { - const args = ['diff', '--name-status', '-z', '--diff-filter=ADMR']; - if (cached) { - args.push('--cached'); - } - - if (ref) { - args.push(ref); - } - - const gitResult = await this.exec(args); - if (gitResult.exitCode) { - return []; - } - - return parseGitChanges(this.repositoryRoot, gitResult.stdout); - } async diffTrees(treeish1: string, treeish2?: string, options?: { similarityThreshold?: number }): Promise { const args = ['diff-tree', '-r', '--name-status', '-z', '--diff-filter=ADMR']; @@ -1730,6 +1764,8 @@ export class Repository { args.push(treeish2); } + args.push('--'); + const gitResult = await this.exec(args); if (gitResult.exitCode) { return []; @@ -1939,11 +1975,12 @@ export class Repository { } } - private async handleCommitError(commitErr: any): Promise { - if (/not possible because you have unmerged files/.test(commitErr.stderr || '')) { + + private async handleCommitError(commitErr: unknown): Promise { + if (commitErr instanceof GitError && /not possible because you have unmerged files/.test(commitErr.stderr || '')) { commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges; throw commitErr; - } else if (/Aborting commit due to empty commit message/.test(commitErr.stderr || '')) { + } else if (commitErr instanceof GitError && /Aborting commit due to empty commit message/.test(commitErr.stderr || '')) { commitErr.gitErrorCode = GitErrorCodes.EmptyCommitMessage; throw commitErr; } @@ -2077,8 +2114,8 @@ export class Repository { const pathsByGroup = groupBy(paths.map(sanitizePath), p => path.dirname(p)); const groups = Object.keys(pathsByGroup).map(k => pathsByGroup[k]); - const limiter = new Limiter(5); - const promises: Promise[] = []; + const limiter = new Limiter>(5); + const promises: Promise>[] = []; const args = ['clean', '-f', '-q']; for (const paths of groups) { diff --git a/extensions/git/src/gitEditor.ts b/extensions/git/src/gitEditor.ts index 6291e5152a7..cbbea2c6d78 100644 --- a/extensions/git/src/gitEditor.ts +++ b/extensions/git/src/gitEditor.ts @@ -34,7 +34,7 @@ export class GitEditor implements IIPCHandler, ITerminalEnvironmentProvider { }; } - async handle({ commitMessagePath }: GitEditorRequest): Promise { + async handle({ commitMessagePath }: GitEditorRequest): Promise { if (commitMessagePath) { const uri = Uri.file(commitMessagePath); const doc = await workspace.openTextDocument(uri); @@ -49,6 +49,8 @@ export class GitEditor implements IIPCHandler, ITerminalEnvironmentProvider { }); }); } + + return Promise.resolve(false); } getEnv(): { [key: string]: string } { diff --git a/extensions/git/src/historyProvider.ts b/extensions/git/src/historyProvider.ts index 77512ecb465..9f2b81fd7b5 100644 --- a/extensions/git/src/historyProvider.ts +++ b/extensions/git/src/historyProvider.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ -import { CancellationToken, Disposable, Event, EventEmitter, FileDecoration, FileDecorationProvider, SourceControlHistoryItem, SourceControlHistoryItemChange, SourceControlHistoryOptions, SourceControlHistoryProvider, ThemeIcon, Uri, window, LogOutputChannel, SourceControlHistoryItemRef, l10n, SourceControlHistoryItemRefsChangeEvent, workspace, ConfigurationChangeEvent, MarkdownString, Command } from 'vscode'; +import { CancellationToken, Disposable, Event, EventEmitter, FileDecoration, FileDecorationProvider, SourceControlHistoryItem, SourceControlHistoryItemChange, SourceControlHistoryOptions, SourceControlHistoryProvider, ThemeIcon, Uri, window, LogOutputChannel, SourceControlHistoryItemRef, l10n, SourceControlHistoryItemRefsChangeEvent, workspace, ConfigurationChangeEvent, MarkdownString, Command, commands } from 'vscode'; import { Repository, Resource } from './repository'; import { IDisposable, deltaHistoryItemRefs, dispose, filterEvent, fromNow, getCommitShortHash, subject, truncate } from './util'; import { toMultiFileDiffEditorUris } from './uri'; @@ -12,17 +12,21 @@ import { AvatarQuery, AvatarQueryCommit, Branch, LogOptions, Ref, RefType } from import { emojify, ensureEmojis } from './emoji'; import { Commit, CommitShortStat } from './git'; import { OperationKind, OperationResult } from './operation'; -import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider'; +import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemHoverCommands, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider'; import { throttle } from './decorators'; -function compareSourceControlHistoryItemRef(ref1: SourceControlHistoryItemRef, ref2: SourceControlHistoryItemRef): number { - const getOrder = (ref: SourceControlHistoryItemRef): number => { +type SourceControlHistoryItemRefWithRenderOptions = SourceControlHistoryItemRef & { + backgroundColor?: string; +}; + +function compareSourceControlHistoryItemRef(ref1: SourceControlHistoryItemRefWithRenderOptions, ref2: SourceControlHistoryItemRefWithRenderOptions): number { + const getOrder = (ref: SourceControlHistoryItemRefWithRenderOptions): number => { if (ref.id.startsWith('refs/heads/')) { - return 1; + return ref.backgroundColor ? 1 : 5; } else if (ref.id.startsWith('refs/remotes/')) { - return 2; + return ref.backgroundColor ? 2 : 15; } else if (ref.id.startsWith('refs/tags/')) { - return 3; + return ref.backgroundColor ? 3 : 25; } return 99; @@ -124,7 +128,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec id: `refs/heads/${this.repository.HEAD.upstream.name}`, name: this.repository.HEAD.upstream.name, revision: this.repository.HEAD.upstream.commit, - icon: new ThemeIcon('gi-branch') + icon: new ThemeIcon('git-branch') }; } else { // Remote branch @@ -185,6 +189,14 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec } } + // Update context keys for HEAD + if (this._HEAD?.ahead !== this.repository.HEAD?.ahead) { + commands.executeCommand('setContext', 'git.currentHistoryItemIsAhead', (this.repository.HEAD?.ahead ?? 0) > 0); + } + if (this._HEAD?.behind !== this.repository.HEAD?.behind) { + commands.executeCommand('setContext', 'git.currentHistoryItemIsBehind', (this.repository.HEAD?.behind ?? 0) > 0); + } + this._HEAD = this.repository.HEAD; this._currentHistoryItemRef = { @@ -282,6 +294,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const commitAvatars = await provideSourceControlHistoryItemAvatar( this.historyItemDetailProviderRegistry, this.repository, avatarQuery); + const remoteHoverCommands = await provideSourceControlHistoryItemHoverCommands(this.historyItemDetailProviderRegistry, this.repository) ?? []; + await ensureEmojis(); const historyItems: SourceControlHistoryItem[] = []; @@ -293,6 +307,13 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const avatarUrl = commitAvatars?.get(commit.hash); const references = this._resolveHistoryItemRefs(commit); + const commands: Command[][] = [ + getHistoryItemHoverCommitHashCommands(Uri.file(this.repository.root), commit.hash), + processHistoryItemRemoteHoverCommands(remoteHoverCommands, commit.hash) + ]; + + const tooltip = getHistoryItemHover(avatarUrl, commit.authorName, commit.authorEmail, commit.authorDate ?? commit.commitDate, messageWithLinks, commit.shortStat, references, commands); + historyItems.push({ id: commit.hash, parentIds: commit.parents, @@ -304,7 +325,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec displayId: truncate(commit.hash, this.commitShortHashLength, false), timestamp: commit.authorDate?.getTime(), statistics: commit.shortStat ?? { files: 0, insertions: 0, deletions: 0 }, - references: references.length !== 0 ? references : undefined + references: references.length !== 0 ? references : undefined, + tooltip } satisfies SourceControlHistoryItem); } @@ -320,7 +342,7 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const historyItemChangesUri: Uri[] = []; const historyItemChanges: SourceControlHistoryItemChange[] = []; - const changes = await this.repository.diffTrees(historyItemParentId, historyItemId); + const changes = await this.repository.diffBetween2(historyItemParentId, historyItemId); for (const change of changes) { const historyItemUri = change.uri.with({ @@ -467,8 +489,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec return this.historyItemDecorations.get(uri.toString()); } - private _resolveHistoryItemRefs(commit: Commit): SourceControlHistoryItemRef[] { - const references: SourceControlHistoryItemRef[] = []; + private _resolveHistoryItemRefs(commit: Commit): SourceControlHistoryItemRefWithRenderOptions[] { + const references: SourceControlHistoryItemRefWithRenderOptions[] = []; for (const ref of commit.refNames) { if (ref === 'refs/remotes/origin/HEAD') { @@ -482,7 +504,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec name: ref.substring('HEAD -> refs/heads/'.length), revision: commit.hash, category: l10n.t('branches'), - icon: new ThemeIcon('target') + icon: new ThemeIcon('target'), + backgroundColor: `--vscode-scmGraph-historyItemRefColor` }); break; case ref.startsWith('refs/heads/'): @@ -500,7 +523,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec name: ref.substring('refs/remotes/'.length), revision: commit.hash, category: l10n.t('remote branches'), - icon: new ThemeIcon('cloud') + icon: new ThemeIcon('cloud'), + backgroundColor: `--vscode-scmGraph-historyItemRemoteRefColor` }); break; case ref.startsWith('tag: refs/tags/'): @@ -509,7 +533,10 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec name: ref.substring('tag: refs/tags/'.length), revision: commit.hash, category: l10n.t('tags'), - icon: new ThemeIcon('tag') + icon: new ThemeIcon('tag'), + backgroundColor: ref === this.currentHistoryItemRef?.id + ? `--vscode-scmGraph-historyItemRefColor` + : undefined }); break; } @@ -614,32 +641,53 @@ export function processHistoryItemRemoteHoverCommands(commands: Command[], hash: } satisfies Command)); } -export function getHistoryItemHover(authorAvatar: string | undefined, authorName: string | undefined, authorEmail: string | undefined, authorDate: Date | number | undefined, message: string, shortStats: CommitShortStat | undefined, commands: Command[][] | undefined): MarkdownString { +export function getHistoryItemHover(authorAvatar: string | undefined, authorName: string | undefined, authorEmail: string | undefined, authorDate: Date | number | undefined, message: string, shortStats: CommitShortStat | undefined, references: SourceControlHistoryItemRefWithRenderOptions[] | undefined, commands: Command[][] | undefined): MarkdownString { const markdownString = new MarkdownString('', true); - markdownString.isTrusted = true; + markdownString.isTrusted = { + enabledCommands: commands?.flat().map(c => c.command) ?? [] + }; + // Author if (authorName) { - const avatar = authorAvatar ? `![${authorName}](${authorAvatar}|width=${AVATAR_SIZE},height=${AVATAR_SIZE})` : '$(account)'; - - if (authorEmail) { - const emailTitle = l10n.t('Email'); - markdownString.appendMarkdown(`${avatar} [**${authorName}**](mailto:${authorEmail} "${emailTitle} ${authorName}")`); + // Avatar + if (authorAvatar) { + markdownString.appendMarkdown('!['); + markdownString.appendText(authorName); + markdownString.appendMarkdown(']('); + markdownString.appendText(authorAvatar); + markdownString.appendMarkdown(`|width=${AVATAR_SIZE},height=${AVATAR_SIZE})`); } else { - markdownString.appendMarkdown(`${avatar} **${authorName}**`); + markdownString.appendMarkdown('$(account)'); } - if (authorDate) { + // Email + if (authorEmail) { + markdownString.appendMarkdown(' [**'); + markdownString.appendText(authorName); + markdownString.appendMarkdown('**](mailto:'); + markdownString.appendText(authorEmail); + markdownString.appendMarkdown(')'); + } else { + markdownString.appendMarkdown(' **'); + markdownString.appendText(authorName); + markdownString.appendMarkdown('**'); + } + + // Date + if (authorDate && !isNaN(new Date(authorDate).getTime())) { const dateString = new Date(authorDate).toLocaleString(undefined, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }); - markdownString.appendMarkdown(`, $(history) ${fromNow(authorDate, true, true)} (${dateString})`); + + markdownString.appendMarkdown(', $(history)'); + markdownString.appendText(` ${fromNow(authorDate, true, true)} (${dateString})`); } markdownString.appendMarkdown('\n\n'); } - // Subject | Message - markdownString.appendMarkdown(`${emojify(message.replace(/\r\n|\r|\n/g, '\n\n'))}\n\n`); + // Subject | Message (escape image syntax) + markdownString.appendMarkdown(`${emojify(message.replace(/!\[/g, '![').replace(/\r\n|\r|\n/g, '\n\n'))}\n\n`); markdownString.appendMarkdown(`---\n\n`); // Short stats @@ -663,6 +711,21 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName markdownString.appendMarkdown(`\n\n---\n\n`); } + // References + if (references && references.length > 0) { + for (const reference of references) { + const labelIconId = reference.icon instanceof ThemeIcon ? reference.icon.id : ''; + const backgroundColor = `var(${reference.backgroundColor ?? '--vscode-scmGraph-historyItemHoverDefaultLabelBackground'})`; + const color = reference.backgroundColor ? `var(--vscode-scmGraph-historyItemHoverLabelForeground)` : `var(--vscode-scmGraph-historyItemHoverDefaultLabelForeground)`; + + markdownString.appendMarkdown(` $(${labelIconId}) `); + markdownString.appendText(reference.name); + markdownString.appendMarkdown(`  `); + } + + markdownString.appendMarkdown(`\n\n---\n\n`); + } + // Commands if (commands && commands.length > 0) { for (let index = 0; index < commands.length; index++) { @@ -676,21 +739,5 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName } } - // markdownString.appendMarkdown(`[\`$(git-commit) ${getCommitShortHash(documentUri, hash)} \`](command:git.viewCommit?${encodeURIComponent(JSON.stringify([documentUri, hash, documentUri]))} "${l10n.t('Open Commit')}")`); - // markdownString.appendMarkdown(' '); - // markdownString.appendMarkdown(`[$(copy)](command:git.copyContentToClipboard?${encodeURIComponent(JSON.stringify(hash))} "${l10n.t('Copy Commit Hash')}")`); - - // // Remote hover commands - // if (commands && commands.length > 0) { - // markdownString.appendMarkdown('  |  '); - - // const remoteCommandsMarkdown = commands - // .map(command => `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify([...command.arguments ?? [], hash]))} "${command.tooltip}")`); - // markdownString.appendMarkdown(remoteCommandsMarkdown.join(' ')); - // } - - // markdownString.appendMarkdown('  |  '); - // markdownString.appendMarkdown(`[$(gear)](command:workbench.action.openSettings?%5B%22git.blame%22%5D "${l10n.t('Open Settings')}")`); - return markdownString; } diff --git a/extensions/git/src/ipc/ipcClient.ts b/extensions/git/src/ipc/ipcClient.ts index f623b3f7b6f..9aab55e44a3 100644 --- a/extensions/git/src/ipc/ipcClient.ts +++ b/extensions/git/src/ipc/ipcClient.ts @@ -19,7 +19,7 @@ export class IPCClient { this.ipcHandlePath = ipcHandlePath; } - call(request: any): Promise { + call(request: unknown): Promise { const opts: http.RequestOptions = { socketPath: this.ipcHandlePath, path: `/${this.handlerName}`, diff --git a/extensions/git/src/ipc/ipcServer.ts b/extensions/git/src/ipc/ipcServer.ts index a7142fe22e1..5e56f9ceef5 100644 --- a/extensions/git/src/ipc/ipcServer.ts +++ b/extensions/git/src/ipc/ipcServer.ts @@ -25,7 +25,7 @@ function getIPCHandlePath(id: string): string { } export interface IIPCHandler { - handle(request: any): Promise; + handle(request: unknown): Promise; } export async function createIPCServer(context?: string): Promise { diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index e48e2e339b5..535c0f2f30e 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -27,16 +27,17 @@ import { GitPostCommitCommandsProvider } from './postCommitCommands'; import { GitEditSessionIdentityProvider } from './editSessionIdentityProvider'; import { GitCommitInputBoxCodeActionsProvider, GitCommitInputBoxDiagnosticsManager } from './diagnostics'; import { GitBlameController } from './blame'; +import { CloneManager } from './cloneManager'; -const deactivateTasks: { (): Promise }[] = []; +const deactivateTasks: { (): Promise }[] = []; -export async function deactivate(): Promise { +export async function deactivate(): Promise { for (const task of deactivateTasks) { await task(); } } -async function createModel(context: ExtensionContext, logger: LogOutputChannel, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise { +async function createModel(context: ExtensionContext, logger: LogOutputChannel, telemetryReporter: TelemetryReporter, disposables: Disposable[]): Promise<{ model: Model; cloneManager: CloneManager }> { const pathValue = workspace.getConfiguration('git').get('path'); let pathHints = Array.isArray(pathValue) ? pathValue : pathValue ? [pathValue] : []; @@ -90,6 +91,7 @@ async function createModel(context: ExtensionContext, logger: LogOutputChannel, }); const model = new Model(git, askpass, context.globalState, context.workspaceState, logger, telemetryReporter); disposables.push(model); + const cloneManager = new CloneManager(model, telemetryReporter, model.repositoryCache); const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`); model.onDidOpenRepository(onRepository, null, disposables); @@ -108,7 +110,7 @@ async function createModel(context: ExtensionContext, logger: LogOutputChannel, git.onOutput.addListener('log', onOutput); disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput))); - const cc = new CommandCenter(git, model, context.globalState, logger, telemetryReporter); + const cc = new CommandCenter(git, model, context.globalState, logger, telemetryReporter, cloneManager); disposables.push( cc, new GitFileSystemProvider(model, logger), @@ -134,7 +136,7 @@ async function createModel(context: ExtensionContext, logger: LogOutputChannel, checkGitVersion(info); commands.executeCommand('setContext', 'gitVersion2.35', git.compareGitVersionTo('2.35') >= 0); - return model; + return { model, cloneManager }; } async function isGitRepository(folder: WorkspaceFolder): Promise { @@ -210,13 +212,18 @@ export async function _activate(context: ExtensionContext): Promise workspace.getConfiguration('git', null).get('enabled') === true); const result = new GitExtensionImpl(); - eventToPromise(onEnabled).then(async () => result.model = await createModel(context, logger, telemetryReporter, disposables)); + eventToPromise(onEnabled).then(async () => { + const { model, cloneManager } = await createModel(context, logger, telemetryReporter, disposables); + result.model = model; + result.cloneManager = cloneManager; + }); return result; } try { - const model = await createModel(context, logger, telemetryReporter, disposables); - return new GitExtensionImpl(model); + const { model, cloneManager } = await createModel(context, logger, telemetryReporter, disposables); + + return new GitExtensionImpl({ model, cloneManager }); } catch (err) { console.warn(err.message); logger.warn(`[main] Failed to create model: ${err}`); diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index 0fe0055e5a6..f553132f2b0 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -20,6 +20,7 @@ import { IRemoteSourcePublisherRegistry } from './remotePublisher'; import { IPostCommitCommandsProviderRegistry } from './postCommitCommands'; import { IBranchProtectionProviderRegistry } from './branchProtection'; import { ISourceControlHistoryItemDetailsProviderRegistry } from './historyItemDetailsProvider'; +import { RepositoryCache } from './repositoryCache'; class RepositoryPick implements QuickPickItem { @memoize get label(): string { @@ -226,7 +227,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi return Promise.resolve(); } - return eventToPromise(filterEvent(this.onDidChangeState, s => s === 'initialized')) as Promise; + return eventToPromise(filterEvent(this.onDidChangeState, s => s === 'initialized') as Event) as Promise; } private remoteSourcePublishers = new Set(); @@ -275,9 +276,14 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi */ private _workspaceFolders = new Map(); + private readonly _repositoryCache: RepositoryCache; + get repositoryCache(): RepositoryCache { + return this._repositoryCache; + } + private disposables: Disposable[] = []; - constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, readonly workspaceState: Memento, private logger: LogOutputChannel, private telemetryReporter: TelemetryReporter) { + constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, readonly workspaceState: Memento, private logger: LogOutputChannel, private readonly telemetryReporter: TelemetryReporter) { // Repositories managers this._closedRepositoriesManager = new ClosedRepositoriesManager(workspaceState); this._parentRepositoriesManager = new ParentRepositoriesManager(globalState); @@ -298,6 +304,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi this.setState('uninitialized'); this.doInitialScan().finally(() => this.setState('initialized')); + this._repositoryCache = new RepositoryCache(globalState, logger); } private async doInitialScan(): Promise { @@ -653,7 +660,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi // Open repository const [dotGit, repositoryRootRealPath] = await Promise.all([this.git.getRepositoryDotGit(repositoryRoot), this.getRepositoryRootRealPath(repositoryRoot)]); const gitRepository = this.git.open(repositoryRoot, repositoryRootRealPath, dotGit, this.logger); - const repository = new Repository(gitRepository, this, this, this, this, this, this, this.globalState, this.logger, this.telemetryReporter); + const repository = new Repository(gitRepository, this, this, this, this, this, this, this.globalState, this.logger, this.telemetryReporter, this._repositoryCache); this.open(repository); this._closedRepositoriesManager.deleteRepository(repository.root); @@ -664,7 +671,9 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi // Do not await this, we want SCM // to know about the repo asap - repository.status(); + repository.status().then(() => { + this._repositoryCache.update(repository.remotes, [], repository.root); + }); } catch (err) { // noop this.logger.trace(`[Model][openRepository] Opening repository for path='${repoPath}' failed. Error:${err}`); @@ -826,7 +835,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi commands.executeCommand('setContext', 'operationInProgress', operationInProgress); }; - const operationEvent = anyEvent(repository.onDidRunOperation as Event, repository.onRunOperation as Event); + const operationEvent = anyEvent(repository.onDidRunOperation as Event, repository.onRunOperation as Event); const operationListener = operationEvent(() => updateOperationInProgressContext()); updateOperationInProgressContext(); @@ -858,7 +867,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi this.logger.info(`[Model][close] Repository: ${repository.root}`); this._closedRepositoriesManager.addRepository(openRepository.repository.root); - + this._repositoryCache.update(repository.remotes, [], repository.root); openRepository.dispose(); } @@ -892,11 +901,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi return pick && pick.repository; } - getRepository(sourceControl: SourceControl): Repository | undefined; - getRepository(resourceGroup: SourceControlResourceGroup): Repository | undefined; - getRepository(path: string): Repository | undefined; - getRepository(resource: Uri): Repository | undefined; - getRepository(hint: any): Repository | undefined { + getRepository(hint: SourceControl | SourceControlResourceGroup | Uri | string): Repository | undefined { const liveRepository = this.getOpenRepository(hint); return liveRepository && liveRepository.repository; } @@ -923,12 +928,7 @@ export class Model implements IRepositoryResolver, IBranchProtectionProviderRegi } } - private getOpenRepository(repository: Repository): OpenRepository | undefined; - private getOpenRepository(sourceControl: SourceControl): OpenRepository | undefined; - private getOpenRepository(resourceGroup: SourceControlResourceGroup): OpenRepository | undefined; - private getOpenRepository(path: string): OpenRepository | undefined; - private getOpenRepository(resource: Uri): OpenRepository | undefined; - private getOpenRepository(hint: any): OpenRepository | undefined { + private getOpenRepository(hint: SourceControl | SourceControlResourceGroup | Repository | Uri | string): OpenRepository | undefined { if (!hint) { return undefined; } diff --git a/extensions/git/src/operation.ts b/extensions/git/src/operation.ts index eaa91d4a047..4519c1f335b 100644 --- a/extensions/git/src/operation.ts +++ b/extensions/git/src/operation.ts @@ -200,7 +200,7 @@ export const Operation = { export interface OperationResult { operation: Operation; - error: any; + error: unknown; } interface IOperationManager { diff --git a/extensions/git/src/protocolHandler.ts b/extensions/git/src/protocolHandler.ts index 90491fecd50..42289abcb9c 100644 --- a/extensions/git/src/protocolHandler.ts +++ b/extensions/git/src/protocolHandler.ts @@ -21,6 +21,7 @@ export class GitProtocolHandler implements UriHandler { this.disposables.push(window.registerUriHandler(this)); } + // example code-oss://vscode.git/clone?url=https://github.com/microsoft/vscode handleUri(uri: Uri): void { this.logger.info(`[GitProtocolHandler][handleUri] URI:(${uri.toString()})`); diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index 619a2c70e9f..f62ef8d45cd 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -14,7 +14,7 @@ import { Branch, BranchQuery, Change, CommitOptions, FetchOptions, ForcePushMode import { AutoFetcher } from './autofetch'; import { GitBranchProtectionProvider, IBranchProtectionProviderRegistry } from './branchProtection'; import { debounce, memoize, sequentialize, throttle } from './decorators'; -import { Repository as BaseRepository, BlameInformation, Commit, GitError, LogFileOptions, LsTreeElement, PullOptions, RefQuery, Stash, Submodule, Worktree } from './git'; +import { Repository as BaseRepository, BlameInformation, Commit, CommitShortStat, GitError, LogFileOptions, LsTreeElement, PullOptions, RefQuery, Stash, Submodule, Worktree } from './git'; import { GitHistoryProvider } from './historyProvider'; import { Operation, OperationKind, OperationManager, OperationResult } from './operation'; import { CommitCommandsCenter, IPostCommitCommandsProviderRegistry } from './postCommitCommands'; @@ -25,6 +25,8 @@ import { toGitUri } from './uri'; import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, eventToPromise, filterEvent, find, getCommitShortHash, IDisposable, isDescendant, isLinuxSnap, isRemote, isWindows, Limiter, onceEvent, pathEquals, relativePath } from './util'; import { IFileWatcher, watch } from './watch'; import { ISourceControlHistoryItemDetailsProviderRegistry } from './historyItemDetailsProvider'; +import { GitArtifactProvider } from './artifactProvider'; +import { RepositoryCache } from './repositoryCache'; const timeout = (millis: number) => new Promise(c => setTimeout(c, millis)); @@ -184,7 +186,7 @@ export class Resource implements SourceControlResourceState { get renameResourceUri(): Uri | undefined { return this._renameResourceUri; } get contextValue(): string | undefined { return this._repositoryKind; } - private static Icons: any = { + private static Icons = { light: { Modified: getIconUri('status-modified', 'light'), Added: getIconUri('status-added', 'light'), @@ -209,7 +211,7 @@ export class Resource implements SourceControlResourceState { } }; - private getIconPath(theme: string): Uri { + private getIconPath(theme: 'light' | 'dark'): Uri { switch (this.type) { case Status.INDEX_MODIFIED: return Resource.Icons[theme].Modified; case Status.MODIFIED: return Resource.Icons[theme].Modified; @@ -690,11 +692,7 @@ interface BranchProtectionMatcher { } export interface IRepositoryResolver { - getRepository(sourceControl: SourceControl): Repository | undefined; - getRepository(resourceGroup: SourceControlResourceGroup): Repository | undefined; - getRepository(path: string): Repository | undefined; - getRepository(resource: Uri): Repository | undefined; - getRepository(hint: any): Repository | undefined; + getRepository(hint: SourceControl | SourceControlResourceGroup | Uri | string): Repository | undefined; } export class Repository implements Disposable { @@ -722,7 +720,9 @@ export class Repository implements Disposable { @memoize get onDidChangeOperations(): Event { - return anyEvent(this.onRunOperation as Event, this.onDidRunOperation as Event); + return anyEvent( + this.onRunOperation as Event, + this.onDidRunOperation as Event) as Event; } private _sourceControl: SourceControl; @@ -872,6 +872,9 @@ export class Repository implements Disposable { return this.repository.kind; } + private _artifactProvider: GitArtifactProvider; + get artifactProvider(): GitArtifactProvider { return this._artifactProvider; } + private _historyProvider: GitHistoryProvider; get historyProvider(): GitHistoryProvider { return this._historyProvider; } @@ -895,7 +898,8 @@ export class Repository implements Disposable { historyItemDetailProviderRegistry: ISourceControlHistoryItemDetailsProviderRegistry, globalState: Memento, private readonly logger: LogOutputChannel, - private telemetryReporter: TelemetryReporter + private telemetryReporter: TelemetryReporter, + private readonly repositoryCache: RepositoryCache ) { this._operations = new OperationManager(this.logger); @@ -934,7 +938,9 @@ export class Repository implements Disposable { : repository.kind === 'worktree' && repository.dotGit.commonPath ? path.dirname(repository.dotGit.commonPath) : undefined; - const parent = this.repositoryResolver.getRepository(parentRoot)?.sourceControl; + const parent = parentRoot + ? this.repositoryResolver.getRepository(parentRoot)?.sourceControl + : undefined; // Icon const icon = repository.kind === 'submodule' @@ -954,6 +960,10 @@ export class Repository implements Disposable { this._sourceControl.historyProvider = this._historyProvider; this.disposables.push(this._historyProvider); + this._artifactProvider = new GitArtifactProvider(this, logger); + this._sourceControl.artifactProvider = this._artifactProvider; + this.disposables.push(this._artifactProvider); + this._sourceControl.acceptInputCommand = { command: 'git.commit', title: l10n.t('Commit'), arguments: [this._sourceControl] }; this._sourceControl.inputBox.validateInput = this.validateInput.bind(this); @@ -1197,6 +1207,10 @@ export class Repository implements Disposable { return this.run(Operation.Diff, () => this.repository.diffWithHEAD(path)); } + diffWithHEADShortStats(path?: string): Promise { + return this.run(Operation.Diff, () => this.repository.diffWithHEADShortStats(path)); + } + diffWith(ref: string): Promise; diffWith(ref: string, path: string): Promise; diffWith(ref: string, path?: string | undefined): Promise; @@ -1211,6 +1225,10 @@ export class Repository implements Disposable { return this.run(Operation.Diff, () => this.repository.diffIndexWithHEAD(path)); } + diffIndexWithHEADShortStats(path?: string): Promise { + return this.run(Operation.Diff, () => this.repository.diffIndexWithHEADShortStats(path)); + } + diffIndexWith(ref: string): Promise; diffIndexWith(ref: string, path: string): Promise; diffIndexWith(ref: string, path?: string | undefined): Promise; @@ -1229,8 +1247,17 @@ export class Repository implements Disposable { return this.run(Operation.Diff, () => this.repository.diffBetween(ref1, ref2, path)); } - diffBetweenShortStat(ref1: string, ref2: string): Promise<{ files: number; insertions: number; deletions: number }> { - return this.run(Operation.Diff, () => this.repository.diffBetweenShortStat(ref1, ref2)); + diffBetween2(ref1: string, ref2: string): Promise { + if (ref1 === this._EMPTY_TREE) { + // Use git diff-tree to get the + // changes in the first commit + return this.diffTrees(ref1, ref2); + } + + const scopedConfig = workspace.getConfiguration('git', Uri.file(this.root)); + const similarityThreshold = scopedConfig.get('similarityThreshold', 50); + + return this.run(Operation.Diff, () => this.repository.diffBetween2(ref1, ref2, { similarityThreshold })); } diffTrees(treeish1: string, treeish2?: string): Promise { @@ -1847,11 +1874,23 @@ export class Repository implements Disposable { } async addRemote(name: string, url: string): Promise { - await this.run(Operation.Remote, () => this.repository.addRemote(name, url)); + await this.run(Operation.Remote, async () => { + const result = await this.repository.addRemote(name, url); + this.repositoryCache.update(this.remotes, [], this.root); + return result; + }); } async removeRemote(name: string): Promise { - await this.run(Operation.Remote, () => this.repository.removeRemote(name)); + await this.run(Operation.Remote, async () => { + const result = this.repository.removeRemote(name); + const remote = this.remotes.find(remote => remote.name === name); + if (remote) { + this.repositoryCache.update([], [remote], this.root); + } + return result; + }); + } async renameRemote(name: string, newName: string): Promise { @@ -2287,14 +2326,15 @@ export class Repository implements Disposable { private async run( operation: Operation, - runOperation: () => Promise = () => Promise.resolve(null), - getOptimisticResourceGroups: () => GitResourceGroups | undefined = () => undefined): Promise { + runOperation: () => Promise = () => Promise.resolve(null) as Promise, + getOptimisticResourceGroups: () => GitResourceGroups | undefined = () => undefined + ): Promise { if (this.state !== RepositoryState.Idle) { throw new Error('Repository not initialized'); } - let error: any = null; + let error: unknown = null; this._operations.start(operation); this._onRunOperation.fire(operation.kind); @@ -2310,7 +2350,7 @@ export class Repository implements Disposable { } catch (err) { error = err; - if (err.gitErrorCode === GitErrorCodes.NotAGitRepository) { + if (err instanceof GitError && err.gitErrorCode === GitErrorCodes.NotAGitRepository) { this.state = RepositoryState.Disposed; } @@ -2325,7 +2365,7 @@ export class Repository implements Disposable { } } - private async retryRun(operation: Operation, runOperation: () => Promise = () => Promise.resolve(null)): Promise { + private async retryRun(operation: Operation, runOperation: () => Promise): Promise { let attempt = 0; while (true) { diff --git a/extensions/git/src/repositoryCache.ts b/extensions/git/src/repositoryCache.ts new file mode 100644 index 00000000000..5e3f8cbe594 --- /dev/null +++ b/extensions/git/src/repositoryCache.ts @@ -0,0 +1,194 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { LogOutputChannel, Memento, workspace } from 'vscode'; +import { LRUCache } from './cache'; +import { Remote } from './api/git'; +import { isDescendant } from './util'; + +export interface RepositoryCacheInfo { + workspacePath: string; // path of the workspace folder or workspace file +} + +function isRepositoryCacheInfo(obj: unknown): obj is RepositoryCacheInfo { + if (!obj || typeof obj !== 'object') { + return false; + } + const rec = obj as Record; + return typeof rec.workspacePath === 'string'; +} + +export class RepositoryCache { + + private static readonly STORAGE_KEY = 'git.repositoryCache'; + private static readonly MAX_REPO_ENTRIES = 30; // Max repositories tracked + private static readonly MAX_FOLDER_ENTRIES = 10; // Max folders per repository + + private normalizeRepoUrl(url: string): string { + try { + const trimmed = url.trim(); + return trimmed.replace(/(?:\.git)?\/*$/i, ''); + } catch { + return url; + } + } + + // Outer LRU: repoUrl -> inner LRU (folderPathOrWorkspaceFile -> RepositoryCacheInfo). + private readonly lru = new LRUCache>(RepositoryCache.MAX_REPO_ENTRIES); + + constructor(public readonly _globalState: Memento, private readonly _logger: LogOutputChannel) { + this.load(); + } + + // Exposed for testing + protected get _workspaceFile() { + return workspace.workspaceFile; + } + + // Exposed for testing + protected get _workspaceFolders() { + return workspace.workspaceFolders; + } + + /** + * Associate a repository remote URL with a local workspace folder or workspace file. + * Re-associating bumps recency and persists the updated LRU state. + * @param repoUrl Remote repository URL (e.g. https://github.com/owner/repo.git) + * @param rootPath Root path of the local repo clone. + */ + set(repoUrl: string, rootPath: string): void { + const key = this.normalizeRepoUrl(repoUrl); + let foldersLru = this.lru.get(key); + if (!foldersLru) { + foldersLru = new LRUCache(RepositoryCache.MAX_FOLDER_ENTRIES); + } + const folderPathOrWorkspaceFile: string | undefined = this._findWorkspaceForRepo(rootPath); + if (!folderPathOrWorkspaceFile) { + return; + } + + foldersLru.set(folderPathOrWorkspaceFile, { + workspacePath: folderPathOrWorkspaceFile + }); // touch entry + this.lru.set(key, foldersLru); + this.save(); + } + + private _findWorkspaceForRepo(rootPath: string): string | undefined { + // If the current workspace is a workspace file, use that. Otherwise, find the workspace folder that contains the rootUri + let folderPathOrWorkspaceFile: string | undefined; + try { + if (this._workspaceFile) { + folderPathOrWorkspaceFile = this._workspaceFile.fsPath; + } else if (this._workspaceFolders && this._workspaceFolders.length) { + const sorted = [...this._workspaceFolders].sort((a, b) => b.uri.fsPath.length - a.uri.fsPath.length); + for (const folder of sorted) { + const folderPath = folder.uri.fsPath; + if (isDescendant(folderPath, rootPath) || isDescendant(rootPath, folderPath)) { + folderPathOrWorkspaceFile = folderPath; + break; + } + } + } + return folderPathOrWorkspaceFile; + } catch { + return; + } + + } + + update(addedRemotes: Remote[], removedRemotes: Remote[], rootPath: string): void { + for (const remote of removedRemotes) { + const url = remote.fetchUrl; + if (!url) { + continue; + } + const relatedWorkspace = this._findWorkspaceForRepo(rootPath); + if (relatedWorkspace) { + this.delete(url, relatedWorkspace); + } + } + + for (const remote of addedRemotes) { + const url = remote.fetchUrl; + if (!url) { + continue; + } + this.set(url, rootPath); + } + } + + /** + * We should possibly support converting between ssh remotes and http remotes. + */ + get(repoUrl: string): RepositoryCacheInfo[] | undefined { + const key = this.normalizeRepoUrl(repoUrl); + const inner = this.lru.get(key); + return inner ? Array.from(inner.values()) : undefined; + } + + delete(repoUrl: string, folderPathOrWorkspaceFile: string) { + const key = this.normalizeRepoUrl(repoUrl); + const inner = this.lru.get(key); + if (!inner) { + return; + } + if (!inner.remove(folderPathOrWorkspaceFile)) { + return; + } + if (inner.size === 0) { + this.lru.remove(key); + } else { + // Re-set to bump outer LRU recency after modification + this.lru.set(key, inner); + } + this.save(); + } + + private load(): void { + try { + const raw = this._globalState.get<[string, [string, RepositoryCacheInfo][]][]>(RepositoryCache.STORAGE_KEY); + if (!Array.isArray(raw)) { + return; + } + for (const [repo, storedFolders] of raw) { + if (typeof repo !== 'string' || !Array.isArray(storedFolders)) { + continue; + } + const inner = new LRUCache(RepositoryCache.MAX_FOLDER_ENTRIES); + for (const entry of storedFolders) { + if (!Array.isArray(entry) || entry.length !== 2) { + continue; + } + const [folderPath, info] = entry; + if (typeof folderPath !== 'string' || !isRepositoryCacheInfo(info)) { + continue; + } + + inner.set(folderPath, info); + } + if (inner.size) { + this.lru.set(repo, inner); + } + } + + } catch { + this._logger.warn('[CachedRepositories][load] Failed to load cached repositories from global state.'); + } + } + + private save(): void { + // Serialize as [repoUrl, [folderPathOrWorkspaceFile, RepositoryCacheInfo][]] preserving outer LRU order. + const serialized: [string, [string, RepositoryCacheInfo][]][] = []; + for (const [repo, inner] of this.lru) { + const folders: [string, RepositoryCacheInfo][] = []; + for (const [folder, info] of inner) { + folders.push([folder, info]); + } + serialized.push([repo, folders]); + } + void this._globalState.update(RepositoryCache.STORAGE_KEY, serialized); + } +} diff --git a/extensions/git/src/statusbar.ts b/extensions/git/src/statusbar.ts index e58096442f2..6a06209eb41 100644 --- a/extensions/git/src/statusbar.ts +++ b/extensions/git/src/statusbar.ts @@ -71,7 +71,18 @@ class CheckoutStatusBar { // Branch if (this.repository.HEAD.type === RefType.Head && this.repository.HEAD.name) { - return this.repository.isBranchProtected() ? '$(lock)' : '$(git-branch)'; + switch (true) { + case this.repository.isBranchProtected(): + return '$(lock)'; + case this.repository.mergeInProgress || !!this.repository.rebaseCommit: + return '$(git-branch-conflicts)'; + case this.repository.indexGroup.resourceStates.length > 0: + return '$(git-branch-staged-changes)'; + case this.repository.workingTreeGroup.resourceStates.length + this.repository.untrackedGroup.resourceStates.length > 0: + return '$(git-branch-changes)'; + default: + return '$(git-branch)'; + } } // Tag diff --git a/extensions/git/src/test/repositoryCache.test.ts b/extensions/git/src/test/repositoryCache.test.ts new file mode 100644 index 00000000000..ce3ec98272d --- /dev/null +++ b/extensions/git/src/test/repositoryCache.test.ts @@ -0,0 +1,197 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import 'mocha'; +import * as assert from 'assert'; +import { RepositoryCache } from '../repositoryCache'; +import { Event, EventEmitter, LogLevel, LogOutputChannel, Memento, Uri, WorkspaceFolder } from 'vscode'; + +class InMemoryMemento implements Memento { + private store = new Map(); + + constructor(initial?: Record) { + if (initial) { + for (const k of Object.keys(initial)) { + this.store.set(k, initial[k]); + } + } + } + + get(key: string): T | undefined; + get(key: string, defaultValue: T): T; + get(key: string, defaultValue?: T): T | undefined { + if (this.store.has(key)) { + return this.store.get(key); + } + return defaultValue as (T | undefined); + } + + update(key: string, value: any): Thenable { + this.store.set(key, value); + return Promise.resolve(); + } + + keys(): readonly string[] { + return Array.from(this.store.keys()); + } +} + +class MockLogOutputChannel implements LogOutputChannel { + logLevel: LogLevel = LogLevel.Info; + onDidChangeLogLevel: Event = new EventEmitter().event; + trace(_message: string, ..._args: any[]): void { } + debug(_message: string, ..._args: any[]): void { } + info(_message: string, ..._args: any[]): void { } + warn(_message: string, ..._args: any[]): void { } + error(_error: string | Error, ..._args: any[]): void { } + name: string = 'MockLogOutputChannel'; + append(_value: string): void { } + appendLine(_value: string): void { } + replace(_value: string): void { } + clear(): void { } + show(_column?: unknown, _preserveFocus?: unknown): void { } + hide(): void { } + dispose(): void { } +} + +class TestRepositoryCache extends RepositoryCache { + constructor(memento: Memento, logger: LogOutputChannel, private readonly _workspaceFileProp: Uri | undefined, private readonly _workspaceFoldersProp: readonly WorkspaceFolder[] | undefined) { + super(memento, logger); + } + + protected override get _workspaceFile() { + return this._workspaceFileProp; + } + + protected override get _workspaceFolders() { + return this._workspaceFoldersProp; + } +} + +suite('RepositoryCache', () => { + + test('set & get basic', () => { + const memento = new InMemoryMemento(); + const folder = Uri.file('/workspace/repo'); + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, [{ uri: folder, name: 'workspace', index: 0 }]); + + cache.set('https://example.com/repo.git', folder.fsPath); + const folders = cache.get('https://example.com/repo.git')!.map(folder => folder.workspacePath); + assert.ok(folders, 'folders should be defined'); + assert.deepStrictEqual(folders, [folder.fsPath]); + }); + + test('inner LRU capped at 10 entries', () => { + const memento = new InMemoryMemento(); + const workspaceFolders: WorkspaceFolder[] = []; + for (let i = 1; i <= 12; i++) { + workspaceFolders.push({ uri: Uri.file(`/ws/folder-${i.toString().padStart(2, '0')}`), name: `folder-${i.toString().padStart(2, '0')}`, index: i - 1 }); + } + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, workspaceFolders); + const repo = 'https://example.com/repo.git'; + for (let i = 1; i <= 12; i++) { + cache.set(repo, Uri.file(`/ws/folder-${i.toString().padStart(2, '0')}`).fsPath); + } + const folders = cache.get(repo)!.map(folder => folder.workspacePath); + assert.strictEqual(folders.length, 10, 'should only retain 10 most recent folders'); + assert.ok(!folders.includes(Uri.file('/ws/folder-01').fsPath), 'oldest folder-01 should be evicted'); + assert.ok(!folders.includes(Uri.file('/ws/folder-02').fsPath), 'second oldest folder-02 should be evicted'); + assert.ok(folders.includes(Uri.file('/ws/folder-12').fsPath), 'latest folder should be present'); + }); + + test('outer LRU capped at 30 repos', () => { + const memento = new InMemoryMemento(); + const workspaceFolders: WorkspaceFolder[] = []; + for (let i = 1; i <= 35; i++) { + workspaceFolders.push({ uri: Uri.file(`/ws/r${i}`), name: `r${i}`, index: i - 1 }); + } + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, workspaceFolders); + for (let i = 1; i <= 35; i++) { + const repo = `https://example.com/r${i}.git`; + cache.set(repo, Uri.file(`/ws/r${i}`).fsPath); + } + assert.strictEqual(cache.get('https://example.com/r1.git'), undefined, 'oldest repo should be trimmed'); + assert.ok(cache.get('https://example.com/r35.git'), 'newest repo should remain'); + }); + + test('delete removes folder and prunes empty repo', () => { + const memento = new InMemoryMemento(); + const workspaceFolders: WorkspaceFolder[] = []; + workspaceFolders.push({ uri: Uri.file(`/ws/a`), name: `a`, index: 0 }); + workspaceFolders.push({ uri: Uri.file(`/ws/b`), name: `b`, index: 1 }); + + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, workspaceFolders); + const repo = 'https://example.com/repo.git'; + const a = Uri.file('/ws/a').fsPath; + const b = Uri.file('/ws/b').fsPath; + cache.set(repo, a); + cache.set(repo, b); + assert.deepStrictEqual(new Set(cache.get(repo)?.map(folder => folder.workspacePath)), new Set([a, b])); + cache.delete(repo, a); + assert.deepStrictEqual(cache.get(repo)!.map(folder => folder.workspacePath), [b]); + cache.delete(repo, b); + assert.strictEqual(cache.get(repo), undefined, 'repo should be pruned when last folder removed'); + }); + + test('normalizes URLs with trailing .git', () => { + const memento = new InMemoryMemento(); + const folder = Uri.file('/workspace/repo'); + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, [{ uri: folder, name: 'workspace', index: 0 }]); + + // Set with .git extension + cache.set('https://example.com/repo.git', folder.fsPath); + + // Should be able to get with or without .git + const withGit = cache.get('https://example.com/repo.git'); + const withoutGit = cache.get('https://example.com/repo'); + + assert.ok(withGit, 'should find repo when querying with .git'); + assert.ok(withoutGit, 'should find repo when querying without .git'); + assert.deepStrictEqual(withGit, withoutGit, 'should return same result regardless of .git suffix'); + }); + + test('normalizes URLs with trailing slashes and .git', () => { + const memento = new InMemoryMemento(); + const folder = Uri.file('/workspace/repo'); + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, [{ uri: folder, name: 'workspace', index: 0 }]); + + // Set with .git and trailing slashes + cache.set('https://example.com/repo.git///', folder.fsPath); + + // Should be able to get with various combinations + const variations = [ + 'https://example.com/repo.git///', + 'https://example.com/repo.git/', + 'https://example.com/repo.git', + 'https://example.com/repo/', + 'https://example.com/repo' + ]; + + const results = variations.map(url => cache.get(url)); + + // All should return the same non-undefined result + assert.ok(results[0], 'should find repo with original URL'); + for (let i = 1; i < results.length; i++) { + assert.deepStrictEqual(results[i], results[0], `variation ${variations[i]} should return same result`); + } + }); + + test('handles URLs without .git correctly', () => { + const memento = new InMemoryMemento(); + const folder = Uri.file('/workspace/repo'); + const cache = new TestRepositoryCache(memento, new MockLogOutputChannel(), undefined, [{ uri: folder, name: 'workspace', index: 0 }]); + + // Set without .git extension + cache.set('https://example.com/repo', folder.fsPath); + + // Should be able to get with or without .git + const withoutGit = cache.get('https://example.com/repo'); + const withGit = cache.get('https://example.com/repo.git'); + + assert.ok(withoutGit, 'should find repo when querying without .git'); + assert.ok(withGit, 'should find repo when querying with .git'); + assert.deepStrictEqual(withoutGit, withGit, 'should return same result regardless of .git suffix'); + }); +}); diff --git a/extensions/git/src/timelineProvider.ts b/extensions/git/src/timelineProvider.ts index 47000d78e91..52452c4c94e 100644 --- a/extensions/git/src/timelineProvider.ts +++ b/extensions/git/src/timelineProvider.ts @@ -202,7 +202,7 @@ export class GitTimelineProvider implements TimelineProvider { processHistoryItemRemoteHoverCommands(commitRemoteSourceCommands, c.hash) ]; - item.tooltip = getHistoryItemHover(avatars?.get(c.hash), c.authorName, c.authorEmail, date, messageWithLinks, c.shortStat, commands); + item.tooltip = getHistoryItemHover(avatars?.get(c.hash), c.authorName, c.authorEmail, date, messageWithLinks, c.shortStat, undefined, commands); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { @@ -227,7 +227,7 @@ export class GitTimelineProvider implements TimelineProvider { // TODO@eamodio: Replace with a better icon -- reflecting its status maybe? item.iconPath = new ThemeIcon('git-commit'); item.description = ''; - item.tooltip = getHistoryItemHover(undefined, you, undefined, date, Resource.getStatusText(index.type), undefined, undefined); + item.tooltip = getHistoryItemHover(undefined, you, undefined, date, Resource.getStatusText(index.type), undefined, undefined, undefined); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { @@ -249,7 +249,7 @@ export class GitTimelineProvider implements TimelineProvider { const item = new GitTimelineItem('', index ? '~' : 'HEAD', l10n.t('Uncommitted Changes'), date.getTime(), 'working', 'git:file:working'); item.iconPath = new ThemeIcon('circle-outline'); item.description = ''; - item.tooltip = getHistoryItemHover(undefined, you, undefined, date, Resource.getStatusText(working.type), undefined, undefined); + item.tooltip = getHistoryItemHover(undefined, you, undefined, date, Resource.getStatusText(working.type), undefined, undefined, undefined); const cmd = this.commands.resolveTimelineOpenDiffCommand(item, uri); if (cmd) { diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index 7600a2e46ac..fcc820c8cd4 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Event, Disposable, EventEmitter, SourceControlHistoryItemRef, l10n, workspace, Uri, DiagnosticSeverity, env } from 'vscode'; +import { Event, Disposable, EventEmitter, SourceControlHistoryItemRef, l10n, workspace, Uri, DiagnosticSeverity, env, SourceControlHistoryItem } from 'vscode'; import { dirname, normalize, sep, relative } from 'path'; import { Readable } from 'stream'; import { promises as fs, createReadStream } from 'fs'; @@ -797,6 +797,12 @@ export function getCommitShortHash(scope: Uri, hash: string): string { return hash.substring(0, shortHashLength); } +export function getHistoryItemDisplayName(historyItem: SourceControlHistoryItem): string { + return historyItem.references?.length + ? historyItem.references[0].name + : historyItem.displayId ?? historyItem.id; +} + export type DiagnosticSeverityConfig = 'error' | 'warning' | 'information' | 'hint' | 'none'; export function toDiagnosticSeverity(value: DiagnosticSeverityConfig): DiagnosticSeverity { diff --git a/extensions/git/tsconfig.json b/extensions/git/tsconfig.json index 3fdc14300e5..eac688f81de 100644 --- a/extensions/git/tsconfig.json +++ b/extensions/git/tsconfig.json @@ -16,6 +16,7 @@ "../../src/vscode-dts/vscode.proposed.quickInputButtonLocation.d.ts", "../../src/vscode-dts/vscode.proposed.quickPickSortByLabel.d.ts", "../../src/vscode-dts/vscode.proposed.scmActionButton.d.ts", + "../../src/vscode-dts/vscode.proposed.scmArtifactProvider.d.ts", "../../src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts", "../../src/vscode-dts/vscode.proposed.scmProviderOptions.d.ts", "../../src/vscode-dts/vscode.proposed.scmSelectedProvider.d.ts", diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index 6d22dfe1a6a..91f2d1b57db 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -62,6 +62,12 @@ "default": true, "scope": "application", "markdownDescription": "%config.github-authentication.useElectronFetch.description%" + }, + "github-authentication.preferDeviceCodeFlow": { + "type": "boolean", + "default": false, + "scope": "application", + "markdownDescription": "%config.github-authentication.preferDeviceCodeFlow.description%" } } } diff --git a/extensions/github-authentication/package.nls.json b/extensions/github-authentication/package.nls.json index 4f45cd5d4f6..dfbd033224d 100644 --- a/extensions/github-authentication/package.nls.json +++ b/extensions/github-authentication/package.nls.json @@ -3,5 +3,6 @@ "description": "GitHub Authentication Provider", "config.github-enterprise.title": "GHE.com & GitHub Enterprise Server Authentication", "config.github-enterprise.uri.description": "The URI for your GHE.com or GitHub Enterprise Server instance.\n\nExamples:\n* GHE.com: `https://octocat.ghe.com`\n* GitHub Enterprise Server: `https://github.octocat.com`\n\n> **Note:** This should _not_ be set to a GitHub.com URI. If your account exists on GitHub.com or is a GitHub Enterprise Managed User, you do not need any additional configuration and can simply log in to GitHub.", - "config.github-authentication.useElectronFetch.description": "When true, uses Electron's built-in fetch function for HTTP requests. When false, uses the Node.js global fetch function. This setting only applies when running in the Electron environment. **Note:** A restart is required for this setting to take effect." + "config.github-authentication.useElectronFetch.description": "When true, uses Electron's built-in fetch function for HTTP requests. When false, uses the Node.js global fetch function. This setting only applies when running in the Electron environment. **Note:** A restart is required for this setting to take effect.", + "config.github-authentication.preferDeviceCodeFlow.description": "When true, prioritize the device code flow for authentication instead of other available flows. This is useful for environments like WSL where the local server or URL handler flows may not work as expected." } diff --git a/extensions/github-authentication/src/flows.ts b/extensions/github-authentication/src/flows.ts index 5a917fbabca..76da600118a 100644 --- a/extensions/github-authentication/src/flows.ts +++ b/extensions/github-authentication/src/flows.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as path from 'path'; -import { ProgressLocation, Uri, commands, env, l10n, window } from 'vscode'; +import { ProgressLocation, Uri, commands, env, l10n, window, workspace } from 'vscode'; import { Log } from './common/logger'; import { Config } from './config'; import { UriEventHandler } from './github'; @@ -612,7 +612,7 @@ const allFlows: IFlow[] = [ ]; export function getFlows(query: IFlowQuery) { - return allFlows.filter(flow => { + const validFlows = allFlows.filter(flow => { let useFlow: boolean = true; switch (query.target) { case GitHubTarget.DotCom: @@ -648,6 +648,16 @@ export function getFlows(query: IFlowQuery) { } return useFlow; }); + + const preferDeviceCodeFlow = workspace.getConfiguration('github-authentication').get('preferDeviceCodeFlow', false); + if (preferDeviceCodeFlow) { + return [ + ...validFlows.filter(flow => flow instanceof DeviceCodeFlow), + ...validFlows.filter(flow => !(flow instanceof DeviceCodeFlow)) + ]; + } + + return validFlows; } /** diff --git a/extensions/github-authentication/src/test/flows.test.ts b/extensions/github-authentication/src/test/flows.test.ts index 77c023e4819..fdcdd0f3f45 100644 --- a/extensions/github-authentication/src/test/flows.test.ts +++ b/extensions/github-authentication/src/test/flows.test.ts @@ -6,6 +6,7 @@ import * as assert from 'assert'; import { ExtensionHost, GitHubTarget, IFlowQuery, getFlows } from '../flows'; import { Config } from '../config'; +import * as vscode from 'vscode'; const enum Flows { UrlHandlerFlow = 'url handler', @@ -193,4 +194,68 @@ suite('getFlows', () => { } }); } + + suite('preferDeviceCodeFlow configuration', () => { + let originalConfig: boolean | undefined; + + suiteSetup(async () => { + const config = vscode.workspace.getConfiguration('github-authentication'); + originalConfig = config.get('preferDeviceCodeFlow'); + }); + + suiteTeardown(async () => { + const config = vscode.workspace.getConfiguration('github-authentication'); + await config.update('preferDeviceCodeFlow', originalConfig, vscode.ConfigurationTarget.Global); + }); + + test('returns device code flow first when preferDeviceCodeFlow is true - VS Code Desktop', async () => { + const config = vscode.workspace.getConfiguration('github-authentication'); + await config.update('preferDeviceCodeFlow', true, vscode.ConfigurationTarget.Global); + + const flows = getFlows({ + extensionHost: ExtensionHost.Local, + isSupportedClient: true, + target: GitHubTarget.DotCom + }); + + // Should return device code flow first, then other flows + assert.strictEqual(flows.length, 3, `Expected 3 flows, got ${flows.length}: ${flows.map(f => f.label).join(',')}`); + assert.strictEqual(flows[0].label, Flows.DeviceCodeFlow); + // Other flows should still be available + assert.strictEqual(flows[1].label, Flows.LocalServerFlow); + assert.strictEqual(flows[2].label, Flows.UrlHandlerFlow); + }); + + test('returns device code flow first when preferDeviceCodeFlow is true - Remote', async () => { + const config = vscode.workspace.getConfiguration('github-authentication'); + await config.update('preferDeviceCodeFlow', true, vscode.ConfigurationTarget.Global); + + const flows = getFlows({ + extensionHost: ExtensionHost.Remote, + isSupportedClient: true, + target: GitHubTarget.DotCom + }); + + // Should return device code flow first, then other flows + assert.strictEqual(flows.length, 2, `Expected 2 flows, got ${flows.length}: ${flows.map(f => f.label).join(',')}`); + assert.strictEqual(flows[0].label, Flows.DeviceCodeFlow); + assert.strictEqual(flows[1].label, Flows.UrlHandlerFlow); + }); + + test('returns normal flows when preferDeviceCodeFlow is true but device code flow is not supported - WebWorker', async () => { + const config = vscode.workspace.getConfiguration('github-authentication'); + await config.update('preferDeviceCodeFlow', true, vscode.ConfigurationTarget.Global); + + const flows = getFlows({ + extensionHost: ExtensionHost.WebWorker, + isSupportedClient: true, + target: GitHubTarget.DotCom + }); + + // WebWorker doesn't support DeviceCodeFlow, so should return normal flows + // Based on the original logic, WebWorker + DotCom should return UrlHandlerFlow + assert.strictEqual(flows.length, 1, `Expected 1 flow for WebWorker configuration, got ${flows.length}: ${flows.map(f => f.label).join(',')}`); + assert.strictEqual(flows[0].label, Flows.UrlHandlerFlow); + }); + }); }); diff --git a/extensions/github/package.json b/extensions/github/package.json index 726a882ebc3..cd70cfea26b 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -157,13 +157,6 @@ "group": "0_view@2" } ], - "scm/historyItem/hover": [ - { - "command": "github.graph.openOnGitHub", - "when": "github.hasGitHubRepo", - "group": "1_open@1" - } - ], "timeline/item/context": [ { "command": "github.timeline.openOnGitHub", diff --git a/extensions/github/src/historyItemDetailsProvider.ts b/extensions/github/src/historyItemDetailsProvider.ts index 1a5d58a1c52..9a267b9e844 100644 --- a/extensions/github/src/historyItemDetailsProvider.ts +++ b/extensions/github/src/historyItemDetailsProvider.ts @@ -114,7 +114,8 @@ export class GitHubSourceControlHistoryItemDetailsProvider implements SourceCont return undefined; } - const descriptor = getRepositoryDefaultRemote(repository); + // upstream -> origin -> first + const descriptor = getRepositoryDefaultRemote(repository, ['upstream', 'origin']); if (!descriptor) { this._logger.trace(`[GitHubSourceControlHistoryItemDetailsProvider][provideAvatar] Repository does not have a GitHub remote.`); return undefined; @@ -206,7 +207,8 @@ export class GitHubSourceControlHistoryItemDetailsProvider implements SourceCont } async provideHoverCommands(repository: Repository): Promise { - const url = getRepositoryDefaultRemoteUrl(repository); + // origin -> upstream -> first + const url = getRepositoryDefaultRemoteUrl(repository, ['origin', 'upstream']); if (!url) { return undefined; } @@ -220,7 +222,8 @@ export class GitHubSourceControlHistoryItemDetailsProvider implements SourceCont } async provideMessageLinks(repository: Repository, message: string): Promise { - const descriptor = getRepositoryDefaultRemote(repository); + // upstream -> origin -> first + const descriptor = getRepositoryDefaultRemote(repository, ['upstream', 'origin']); if (!descriptor) { return undefined; } diff --git a/extensions/github/src/links.ts b/extensions/github/src/links.ts index 8eb0f6b23f6..b4f8379e5f7 100644 --- a/extensions/github/src/links.ts +++ b/extensions/github/src/links.ts @@ -47,12 +47,12 @@ interface EditorLineNumberContext { export type LinkContext = vscode.Uri | EditorLineNumberContext | undefined; function extractContext(context: LinkContext): { fileUri: vscode.Uri | undefined; lineNumber: number | undefined } { - if (context instanceof vscode.Uri) { - return { fileUri: context, lineNumber: undefined }; - } else if (context !== undefined && 'lineNumber' in context && 'uri' in context) { - return { fileUri: context.uri, lineNumber: context.lineNumber }; - } else { + if (context === undefined) { return { fileUri: undefined, lineNumber: undefined }; + } else if (context instanceof vscode.Uri) { + return { fileUri: context, lineNumber: undefined }; + } else { + return { fileUri: context.uri, lineNumber: context.lineNumber }; } } diff --git a/extensions/github/src/remoteSourceProvider.ts b/extensions/github/src/remoteSourceProvider.ts index 291a3f1a6ba..bed2bb1aa6b 100644 --- a/extensions/github/src/remoteSourceProvider.ts +++ b/extensions/github/src/remoteSourceProvider.ts @@ -10,7 +10,15 @@ import { Octokit } from '@octokit/rest'; import { getRepositoryFromQuery, getRepositoryFromUrl } from './util.js'; import { getBranchLink, getVscodeDevHost } from './links.js'; -function asRemoteSource(raw: any): RemoteSource { +type RemoteSourceResponse = { + readonly full_name: string; + readonly description: string | null; + readonly stargazers_count: number; + readonly clone_url: string; + readonly ssh_url: string; +}; + +function asRemoteSource(raw: RemoteSourceResponse): RemoteSource { const protocol = workspace.getConfiguration('github').get<'https' | 'ssh'>('gitProtocol'); return { name: `$(github) ${raw.full_name}`, diff --git a/extensions/github/src/test/github.test.ts b/extensions/github/src/test/github.test.ts index db0eba515cb..838fd37923e 100644 --- a/extensions/github/src/test/github.test.ts +++ b/extensions/github/src/test/github.test.ts @@ -39,11 +39,11 @@ suite('github smoke test', function () { }); test('selecting non-default quick-pick item should correspond to a template', async () => { - const template0 = Uri.file("some-imaginary-template-0"); - const template1 = Uri.file("some-imaginary-template-1"); + const template0 = Uri.file('some-imaginary-template-0'); + const template1 = Uri.file('some-imaginary-template-1'); const templates = [template0, template1]; - const pick = pickPullRequestTemplate(Uri.file("/"), templates); + const pick = pickPullRequestTemplate(Uri.file('/'), templates); await commands.executeCommand('workbench.action.quickOpenSelectNext'); await commands.executeCommand('workbench.action.quickOpenSelectNext'); @@ -53,9 +53,9 @@ suite('github smoke test', function () { }); test('selecting first quick-pick item should return undefined', async () => { - const templates = [Uri.file("some-imaginary-file")]; + const templates = [Uri.file('some-imaginary-file')]; - const pick = pickPullRequestTemplate(Uri.file("/"), templates); + const pick = pickPullRequestTemplate(Uri.file('/'), templates); await commands.executeCommand('workbench.action.quickOpenSelectNext'); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); diff --git a/extensions/github/src/util.ts b/extensions/github/src/util.ts index d2ccc426170..f7f54ec5f3f 100644 --- a/extensions/github/src/util.ts +++ b/extensions/github/src/util.ts @@ -74,7 +74,7 @@ export function repositoryHasGitHubRemote(repository: Repository) { return !!repository.state.remotes.find(remote => remote.fetchUrl ? getRepositoryFromUrl(remote.fetchUrl) : undefined); } -export function getRepositoryDefaultRemoteUrl(repository: Repository): string | undefined { +export function getRepositoryDefaultRemoteUrl(repository: Repository, order: string[]): string | undefined { const remotes = repository.state.remotes .filter(remote => remote.fetchUrl && getRepositoryFromUrl(remote.fetchUrl)); @@ -82,15 +82,20 @@ export function getRepositoryDefaultRemoteUrl(repository: Repository): string | return undefined; } - // origin -> upstream -> first - const remote = remotes.find(remote => remote.name === 'origin') - ?? remotes.find(remote => remote.name === 'upstream') - ?? remotes[0]; + for (const name of order) { + const remote = remotes + .find(remote => remote.name === name); - return remote.fetchUrl; + if (remote) { + return remote.fetchUrl; + } + } + + // Fallback to first remote + return remotes[0].fetchUrl; } -export function getRepositoryDefaultRemote(repository: Repository): { owner: string; repo: string } | undefined { - const fetchUrl = getRepositoryDefaultRemoteUrl(repository); +export function getRepositoryDefaultRemote(repository: Repository, order: string[]): { owner: string; repo: string } | undefined { + const fetchUrl = getRepositoryDefaultRemoteUrl(repository, order); return fetchUrl ? getRepositoryFromUrl(fetchUrl) : undefined; } diff --git a/extensions/github/tsconfig.json b/extensions/github/tsconfig.json index 63a4cd931d9..c82524f6d26 100644 --- a/extensions/github/tsconfig.json +++ b/extensions/github/tsconfig.json @@ -5,7 +5,6 @@ "moduleResolution": "NodeNext", "outDir": "./out", "skipLibCheck": true, - "allowSyntheticDefaultImports": false, "typeRoots": [ "./node_modules/@types" ] diff --git a/extensions/html-language-features/client/src/htmlClient.ts b/extensions/html-language-features/client/src/htmlClient.ts index 9cbbca14292..54fc91469da 100644 --- a/extensions/html-language-features/client/src/htmlClient.ts +++ b/extensions/html-language-features/client/src/htmlClient.ts @@ -179,9 +179,9 @@ async function startClientWithParticipants(languageParticipants: LanguagePartici } return r; } - // eslint-disable-next-line local/code-no-any-casts - const isThenable = (obj: ProviderResult): obj is Thenable => obj && (obj)['then']; - + function isThenable(obj: unknown): obj is Thenable { + return !!obj && typeof (obj as unknown as Thenable).then === 'function'; + } const r = next(document, position, context, token); if (isThenable(r)) { return r.then(updateProposals); diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 731a2e396f2..2aae9f4a113 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -182,6 +182,12 @@ "default": true, "description": "%html.suggest.html5.desc%" }, + "html.suggest.hideEndTagSuggestions": { + "type": "boolean", + "scope": "resource", + "default": false, + "description": "%html.suggest.hideEndTagSuggestions.desc%" + }, "html.validate.scripts": { "type": "boolean", "scope": "resource", diff --git a/extensions/html-language-features/package.nls.json b/extensions/html-language-features/package.nls.json index f36ecf34f02..d8390703757 100644 --- a/extensions/html-language-features/package.nls.json +++ b/extensions/html-language-features/package.nls.json @@ -23,6 +23,7 @@ "html.format.unformattedContentDelimiter.desc": "Keep text content together between this string.", "html.format.wrapAttributesIndentSize.desc": "Indent wrapped attributes to after N characters. Use `null` to use the default indent size. Ignored if `#html.format.wrapAttributes#` is set to `aligned`.", "html.suggest.html5.desc": "Controls whether the built-in HTML language support suggests HTML5 tags, properties and values.", + "html.suggest.hideEndTagSuggestions.desc": "Controls whether the built-in HTML language support suggests closing tags. When disabled, end tag completions like `` will not be shown.", "html.trace.server.desc": "Traces the communication between VS Code and the HTML language server.", "html.validate.scripts": "Controls whether the built-in HTML language support validates embedded scripts.", "html.validate.styles": "Controls whether the built-in HTML language support validates embedded styles.", diff --git a/extensions/html-language-features/server/src/htmlServer.ts b/extensions/html-language-features/server/src/htmlServer.ts index 66e3d3474fc..877c42f5c7c 100644 --- a/extensions/html-language-features/server/src/htmlServer.ts +++ b/extensions/html-language-features/server/src/htmlServer.ts @@ -134,16 +134,15 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) // After the server has started the client sends an initialize request. The server receives // in the passed params the rootPath of the workspace plus the client capabilities connection.onInitialize((params: InitializeParams): InitializeResult => { - // eslint-disable-next-line local/code-no-any-casts - const initializationOptions = params.initializationOptions as any || {}; + const initializationOptions = params.initializationOptions || {}; - // eslint-disable-next-line local/code-no-any-casts - workspaceFolders = (params).workspaceFolders; - if (!Array.isArray(workspaceFolders)) { + if (!Array.isArray(params.workspaceFolders)) { workspaceFolders = []; if (params.rootPath) { workspaceFolders.push({ name: '', uri: URI.file(params.rootPath).toString() }); } + } else { + workspaceFolders = params.workspaceFolders; } const handledSchemas = initializationOptions?.handledSchemas as string[] ?? ['file']; diff --git a/extensions/ini/package.json b/extensions/ini/package.json index 8523df264c1..f4837eb881f 100644 --- a/extensions/ini/package.json +++ b/extensions/ini/package.json @@ -40,13 +40,11 @@ ".repo" ], "filenames": [ - "gitconfig", - ".env" + "gitconfig" ], "filenamePatterns": [ "**/.config/git/config", - "**/.git/config", - ".*.env" + "**/.git/config" ], "aliases": [ "Properties", diff --git a/extensions/ipynb/src/common.ts b/extensions/ipynb/src/common.ts index dbd3ea1a618..f0330c88440 100644 --- a/extensions/ipynb/src/common.ts +++ b/extensions/ipynb/src/common.ts @@ -65,3 +65,36 @@ export interface CellMetadata { execution_count?: number | null; } + + +type KeysOfUnionType = T extends T ? keyof T : never; +type FilterType = T extends TTest ? T : never; +type MakeOptionalAndBool = { [K in keyof T]?: boolean }; + +/** + * Type guard that checks if an object has specific keys and narrows the type accordingly. + * + * @param x - The object to check + * @param key - An object with boolean values indicating which keys to check for + * @returns true if all specified keys exist in the object, false otherwise + * + * @example + * ```typescript + * type A = { a: string }; + * type B = { b: number }; + * const obj: A | B = getObject(); + * + * if (hasKey(obj, { a: true })) { + * // obj is now narrowed to type A + * console.log(obj.a); + * } + * ``` + */ +export function hasKey(x: T, key: TKeys & MakeOptionalAndBool): x is FilterType & keyof TKeys]: unknown }> { + for (const k in key) { + if (!(k in x)) { + return false; + } + } + return true; +} diff --git a/extensions/ipynb/src/deserializers.ts b/extensions/ipynb/src/deserializers.ts index 930092f6feb..1633a8ee330 100644 --- a/extensions/ipynb/src/deserializers.ts +++ b/extensions/ipynb/src/deserializers.ts @@ -20,8 +20,7 @@ const jupyterLanguageToMonacoLanguageMapping = new Map([ export function getPreferredLanguage(metadata?: nbformat.INotebookMetadata) { const jupyterLanguage = metadata?.language_info?.name || - // eslint-disable-next-line local/code-no-any-casts - (metadata?.kernelspec as any)?.language; + (metadata?.kernelspec as unknown as { language: string })?.language; // Default to python language only if the Python extension is installed. const defaultLanguage = @@ -151,7 +150,7 @@ function convertJupyterOutputToBuffer(mime: string, value: unknown): NotebookCel } } -function getNotebookCellMetadata(cell: nbformat.IBaseCell): { +function getNotebookCellMetadata(cell: nbformat.ICell): { [key: string]: any; } { // We put this only for VSC to display in diff view. @@ -169,7 +168,7 @@ function getNotebookCellMetadata(cell: nbformat.IBaseCell): { cellMetadata['metadata'] = JSON.parse(JSON.stringify(cell['metadata'])); } - if ('id' in cell && typeof cell.id === 'string') { + if (typeof cell.id === 'string') { cellMetadata.id = cell.id; } @@ -291,8 +290,7 @@ export function jupyterCellOutputToCellOutput(output: nbformat.IOutput): Noteboo if (fn) { result = fn(output); } else { - // eslint-disable-next-line local/code-no-any-casts - result = translateDisplayDataOutput(output as any); + result = translateDisplayDataOutput(output as unknown as nbformat.IDisplayData | nbformat.IDisplayUpdate | nbformat.IExecuteResult); } return result; } diff --git a/extensions/ipynb/src/helper.ts b/extensions/ipynb/src/helper.ts index 40dad3b887d..6a23633f52c 100644 --- a/extensions/ipynb/src/helper.ts +++ b/extensions/ipynb/src/helper.ts @@ -6,27 +6,26 @@ import { CancellationError } from 'vscode'; export function deepClone(obj: T): T { - if (!obj || typeof obj !== 'object') { + if (obj === null || typeof obj !== 'object') { return obj; } if (obj instanceof RegExp) { // See https://github.com/microsoft/TypeScript/issues/10990 - // eslint-disable-next-line local/code-no-any-casts - return obj as any; + return obj; } - const result: any = Array.isArray(obj) ? [] : {}; - // eslint-disable-next-line local/code-no-any-casts - Object.keys(obj).forEach((key: string) => { - // eslint-disable-next-line local/code-no-any-casts - if ((obj)[key] && typeof (obj)[key] === 'object') { - // eslint-disable-next-line local/code-no-any-casts - result[key] = deepClone((obj)[key]); + if (Array.isArray(obj)) { + return obj.map(item => deepClone(item)) as unknown as T; + } + const result = {}; + for (const key of Object.keys(obj as object) as Array) { + const value = obj[key]; + if (value && typeof value === 'object') { + (result as T)[key] = deepClone(value); } else { - // eslint-disable-next-line local/code-no-any-casts - result[key] = (obj)[key]; + (result as T)[key] = value; } - }); - return result; + } + return result as T; } // from https://github.com/microsoft/vscode/blob/43ae27a30e7b5e8711bf6b218ee39872ed2b8ef6/src/vs/base/common/objects.ts#L117 diff --git a/extensions/ipynb/src/notebookImagePaste.ts b/extensions/ipynb/src/notebookImagePaste.ts index 70a24e9bf2d..97c2ee73946 100644 --- a/extensions/ipynb/src/notebookImagePaste.ts +++ b/extensions/ipynb/src/notebookImagePaste.ts @@ -274,7 +274,7 @@ function buildAttachment( const filenameWithoutExt = basename(attachment.fileName, fileExt); let tempFilename = filenameWithoutExt + fileExt; - for (let appendValue = 2; tempFilename in cellMetadata.attachments; appendValue++) { + for (let appendValue = 2; cellMetadata.attachments[tempFilename]; appendValue++) { const objEntries = Object.entries(cellMetadata.attachments[tempFilename]); if (objEntries.length) { // check that mime:b64 are present const [mime, attachmentb64] = objEntries[0]; diff --git a/extensions/ipynb/src/serializers.ts b/extensions/ipynb/src/serializers.ts index a38ae39b6c7..6647c27176f 100644 --- a/extensions/ipynb/src/serializers.ts +++ b/extensions/ipynb/src/serializers.ts @@ -5,7 +5,7 @@ import type * as nbformat from '@jupyterlab/nbformat'; import type { NotebookCell, NotebookCellData, NotebookCellOutput, NotebookData, NotebookDocument } from 'vscode'; -import { CellOutputMetadata, type CellMetadata } from './common'; +import { CellOutputMetadata, hasKey, type CellMetadata } from './common'; import { textMimeTypes, NotebookCellKindMarkup, CellOutputMimeTypes, defaultNotebookFormat } from './constants'; const textDecoder = new TextDecoder(); @@ -37,20 +37,19 @@ export function sortObjectPropertiesRecursively(obj: any): any { } if (obj !== undefined && obj !== null && typeof obj === 'object' && Object.keys(obj).length > 0) { return ( - // eslint-disable-next-line local/code-no-any-casts Object.keys(obj) .sort() - .reduce>((sortedObj, prop) => { + .reduce>((sortedObj, prop) => { sortedObj[prop] = sortObjectPropertiesRecursively(obj[prop]); return sortedObj; - }, {}) as any + }, {}) ); } return obj; } export function getCellMetadata(options: { cell: NotebookCell | NotebookCellData } | { metadata?: { [key: string]: any } }): CellMetadata { - if ('cell' in options) { + if (hasKey(options, { cell: true })) { const cell = options.cell; const metadata = { execution_count: null, @@ -58,8 +57,7 @@ export function getCellMetadata(options: { cell: NotebookCell | NotebookCellData ...(cell.metadata ?? {}) } satisfies CellMetadata; if (cell.kind === NotebookCellKindMarkup) { - // eslint-disable-next-line local/code-no-any-casts - delete (metadata as any).execution_count; + delete (metadata as Record).execution_count; } return metadata; } else { @@ -400,10 +398,8 @@ export function pruneCell(cell: nbformat.ICell): nbformat.ICell { // Remove outputs and execution_count from non code cells if (result.cell_type !== 'code') { - // eslint-disable-next-line local/code-no-any-casts - delete (result).outputs; - // eslint-disable-next-line local/code-no-any-casts - delete (result).execution_count; + delete (result as Record).outputs; + delete (result as Record).execution_count; } else { // Clean outputs from code cells result.outputs = result.outputs ? (result.outputs as nbformat.IOutput[]).map(fixupOutput) : []; @@ -472,7 +468,7 @@ export function serializeNotebookToString(data: NotebookData): string { .map(cell => createJupyterCellFromNotebookCell(cell, preferredCellLanguage)) .map(pruneCell); - const indentAmount = data.metadata && 'indentAmount' in data.metadata && typeof data.metadata.indentAmount === 'string' ? + const indentAmount = data.metadata && typeof data.metadata.indentAmount === 'string' ? data.metadata.indentAmount : ' '; diff --git a/extensions/ipynb/src/test/notebookModelStoreSync.test.ts b/extensions/ipynb/src/test/notebookModelStoreSync.test.ts index c0d921cb886..42395b0a238 100644 --- a/extensions/ipynb/src/test/notebookModelStoreSync.test.ts +++ b/extensions/ipynb/src/test/notebookModelStoreSync.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import * as sinon from 'sinon'; -import { CancellationTokenSource, Disposable, EventEmitter, ExtensionContext, NotebookCellKind, NotebookDocumentChangeEvent, NotebookDocumentWillSaveEvent, NotebookEdit, NotebookRange, TextDocumentSaveReason, workspace, type CancellationToken, type NotebookCell, type NotebookDocument, type WorkspaceEdit, type WorkspaceEditMetadata } from 'vscode'; +import { CancellationTokenSource, Disposable, EventEmitter, ExtensionContext, NotebookCellKind, NotebookDocumentChangeEvent, NotebookDocumentWillSaveEvent, NotebookEdit, NotebookRange, TextDocument, TextDocumentSaveReason, workspace, type CancellationToken, type NotebookCell, type NotebookDocument, type WorkspaceEdit, type WorkspaceEditMetadata } from 'vscode'; import { activate } from '../notebookModelStoreSync'; suite(`Notebook Model Store Sync`, () => { @@ -36,9 +36,8 @@ suite(`Notebook Model Store Sync`, () => { disposables.push(onDidChangeNotebookDocument); onWillSaveNotebookDocument = new AsyncEmitter(); - sinon.stub(NotebookEdit, 'updateCellMetadata').callsFake((index, metadata) => { - // eslint-disable-next-line local/code-no-any-casts - const edit = (NotebookEdit.updateCellMetadata as any).wrappedMethod.call(NotebookEdit, index, metadata); + const stub = sinon.stub(NotebookEdit, 'updateCellMetadata').callsFake((index, metadata) => { + const edit = stub.wrappedMethod.call(NotebookEdit, index, metadata); cellMetadataUpdates.push(edit); return edit; } @@ -76,8 +75,7 @@ suite(`Notebook Model Store Sync`, () => { test('Adding cell for non Jupyter Notebook will not result in any updates', async () => { sinon.stub(notebook, 'notebookType').get(() => 'some-other-type'); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -106,8 +104,7 @@ suite(`Notebook Model Store Sync`, () => { test('Adding cell to nbformat 4.2 notebook will result in adding empty metadata', async () => { sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 2 })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -138,8 +135,7 @@ suite(`Notebook Model Store Sync`, () => { test('Added cell will have a cell id if nbformat is 4.5', async () => { sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 5 })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -173,8 +169,7 @@ suite(`Notebook Model Store Sync`, () => { test('Do not add cell id if one already exists', async () => { sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 5 })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -210,8 +205,7 @@ suite(`Notebook Model Store Sync`, () => { test('Do not perform any updates if cell id and metadata exists', async () => { sinon.stub(notebook, 'metadata').get(() => ({ nbformat: 4, nbformat_minor: 5 })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -248,10 +242,9 @@ suite(`Notebook Model Store Sync`, () => { } })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'javascript' - } as any, + } as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -271,10 +264,9 @@ suite(`Notebook Model Store Sync`, () => { cellChanges: [ { cell, - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'javascript' - } as any, + } as unknown as TextDocument, metadata: undefined, outputs: undefined, executionSummary: undefined @@ -300,10 +292,9 @@ suite(`Notebook Model Store Sync`, () => { } })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'javascript' - } as any, + } as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -344,10 +335,9 @@ suite(`Notebook Model Store Sync`, () => { } })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'javascript' - } as any, + } as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -368,10 +358,9 @@ suite(`Notebook Model Store Sync`, () => { cellChanges: [ { cell, - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'javascript' - } as any, + } as unknown as TextDocument, metadata: undefined, outputs: undefined, executionSummary: undefined @@ -397,10 +386,9 @@ suite(`Notebook Model Store Sync`, () => { } })); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'powershell' - } as any, + } as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, @@ -421,10 +409,9 @@ suite(`Notebook Model Store Sync`, () => { cellChanges: [ { cell, - // eslint-disable-next-line local/code-no-any-casts document: { languageId: 'powershell' - } as any, + } as unknown as TextDocument, metadata: undefined, outputs: undefined, executionSummary: undefined @@ -456,8 +443,7 @@ suite(`Notebook Model Store Sync`, () => { }); const cell: NotebookCell = { - // eslint-disable-next-line local/code-no-any-casts - document: {} as any, + document: {} as unknown as TextDocument, executionSummary: {}, index: 0, kind: NotebookCellKind.Code, diff --git a/extensions/java/cgmanifest.json b/extensions/java/cgmanifest.json index a62f6cdd1aa..ebb3d19beb5 100644 --- a/extensions/java/cgmanifest.json +++ b/extensions/java/cgmanifest.json @@ -49,4 +49,4 @@ } ], "version": 1 -} +} \ No newline at end of file diff --git a/extensions/json-language-features/client/src/jsonClient.ts b/extensions/json-language-features/client/src/jsonClient.ts index afa1c201dca..6d832e6c159 100644 --- a/extensions/json-language-features/client/src/jsonClient.ts +++ b/extensions/json-language-features/client/src/jsonClient.ts @@ -771,9 +771,8 @@ function getSchemaId(schema: JSONSchemaSettings, settingsLocation?: Uri): string return url; } -function isThenable(obj: ProviderResult): obj is Thenable { - // eslint-disable-next-line local/code-no-any-casts - return obj && (obj)['then']; +function isThenable(obj: unknown): obj is Thenable { + return !!obj && typeof (obj as unknown as Thenable).then === 'function'; } function updateMarkdownString(h: MarkdownString): MarkdownString { diff --git a/extensions/json-language-features/server/README.md b/extensions/json-language-features/server/README.md index 1c382916072..8047006f4e3 100644 --- a/extensions/json-language-features/server/README.md +++ b/extensions/json-language-features/server/README.md @@ -17,7 +17,7 @@ The JSON language server supports requests on documents of language id `json` an The server implements the following capabilities of the language server protocol: -- [Code completion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion) for JSON properties and values based on the document's [JSON schema](http://json-schema.org/) or based on existing properties and values used at other places in the document. JSON schemas are configured through the server configuration options. +- [Inline Suggestion](https://microsoft.github.io/language-server-protocol/specification#textDocument_completion) for JSON properties and values based on the document's [JSON schema](http://json-schema.org/) or based on existing properties and values used at other places in the document. JSON schemas are configured through the server configuration options. - [Hover](https://microsoft.github.io/language-server-protocol/specification#textDocument_hover) for values based on descriptions in the document's [JSON schema](http://json-schema.org/). - [Document Symbols](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol) for quick navigation to properties in the document. - [Document Colors](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentColor) for showing color decorators on values representing colors and [Color Presentation](https://microsoft.github.io/language-server-protocol/specification#textDocument_colorPresentation) for color presentation information to support color pickers. The location of colors is defined by the document's [JSON schema](http://json-schema.org/). All values marked with `"format": "color-hex"` (VSCode specific, non-standard JSON Schema extension) are considered color values. The supported color formats are `#rgb[a]` and `#rrggbb[aa]`. @@ -37,7 +37,7 @@ The JSON language server expects the client to only send requests and notificati The JSON language server has the following dependencies on the client's capabilities: -- Code completion requires that the client capability has *snippetSupport*. If not supported by the client, the server will not offer the completion capability. +- Inline suggestion requires that the client capability has *snippetSupport*. If not supported by the client, the server will not offer the completion capability. - Formatting support requires the client to support *dynamicRegistration* for *rangeFormatting*. If not supported by the client, the server will not offer the format capability. ## Configuration diff --git a/extensions/json-language-features/server/package-lock.json b/extensions/json-language-features/server/package-lock.json index f16745454d9..e0f73335f29 100644 --- a/extensions/json-language-features/server/package-lock.json +++ b/extensions/json-language-features/server/package-lock.json @@ -12,7 +12,7 @@ "@vscode/l10n": "^0.0.18", "jsonc-parser": "^3.3.1", "request-light": "^0.8.0", - "vscode-json-languageservice": "^5.6.2", + "vscode-json-languageservice": "^5.6.3", "vscode-languageserver": "^10.0.0-next.14", "vscode-uri": "^3.1.0" }, @@ -67,9 +67,9 @@ "license": "MIT" }, "node_modules/vscode-json-languageservice": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.2.tgz", - "integrity": "sha512-miojUH15R/yKxgWkAw1zofv2LDn3Hv3nqIBK+11nGgvdieVClf6ZWOqybPeROruAAMOtX9R6hPptuWYzj3q9NA==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-5.6.3.tgz", + "integrity": "sha512-UDF7sJF5t7mzUzXL6dsClkvnHS4xnDL/gOMKGQiizRHmswlk/xSPGZxEvAtszWQF0ImNcJ0j9l+rHuefGzit1w==", "license": "MIT", "dependencies": { "@vscode/l10n": "^0.0.18", diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index be78d121a8a..446087c31f0 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -15,7 +15,7 @@ "@vscode/l10n": "^0.0.18", "jsonc-parser": "^3.3.1", "request-light": "^0.8.0", - "vscode-json-languageservice": "^5.6.2", + "vscode-json-languageservice": "^5.6.3", "vscode-languageserver": "^10.0.0-next.14", "vscode-uri": "^3.1.0" }, diff --git a/extensions/json-language-features/server/src/jsonServer.ts b/extensions/json-language-features/server/src/jsonServer.ts index 8dc1c588a6d..cbe1e7d02b4 100644 --- a/extensions/json-language-features/server/src/jsonServer.ts +++ b/extensions/json-language-features/server/src/jsonServer.ts @@ -141,8 +141,7 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment) // in the passed params the rootPath of the workspace plus the client capabilities. connection.onInitialize((params: InitializeParams): InitializeResult => { - // eslint-disable-next-line local/code-no-any-casts - const initializationOptions = params.initializationOptions as any || {}; + const initializationOptions = params.initializationOptions || {}; const handledProtocols = initializationOptions?.handledSchemaProtocols; diff --git a/extensions/latex/cgmanifest.json b/extensions/latex/cgmanifest.json index c23c98bd760..80bd155384a 100644 --- a/extensions/latex/cgmanifest.json +++ b/extensions/latex/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "jlelong/vscode-latex-basics", "repositoryUrl": "https://github.com/jlelong/vscode-latex-basics", - "commitHash": "84ce12aa6be384369ff218ac25efb27e6f34e78c" + "commitHash": "f40116471b3b479082937850c822a27208d6b054" } }, "license": "MIT", diff --git a/extensions/latex/package.json b/extensions/latex/package.json index 73e1829f73f..197343cd6a1 100644 --- a/extensions/latex/package.json +++ b/extensions/latex/package.json @@ -66,12 +66,20 @@ { "language": "tex", "scopeName": "text.tex", - "path": "./syntaxes/TeX.tmLanguage.json" + "path": "./syntaxes/TeX.tmLanguage.json", + "unbalancedBracketScopes": [ + "keyword.control.ifnextchar.tex", + "punctuation.math.operator.tex" + ] }, { "language": "latex", "scopeName": "text.tex.latex", "path": "./syntaxes/LaTeX.tmLanguage.json", + "unbalancedBracketScopes": [ + "keyword.control.ifnextchar.tex", + "punctuation.math.operator.tex" + ], "embeddedLanguages": { "source.cpp": "cpp_embedded_latex", "source.css": "css", diff --git a/extensions/latex/syntaxes/TeX.tmLanguage.json b/extensions/latex/syntaxes/TeX.tmLanguage.json index b31ccccb631..1a2e3211ae6 100644 --- a/extensions/latex/syntaxes/TeX.tmLanguage.json +++ b/extensions/latex/syntaxes/TeX.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/jlelong/vscode-latex-basics/commit/6bd99800f7b2cbd0e36cecb56fe1936da5affadb", + "version": "https://github.com/jlelong/vscode-latex-basics/commit/f40116471b3b479082937850c822a27208d6b054", "name": "TeX", "scopeName": "text.tex", "patterns": [ @@ -31,6 +31,9 @@ "match": "\\\\\\\\", "name": "keyword.control.newline.tex" }, + { + "include": "#ifnextchar" + }, { "include": "#macro-general" } @@ -86,6 +89,10 @@ } ] }, + "ifnextchar": { + "match": "\\\\@ifnextchar[({\\[]", + "name": "keyword.control.ifnextchar.tex" + }, "macro-control": { "match": "(\\\\)(backmatter|csname|else|endcsname|fi|frontmatter|mainmatter|unless|if(case|cat|csname|defined|dim|eof|false|fontchar|hbox|hmode|inner|mmode|num|odd|true|vbox|vmode|void|x)?)(?![a-zA-Z@])", "captures": { @@ -225,7 +232,7 @@ "name": "punctuation.math.bracket.pair.big.tex" }, { - "match": "(\\\\)(s(s(earrow|warrow|lash)|h(ort(downarrow|uparrow|parallel|leftarrow|rightarrow|mid)|arp)|tar|i(gma|m(eq)?)|u(cc(sim|n(sim|approx)|curlyeq|eq|approx)?|pset(neq(q)?|plus(eq)?|eq(q)?)?|rd|m|bset(neq(q)?|plus(eq)?|eq(q)?)?)|p(hericalangle|adesuit)|e(tminus|arrow)|q(su(pset(eq)?|bset(eq)?)|c(up|ap)|uare)|warrow|m(ile|all(s(etminus|mile)|frown)))|h(slash|ook(leftarrow|rightarrow)|eartsuit|bar)|R(sh|ightarrow|e|bag)|Gam(e|ma)|n(s(hort(parallel|mid)|im|u(cc(eq)?|pseteq(q)?|bseteq))|Rightarrow|n(earrow|warrow)|cong|triangle(left(eq(slant)?)?|right(eq(slant)?)?)|i(plus)?|u|p(lus|arallel|rec(eq)?)|e(q|arrow|g|xists)|v(dash|Dash)|warrow|le(ss|q(slant|q)?|ft(arrow|rightarrow))|a(tural|bla)|VDash|rightarrow|g(tr|eq(slant|q)?)|mid|Left(arrow|rightarrow))|c(hi|irc(eq|le(d(circ|S|dash|ast)|arrow(left|right)))?|o(ng|prod|lon|mplement)|dot(s|p)?|u(p|r(vearrow(left|right)|ly(eq(succ|prec)|vee(downarrow|uparrow)?|wedge(downarrow|uparrow)?)))|enterdot|lubsuit|ap)|Xi|Maps(to(char)?|from(char)?)|B(ox|umpeq|bbk)|t(h(ick(sim|approx)|e(ta|refore))|imes|op|wohead(leftarrow|rightarrow)|a(u|lloblong)|riangle(down|q|left(eq(slant)?)?|right(eq(slant)?)?)?)|i(n(t(er(cal|leave))?|plus|fty)?|ota|math)|S(igma|u(pset|bset))|zeta|o(slash|times|int|dot|plus|vee|wedge|lessthan|greaterthan|m(inus|ega)|b(slash|long|ar))|d(i(v(ideontimes)?|a(g(down|up)|mond(suit)?)|gamma)|o(t(plus|eq(dot)?)|ublebarwedge|wn(harpoon(left|right)|downarrows|arrow))|d(ots|agger)|elta|a(sh(v|leftarrow|rightarrow)|leth|gger))|Y(down|up|left|right)|C(up|ap)|u(n(lhd|rhd)|p(silon|harpoon(left|right)|downarrow|uparrows|lus|arrow)|lcorner|rcorner)|jmath|Theta|Im|p(si|hi|i(tchfork)?|erp|ar(tial|allel)|r(ime|o(d|pto)|ec(sim|n(sim|approx)|curlyeq|eq|approx)?)|m)|e(t(h|a)|psilon|q(slant(less|gtr)|circ|uiv)|ll|xists|mptyset)|Omega|D(iamond|ownarrow|elta)|v(d(ots|ash)|ee(bar)?|Dash|ar(s(igma|u(psetneq(q)?|bsetneq(q)?))|nothing|curly(vee|wedge)|t(heta|imes|riangle(left|right)?)|o(slash|circle|times|dot|plus|vee|wedge|lessthan|ast|greaterthan|minus|b(slash|ar))|p(hi|i|ropto)|epsilon|kappa|rho|bigcirc))|kappa|Up(silon|downarrow|arrow)|Join|f(orall|lat|a(t(s(emi|lash)|bslash)|llingdotseq)|rown)|P(si|hi|i)|w(p|edge|r)|l(hd|n(sim|eq(q)?|approx)|ceil|times|ightning|o(ng(left(arrow|rightarrow)|rightarrow|maps(to|from))|zenge|oparrow(left|right))|dot(s|p)|e(ss(sim|dot|eq(qgtr|gtr)|approx|gtr)|q(slant|q)?|ft(slice|harpoon(down|up)|threetimes|leftarrows|arrow(t(ail|riangle))?|right(squigarrow|harpoons|arrow(s|triangle|eq)?))|adsto)|vertneqq|floor|l(c(orner|eil)|floor|l|bracket)?|a(ngle|mbda)|rcorner|bag)|a(s(ymp|t)|ngle|pprox(eq)?|l(pha|eph)|rrownot|malg)|V(dash|vdash)|r(h(o|d)|ceil|times|i(singdotseq|ght(s(quigarrow|lice)|harpoon(down|up)|threetimes|left(harpoons|arrows)|arrow(t(ail|riangle))?|rightarrows))|floor|angle|r(ceil|parenthesis|floor|bracket)|bag)|g(n(sim|eq(q)?|approx)|tr(sim|dot|eq(qless|less)|less|approx)|imel|eq(slant|q)?|vertneqq|amma|g(g)?)|Finv|xi|m(ho|i(nuso|d)|o(o|dels)|u(ltimap)?|p|e(asuredangle|rge)|aps(to|from(char)?))|b(i(n(dnasrepma|ampersand)|g(s(tar|qc(up|ap))|nplus|c(irc|u(p|rly(vee|wedge))|ap)|triangle(down|up)|interleave|o(times|dot|plus)|uplus|parallel|vee|wedge|box))|o(t|wtie|x(slash|circle|times|dot|plus|empty|ast|minus|b(slash|ox|ar)))|u(llet|mpeq)|e(cause|t(h|ween|a))|lack(square|triangle(down|left|right)?|lozenge)|a(ck(s(im(eq)?|lash)|prime|epsilon)|r(o|wedge))|bslash)|L(sh|ong(left(arrow|rightarrow)|rightarrow|maps(to|from))|eft(arrow|rightarrow)|leftarrow|ambda|bag)|Arrownot)(?![a-zA-Z@])", + "match": "(\\\\)(s(s(earrow|warrow|lash)|h(ort(downarrow|uparrow|parallel|leftarrow|rightarrow|mid)|arp)|tar|i(gma|m(eq)?)|u(cc(sim|n(sim|approx)|curlyeq|eq|approx)?|pset(neq(q)?|plus(eq)?|eq(q)?)?|rd|m|bset(neq(q)?|plus(eq)?|eq(q)?)?)|p(hericalangle|adesuit)|e(tminus|arrow)|q(su(pset(eq)?|bset(eq)?)|c(up|ap)|uare)|warrow|m(ile|all(s(etminus|mile)|frown)))|h(slash|ook(leftarrow|rightarrow)|eartsuit|bar)|R(sh|ightarrow|e|bag)|Gam(e|ma)|n(s(hort(parallel|mid)|im|u(cc(eq)?|pseteq(q)?|bseteq))|Rightarrow|n(earrow|warrow)|cong|triangle(left(eq(slant)?)?|right(eq(slant)?)?)|i(plus)?|u|p(lus|arallel|rec(eq)?)|e(q|arrow|g|xists)|v(dash|Dash)|warrow|le(ss|q(slant|q)?|ft(arrow|rightarrow))|a(tural|bla)|VDash|rightarrow|g(tr|eq(slant|q)?)|mid|Left(arrow|rightarrow))|c(hi|irc(eq|le(d(circ|S|dash|ast)|arrow(left|right)))?|o(ng|prod|lon|mplement)|dot(s|p)?|u(p|r(vearrow(left|right)|ly(eq(succ|prec)|vee(downarrow|uparrow)?|wedge(downarrow|uparrow)?)))|enterdot|lubsuit|ap)|Xi|Maps(to(char)?|from(char)?)|B(ox|umpeq|bbk)|t(h(ick(sim|approx)|e(ta|refore))|imes|op|wohead(leftarrow|rightarrow)|a(u|lloblong)|riangle(down|q|left(eq(slant)?)?|right(eq(slant)?)?)?)|i(n(t(er(cal|leave))?|plus|fty)?|ota|math)|S(igma|u(pset|bset))|zeta|o(slash|times|int|dot|plus|vee|wedge|lessthan|greaterthan|m(inus|ega)|b(slash|long|ar))|d(i(v(ideontimes)?|a(g(down|up)|mond(suit)?)|gamma)|o(t(plus|eq(dot)?)|ublebarwedge|wn(harpoon(left|right)|downarrows|arrow))|d(ots|agger)|elta|a(sh(v|leftarrow|rightarrow)|leth|gger))|Y(down|up|left|right)|C(up|ap)|u(n(lhd|rhd)|p(silon|harpoon(left|right)|downarrow|uparrows|lus|arrow)|lcorner|rcorner)|jmath|Theta|Im|p(si|hi|i(tchfork)?|erp|ar(tial|allel)|r(ime|o(d|pto)|ec(sim|n(sim|approx)|curlyeq|eq|approx)?)|m)|e(t(h|a)|psilon|q(slant(less|gtr)|circ|uiv)|ll|xists|mptyset)|Omega|D(iamond|ownarrow|elta)|v(d(ots|ash)|ee(bar)?|Dash|ar(s(igma|u(psetneq(q)?|bsetneq(q)?))|nothing|curly(vee|wedge)|t(heta|imes|riangle(left|right)?)|o(slash|circle|times|dot|plus|vee|wedge|lessthan|ast|greaterthan|minus|b(slash|ar))|p(hi|i|ropto)|epsilon|kappa|rho|bigcirc))|kappa|Up(silon|downarrow|arrow)|Join|f(orall|lat|a(t(s(emi|lash)|bslash)|llingdotseq)|rown)|P(si|hi|i)|w(p|edge|r)|l(hd|n(sim|eq(q)?|approx)|ceil|times|ightning|o(ng(left(arrow|rightarrow)|rightarrow|maps(to|from))|zenge|oparrow(left|right))|dot(s|p)|e(ss(sim|dot|eq(qgtr|gtr)|approx|gtr)|q(slant|q)?|ft(slice|harpoon(down|up)|threetimes|leftarrows|arrow(t(ail|riangle))?|right(squigarrow|harpoons|arrow(s|triangle|eq)?))|adsto)|vertneqq|floor|l(c(orner|eil)|floor|l|bracket)?|a(ngle|mbda)|rcorner|bag)|a(s(ymp|t)|ngle|pprox(eq)?|l(pha|eph)|rrownot|malg)|V(dash|vdash)|r(h(o|d)|ceil|times|i(singdotseq|ght(s(quigarrow|lice)|harpoon(down|up)|threetimes|left(harpoons|arrows)|arrow(t(ail|riangle))?|rightarrows))|floor|angle|r(ceil|parenthesis|floor|bracket)|bag)|g(n(sim|eq(q)?|approx)|tr(sim|dot|eq(qless|less)|less|approx)|imel|eq(slant|q)?|vertneqq|amma|g(g)?)|Finv|xi|m(ho|i(nuso|d)|o(o|dels)|u(ltimap)?|p|e(asuredangle|rge)|aps(to|from(char)?))|b(i(n(dnasrepma|ampersand)|g(s(tar|qc(up|ap))|nplus|c(irc|u(p|rly(vee|wedge))|ap)|triangle(down|up)|interleave|o(times|dot|plus)|uplus|parallel|vee|wedge|box))|o(t|wtie|x(slash|circle|times|dot|plus|empty|ast|minus|b(slash|ox|ar)))|u(llet|mpeq)|e(cause|t(h|ween|a))|lack(square|triangle(down|left|right)?|lozenge)|a(ck(s(im(eq)?|lash)|prime|epsilon)|r(o|wedge))|bslash)|L(sh|ong(left(arrow|rightarrow)|rightarrow|maps(to|from))|eft(arrow|rightarrow)|leftarrow|ambda|bag)|ge|le|Arrownot)(?![a-zA-Z@])", "captures": { "1": { "name": "punctuation.definition.constant.math.tex" diff --git a/extensions/markdown-basics/package.json b/extensions/markdown-basics/package.json index baf50c80bb2..cb1351a71cf 100644 --- a/extensions/markdown-basics/package.json +++ b/extensions/markdown-basics/package.json @@ -28,6 +28,9 @@ ".mdtext", ".workbook" ], + "filenamePatterns": [ + "**/.cursor/**/*.mdc" + ], "configuration": "./language-configuration.json" } ], diff --git a/extensions/markdown-language-features/notebook/tsconfig.json b/extensions/markdown-language-features/notebook/tsconfig.json index 77ee816cd75..90241aa7803 100644 --- a/extensions/markdown-language-features/notebook/tsconfig.json +++ b/extensions/markdown-language-features/notebook/tsconfig.json @@ -4,7 +4,6 @@ "outDir": "./dist/", "jsx": "react", "module": "esnext", - "allowSyntheticDefaultImports": true, "lib": [ "ES2024", "DOM", diff --git a/extensions/markdown-language-features/package-lock.json b/extensions/markdown-language-features/package-lock.json index aa624439871..0ba6fbad391 100644 --- a/extensions/markdown-language-features/package-lock.json +++ b/extensions/markdown-language-features/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@vscode/extension-telemetry": "^0.9.8", - "dompurify": "^3.2.4", + "dompurify": "^3.2.7", "highlight.js": "^11.8.0", "markdown-it": "^12.3.2", "markdown-it-front-matter": "^0.2.4", @@ -386,9 +386,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", - "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 014d50bbb4c..440d853f872 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -759,7 +759,7 @@ "compile": "gulp compile-extension:markdown-language-features && npm run build-preview && npm run build-notebook", "watch": "npm run build-preview && gulp watch-extension:markdown-language-features", "vscode:prepublish": "npm run build-ext && npm run build-preview", - "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:markdown-language-features ./tsconfig.json", + "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:markdown-language-features ./tsconfig.json", "build-notebook": "node ./esbuild-notebook.mjs", "build-preview": "node ./esbuild-preview.mjs", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", @@ -767,7 +767,7 @@ }, "dependencies": { "@vscode/extension-telemetry": "^0.9.8", - "dompurify": "^3.2.4", + "dompurify": "^3.2.7", "highlight.js": "^11.8.0", "markdown-it": "^12.3.2", "markdown-it-front-matter": "^0.2.4", diff --git a/extensions/markdown-language-features/src/preview/documentRenderer.ts b/extensions/markdown-language-features/src/preview/documentRenderer.ts index c7bc75b9849..61182a24436 100644 --- a/extensions/markdown-language-features/src/preview/documentRenderer.ts +++ b/extensions/markdown-language-features/src/preview/documentRenderer.ts @@ -8,8 +8,9 @@ import * as uri from 'vscode-uri'; import { ILogger } from '../logging'; import { MarkdownItEngine } from '../markdownEngine'; import { MarkdownContributionProvider } from '../markdownExtensions'; -import { escapeAttribute, getNonce } from '../util/dom'; +import { escapeAttribute } from '../util/dom'; import { WebviewResourceProvider } from '../util/resources'; +import { generateUuid } from '../util/uuid'; import { MarkdownPreviewConfiguration, MarkdownPreviewConfigurationManager } from './previewConfig'; import { ContentSecurityPolicyArbiter, MarkdownPreviewSecurityLevel } from './security'; @@ -82,7 +83,7 @@ export class MdDocumentRenderer { this._logger.trace('DocumentRenderer', `provideTextDocumentContent - ${markdownDocument.uri}`, initialData); // Content Security Policy - const nonce = getNonce(); + const nonce = generateUuid(); const csp = this._getCsp(resourceProvider, sourceUri, nonce); const body = await this.renderBody(markdownDocument, resourceProvider); diff --git a/extensions/markdown-language-features/src/preview/preview.ts b/extensions/markdown-language-features/src/preview/preview.ts index 1a7a859d446..19d1755e7eb 100644 --- a/extensions/markdown-language-features/src/preview/preview.ts +++ b/extensions/markdown-language-features/src/preview/preview.ts @@ -110,15 +110,17 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { } })); - const watcher = this._register(vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(resource, '*'))); - this._register(watcher.onDidChange(uri => { - if (this.isPreviewOf(uri)) { - // Only use the file system event when VS Code does not already know about the file - if (!vscode.workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString())) { - this.refresh(); + if (vscode.workspace.fs.isWritableFileSystem(resource.scheme)) { + const watcher = this._register(vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(resource, '*'))); + this._register(watcher.onDidChange(uri => { + if (this.isPreviewOf(uri)) { + // Only use the file system event when VS Code does not already know about the file + if (!vscode.workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString())) { + this.refresh(); + } } - } - })); + })); + } this._register(this._webviewPanel.webview.onDidReceiveMessage((e: FromWebviewMessage.Type) => { if (e.source !== this._resource.toString()) { diff --git a/extensions/markdown-language-features/src/util/dom.ts b/extensions/markdown-language-features/src/util/dom.ts index 8bbce79c303..16c825c68ff 100644 --- a/extensions/markdown-language-features/src/util/dom.ts +++ b/extensions/markdown-language-features/src/util/dom.ts @@ -11,11 +11,3 @@ export function escapeAttribute(value: string | vscode.Uri): string { .replace(/'/g, '''); } -export function getNonce() { - let text = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 64; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} diff --git a/extensions/markdown-language-features/src/util/uuid.ts b/extensions/markdown-language-features/src/util/uuid.ts new file mode 100644 index 00000000000..ca420b3b6af --- /dev/null +++ b/extensions/markdown-language-features/src/util/uuid.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Copied from src/vs/base/common/uuid.ts + */ +export function generateUuid(): string { + // use `randomUUID` if possible + if (typeof crypto.randomUUID === 'function') { + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto + // > Although crypto is available on all windows, the returned Crypto object only has one + // > usable feature in insecure contexts: the getRandomValues() method. + // > In general, you should use this API only in secure contexts. + + return crypto.randomUUID.bind(crypto)(); + } + + // prep-work + const _data = new Uint8Array(16); + const _hex: string[] = []; + for (let i = 0; i < 256; i++) { + _hex.push(i.toString(16).padStart(2, '0')); + } + + // get data + crypto.getRandomValues(_data); + + // set version bits + _data[6] = (_data[6] & 0x0f) | 0x40; + _data[8] = (_data[8] & 0x3f) | 0x80; + + // print as string + let i = 0; + let result = ''; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + return result; +} diff --git a/extensions/media-preview/package-lock.json b/extensions/media-preview/package-lock.json index d26855f3ad2..fcd827cb0c3 100644 --- a/extensions/media-preview/package-lock.json +++ b/extensions/media-preview/package-lock.json @@ -12,6 +12,9 @@ "@vscode/extension-telemetry": "^0.9.8", "vscode-uri": "^3.0.6" }, + "devDependencies": { + "@types/node": "22.x" + }, "engines": { "vscode": "^1.70.0" } @@ -140,6 +143,16 @@ "integrity": "sha512-OUUJTh3fnaUSzg9DEHgv3d7jC+DnPL65mIO7RaR+jWve7+MmcgIvF79gY97DPQ4frH+IpNR78YAYd/dW4gK3kg==", "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.13.tgz", + "integrity": "sha512-Bo45YKIjnmFtv6I1TuC8AaHBbqXtIo+Om5fE4QiU1Tj8QR/qt+8O3BAtOimG5IFmwaWiPmB3Mv3jtYzBA4Us2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/@vscode/extension-telemetry": { "version": "0.9.8", "resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.9.8.tgz", @@ -154,6 +167,13 @@ "vscode": "^1.75.0" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/vscode-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.6.tgz", diff --git a/extensions/media-preview/package.json b/extensions/media-preview/package.json index 02b0134e4cf..3f7e1c01653 100644 --- a/extensions/media-preview/package.json +++ b/extensions/media-preview/package.json @@ -155,7 +155,7 @@ "compile": "gulp compile-extension:media-preview", "watch": "npm run build-preview && gulp watch-extension:media-preview", "vscode:prepublish": "npm run build-ext", - "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:media-preview ./tsconfig.json", + "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:media-preview ./tsconfig.json", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, @@ -163,6 +163,9 @@ "@vscode/extension-telemetry": "^0.9.8", "vscode-uri": "^3.0.6" }, + "devDependencies": { + "@types/node": "22.x" + }, "repository": { "type": "git", "url": "https://github.com/microsoft/vscode.git" diff --git a/extensions/media-preview/src/audioPreview.ts b/extensions/media-preview/src/audioPreview.ts index 5058f7e978e..282d579b380 100644 --- a/extensions/media-preview/src/audioPreview.ts +++ b/extensions/media-preview/src/audioPreview.ts @@ -6,7 +6,8 @@ import * as vscode from 'vscode'; import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry'; import { MediaPreview, reopenAsText } from './mediaPreview'; -import { escapeAttribute, getNonce } from './util/dom'; +import { escapeAttribute } from './util/dom'; +import { generateUuid } from './util/uuid'; class AudioPreviewProvider implements vscode.CustomReadonlyEditorProvider { @@ -57,7 +58,7 @@ class AudioPreview extends MediaPreview { src: await this.getResourcePath(this._webviewEditor, this._resource, version), }; - const nonce = getNonce(); + const nonce = generateUuid(); const cspSource = this._webviewEditor.webview.cspSource; return /* html */` diff --git a/extensions/media-preview/src/imagePreview/index.ts b/extensions/media-preview/src/imagePreview/index.ts index b405cd652c4..6c2c8a73f66 100644 --- a/extensions/media-preview/src/imagePreview/index.ts +++ b/extensions/media-preview/src/imagePreview/index.ts @@ -6,7 +6,8 @@ import * as vscode from 'vscode'; import { BinarySizeStatusBarEntry } from '../binarySizeStatusBarEntry'; import { MediaPreview, PreviewState, reopenAsText } from '../mediaPreview'; -import { escapeAttribute, getNonce } from '../util/dom'; +import { escapeAttribute } from '../util/dom'; +import { generateUuid } from '../util/uuid'; import { SizeStatusBarEntry } from './sizeStatusBarEntry'; import { Scale, ZoomStatusBarEntry } from './zoomStatusBarEntry'; @@ -184,7 +185,7 @@ class ImagePreview extends MediaPreview { src: await this.getResourcePath(this._webviewEditor, this._resource, version), }; - const nonce = getNonce(); + const nonce = generateUuid(); const cspSource = this._webviewEditor.webview.cspSource; return /* html */` diff --git a/extensions/media-preview/src/util/dom.ts b/extensions/media-preview/src/util/dom.ts index 0f6c00da9da..f89d668c74d 100644 --- a/extensions/media-preview/src/util/dom.ts +++ b/extensions/media-preview/src/util/dom.ts @@ -7,12 +7,3 @@ import * as vscode from 'vscode'; export function escapeAttribute(value: string | vscode.Uri): string { return value.toString().replace(/"/g, '"'); } - -export function getNonce() { - let text = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 64; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} diff --git a/extensions/media-preview/src/util/uuid.ts b/extensions/media-preview/src/util/uuid.ts new file mode 100644 index 00000000000..ca420b3b6af --- /dev/null +++ b/extensions/media-preview/src/util/uuid.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Copied from src/vs/base/common/uuid.ts + */ +export function generateUuid(): string { + // use `randomUUID` if possible + if (typeof crypto.randomUUID === 'function') { + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto + // > Although crypto is available on all windows, the returned Crypto object only has one + // > usable feature in insecure contexts: the getRandomValues() method. + // > In general, you should use this API only in secure contexts. + + return crypto.randomUUID.bind(crypto)(); + } + + // prep-work + const _data = new Uint8Array(16); + const _hex: string[] = []; + for (let i = 0; i < 256; i++) { + _hex.push(i.toString(16).padStart(2, '0')); + } + + // get data + crypto.getRandomValues(_data); + + // set version bits + _data[6] = (_data[6] & 0x0f) | 0x40; + _data[8] = (_data[8] & 0x3f) | 0x80; + + // print as string + let i = 0; + let result = ''; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + return result; +} diff --git a/extensions/media-preview/src/videoPreview.ts b/extensions/media-preview/src/videoPreview.ts index 67012128cf7..1cb74c58426 100644 --- a/extensions/media-preview/src/videoPreview.ts +++ b/extensions/media-preview/src/videoPreview.ts @@ -6,7 +6,8 @@ import * as vscode from 'vscode'; import { BinarySizeStatusBarEntry } from './binarySizeStatusBarEntry'; import { MediaPreview, reopenAsText } from './mediaPreview'; -import { escapeAttribute, getNonce } from './util/dom'; +import { escapeAttribute } from './util/dom'; +import { generateUuid } from './util/uuid'; class VideoPreviewProvider implements vscode.CustomReadonlyEditorProvider { @@ -61,7 +62,7 @@ class VideoPreview extends MediaPreview { loop: configurations.get('loop'), }; - const nonce = getNonce(); + const nonce = generateUuid(); const cspSource = this._webviewEditor.webview.cspSource; return /* html */` diff --git a/extensions/mermaid-chat-features/package-lock.json b/extensions/mermaid-chat-features/package-lock.json index 18394643a0c..185afcde646 100644 --- a/extensions/mermaid-chat-features/package-lock.json +++ b/extensions/mermaid-chat-features/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "dompurify": "^3.2.6", + "dompurify": "^3.2.7", "mermaid": "^11.11.0" }, "devDependencies": { @@ -1008,9 +1008,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.6.tgz", - "integrity": "sha512-/2GogDQlohXPZe6D6NOgQvXLPSYBqIWMnZ8zzOhn09REE4eyAzb+Hed3jhoM9OkuaJ8P6ZGTTVWQKAi8ieIzfQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" diff --git a/extensions/mermaid-chat-features/package.json b/extensions/mermaid-chat-features/package.json index 2992cbe6c20..2311521c9b1 100644 --- a/extensions/mermaid-chat-features/package.json +++ b/extensions/mermaid-chat-features/package.json @@ -73,7 +73,7 @@ "compile": "gulp compile-extension:mermaid-chat-features && npm run build-chat-webview", "watch": "npm run build-chat-webview && gulp watch-extension:mermaid-chat-features", "vscode:prepublish": "npm run build-ext && npm run build-chat-webview", - "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:mermaid-chat-features", + "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:mermaid-chat-features", "build-chat-webview": "node ./esbuild-chat-webview.mjs", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" @@ -82,7 +82,7 @@ "@types/node": "^22.18.10" }, "dependencies": { - "dompurify": "^3.2.6", + "dompurify": "^3.2.7", "mermaid": "^11.11.0" } } diff --git a/extensions/mermaid-chat-features/src/extension.ts b/extensions/mermaid-chat-features/src/extension.ts index d66518a8db3..51294649f4f 100644 --- a/extensions/mermaid-chat-features/src/extension.ts +++ b/extensions/mermaid-chat-features/src/extension.ts @@ -3,6 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; +import { generateUuid } from './uuid'; /** * View type that uniquely identifies the Mermaid chat output renderer. @@ -42,7 +43,7 @@ export function activate(context: vscode.ExtensionContext) { }; // Set the HTML content for the webview - const nonce = getNonce(); + const nonce = generateUuid(); const mermaidScript = vscode.Uri.joinPath(mediaRoot, 'index.js'); webview.html = ` @@ -96,11 +97,4 @@ function escapeHtmlText(str: string): string { .replace(/'/g, '''); } -function getNonce() { - let text = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 64; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} + diff --git a/extensions/mermaid-chat-features/src/uuid.ts b/extensions/mermaid-chat-features/src/uuid.ts new file mode 100644 index 00000000000..ca420b3b6af --- /dev/null +++ b/extensions/mermaid-chat-features/src/uuid.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Copied from src/vs/base/common/uuid.ts + */ +export function generateUuid(): string { + // use `randomUUID` if possible + if (typeof crypto.randomUUID === 'function') { + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto + // > Although crypto is available on all windows, the returned Crypto object only has one + // > usable feature in insecure contexts: the getRandomValues() method. + // > In general, you should use this API only in secure contexts. + + return crypto.randomUUID.bind(crypto)(); + } + + // prep-work + const _data = new Uint8Array(16); + const _hex: string[] = []; + for (let i = 0; i < 256; i++) { + _hex.push(i.toString(16).padStart(2, '0')); + } + + // get data + crypto.getRandomValues(_data); + + // set version bits + _data[6] = (_data[6] & 0x0f) | 0x40; + _data[8] = (_data[8] & 0x3f) | 0x80; + + // print as string + let i = 0; + let result = ''; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + return result; +} diff --git a/extensions/mermaid-chat-features/tsconfig.json b/extensions/mermaid-chat-features/tsconfig.json index 7e1920f289e..35a9a9ad8a0 100644 --- a/extensions/mermaid-chat-features/tsconfig.json +++ b/extensions/mermaid-chat-features/tsconfig.json @@ -15,6 +15,7 @@ "../../src/vscode-dts/vscode.proposed.chatOutputRenderer.d.ts", "../../src/vscode-dts/vscode.proposed.chatParticipantAdditions.d.ts", "../../src/vscode-dts/vscode.proposed.languageModelThinkingPart.d.ts", - "../../src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts" + "../../src/vscode-dts/vscode.proposed.chatParticipantPrivate.d.ts", + "../../src/vscode-dts/vscode.proposed.languageModelProxy.d.ts" ] } diff --git a/extensions/microsoft-authentication/.vscodeignore b/extensions/microsoft-authentication/.vscodeignore index e7feddb5da8..e2daf4b8a89 100644 --- a/extensions/microsoft-authentication/.vscodeignore +++ b/extensions/microsoft-authentication/.vscodeignore @@ -3,7 +3,6 @@ out/test/** out/** extension.webpack.config.js -extension-browser.webpack.config.js package-lock.json src/** .gitignore diff --git a/extensions/microsoft-authentication/extension-browser.webpack.config.js b/extensions/microsoft-authentication/extension-browser.webpack.config.js deleted file mode 100644 index daf3fdf8447..00000000000 --- a/extensions/microsoft-authentication/extension-browser.webpack.config.js +++ /dev/null @@ -1,27 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -// @ts-check -import path from 'path'; -import { browser as withBrowserDefaults } from '../shared.webpack.config.mjs'; - -export default withBrowserDefaults({ - context: import.meta.dirname, - node: { - global: true, - __filename: false, - __dirname: false, - }, - entry: { - extension: './src/extension.ts', - }, - resolve: { - alias: { - './node/authServer': path.resolve(import.meta.dirname, 'src/browser/authServer'), - './node/buffer': path.resolve(import.meta.dirname, 'src/browser/buffer'), - './node/fetch': path.resolve(import.meta.dirname, 'src/browser/fetch'), - './node/authProvider': path.resolve(import.meta.dirname, 'src/browser/authProvider'), - } - } -}); diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 992e7d09a66..3b3cdeef576 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -14,7 +14,6 @@ ], "activationEvents": [], "enabledApiProposals": [ - "idToken", "nativeWindowHandle", "authIssuers", "authenticationChallenges" @@ -111,13 +110,11 @@ "default": "msal", "enum": [ "msal", - "msal-no-broker", - "classic" + "msal-no-broker" ], "enumDescriptions": [ "%microsoft-authentication.implementation.enumDescriptions.msal%", - "%microsoft-authentication.implementation.enumDescriptions.msal-no-broker%", - "%microsoft-authentication.implementation.enumDescriptions.classic%" + "%microsoft-authentication.implementation.enumDescriptions.msal-no-broker%" ], "markdownDescription": "%microsoft-authentication.implementation.description%", "tags": [ @@ -130,13 +127,10 @@ }, "aiKey": "0c6ae279ed8443289764825290e4f9e2-1a736e7c-1324-4338-be46-fc2a58ae4d14-7255", "main": "./out/extension.js", - "browser": "./dist/browser/extension.js", "scripts": { "vscode:prepublish": "npm run compile", "compile": "gulp compile-extension:microsoft-authentication", - "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", - "watch": "gulp watch-extension:microsoft-authentication", - "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" + "watch": "gulp watch-extension:microsoft-authentication" }, "devDependencies": { "@types/node": "22.x", diff --git a/extensions/microsoft-authentication/package.nls.json b/extensions/microsoft-authentication/package.nls.json index 3b14adfa58e..4fcd2d27b74 100644 --- a/extensions/microsoft-authentication/package.nls.json +++ b/extensions/microsoft-authentication/package.nls.json @@ -3,16 +3,9 @@ "description": "Microsoft authentication provider", "signIn": "Sign In", "signOut": "Sign Out", - "microsoft-authentication.implementation.description": { - "message": "The authentication implementation to use for signing in with a Microsoft account.\n\n*NOTE: The `classic` implementation is deprecated and will be removed in a future release. If the `msal` implementation does not work for you, please [open an issue](command:workbench.action.openIssueReporter) and explain what you are trying to log in to.*", - "comment": [ - "{Locked='[(command:workbench.action.openIssueReporter)]'}", - "The `command:` syntax will turn into a link. Do not translate it." - ] - }, + "microsoft-authentication.implementation.description": "The authentication implementation to use for signing in with a Microsoft account.", "microsoft-authentication.implementation.enumDescriptions.msal": "Use the Microsoft Authentication Library (MSAL) to sign in with a Microsoft account.", "microsoft-authentication.implementation.enumDescriptions.msal-no-broker": "Use the Microsoft Authentication Library (MSAL) to sign in with a Microsoft account using a browser. This is useful if you are having issues with the native broker.", - "microsoft-authentication.implementation.enumDescriptions.classic": "(deprecated) Use the classic authentication flow to sign in with a Microsoft account.", "microsoft-sovereign-cloud.environment.description": { "message": "The Sovereign Cloud to use for authentication. If you select `custom`, you must also set the `#microsoft-sovereign-cloud.customEnvironment#` setting.", "comment": [ diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts deleted file mode 100644 index 1246b2ec40e..00000000000 --- a/extensions/microsoft-authentication/src/AADHelper.ts +++ /dev/null @@ -1,963 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import * as path from 'path'; -import { isSupportedEnvironment } from './common/uri'; -import { IntervalTimer, raceCancellationAndTimeoutError, SequencerByKey } from './common/async'; -import { generateCodeChallenge, generateCodeVerifier, randomUUID } from './cryptoUtils'; -import { BetterTokenStorage, IDidChangeInOtherWindowEvent } from './betterSecretStorage'; -import { LoopbackAuthServer } from './node/authServer'; -import { base64Decode } from './node/buffer'; -import fetch from './node/fetch'; -import { UriEventHandler } from './UriEventHandler'; -import TelemetryReporter from '@vscode/extension-telemetry'; -import { Environment } from '@azure/ms-rest-azure-env'; - -const redirectUrl = 'https://vscode.dev/redirect'; -const defaultActiveDirectoryEndpointUrl = Environment.AzureCloud.activeDirectoryEndpointUrl; -const DEFAULT_CLIENT_ID = 'aebc6443-996d-45c2-90f0-388ff96faa56'; -const DEFAULT_TENANT = 'organizations'; -const MSA_TID = '9188040d-6c67-4c5b-b112-36a304b66dad'; -const MSA_PASSTHRU_TID = 'f8cdef31-a31e-4b4a-93e4-5f571e91255a'; - -const enum MicrosoftAccountType { - AAD = 'aad', - MSA = 'msa', - Unknown = 'unknown' -} - -interface IToken { - accessToken?: string; // When unable to refresh due to network problems, the access token becomes undefined - idToken?: string; // depending on the scopes can be either supplied or empty - - expiresIn?: number; // How long access token is valid, in seconds - expiresAt?: number; // UNIX epoch time at which token will expire - refreshToken: string; - - account: { - label: string; - id: string; - type: MicrosoftAccountType; - }; - scope: string; - sessionId: string; // The account id + the scope -} - -export interface IStoredSession { - id: string; - refreshToken: string; - scope: string; // Scopes are alphabetized and joined with a space - account: { - label: string; - id: string; - }; - endpoint: string | undefined; -} - -export interface ITokenResponse { - access_token: string; - expires_in: number; - ext_expires_in: number; - refresh_token: string; - scope: string; - token_type: string; - id_token?: string; -} - -export interface IMicrosoftTokens { - accessToken: string; - idToken?: string; -} - -interface IScopeData { - originalScopes?: string[]; - scopes: string[]; - scopeStr: string; - scopesToSend: string; - clientId: string; - tenant: string; -} - -export const REFRESH_NETWORK_FAILURE = 'Network failure'; - -export class AzureActiveDirectoryService { - // For details on why this is set to 2/3... see https://github.com/microsoft/vscode/issues/133201#issuecomment-966668197 - private static REFRESH_TIMEOUT_MODIFIER = 1000 * 2 / 3; - private static POLLING_CONSTANT = 1000 * 60 * 30; - - private _tokens: IToken[] = []; - private _refreshTimeouts: Map = new Map(); - private _sessionChangeEmitter: vscode.EventEmitter = new vscode.EventEmitter(); - - // Used to keep track of current requests when not using the local server approach. - private _pendingNonces = new Map(); - private _codeExchangePromises = new Map>(); - private _codeVerfifiers = new Map(); - - // Used to keep track of tokens that we need to store but can't because we aren't the focused window. - private _pendingTokensToStore: Map = new Map(); - - // Used to sequence requests to the same scope. - private _sequencer = new SequencerByKey(); - - constructor( - private readonly _logger: vscode.LogOutputChannel, - _context: vscode.ExtensionContext, - private readonly _uriHandler: UriEventHandler, - private readonly _tokenStorage: BetterTokenStorage, - private readonly _telemetryReporter: TelemetryReporter, - private readonly _env: Environment - ) { - _context.subscriptions.push(this._tokenStorage.onDidChangeInOtherWindow((e) => this.checkForUpdates(e))); - _context.subscriptions.push(vscode.window.onDidChangeWindowState(async (e) => e.focused && await this.storePendingTokens())); - - // In the event that a window isn't focused for a long time, we should still try to store the tokens at some point. - const timer = new IntervalTimer(); - timer.cancelAndSet( - () => !vscode.window.state.focused && this.storePendingTokens(), - // 5 hours + random extra 0-30 seconds so that each window doesn't try to store at the same time - (18000000) + Math.floor(Math.random() * 30000)); - _context.subscriptions.push(timer); - } - - public async initialize(): Promise { - this._logger.trace('Reading sessions from secret storage...'); - const sessions = await this._tokenStorage.getAll(item => this.sessionMatchesEndpoint(item)); - this._logger.trace(`Got ${sessions.length} stored sessions`); - - const refreshes = sessions.map(async session => { - this._logger.trace(`[${session.scope}] '${session.id}' Read stored session`); - const scopes = session.scope.split(' '); - const scopeData: IScopeData = { - scopes, - scopeStr: session.scope, - // filter our special scopes - scopesToSend: scopes.filter(s => !s.startsWith('VSCODE_')).join(' '), - clientId: this.getClientId(scopes), - tenant: this.getTenantId(scopes), - }; - try { - await this.refreshToken(session.refreshToken, scopeData, session.id); - } catch (e) { - // If we aren't connected to the internet, then wait and try to refresh again later. - if (e.message === REFRESH_NETWORK_FAILURE) { - this._tokens.push({ - accessToken: undefined, - refreshToken: session.refreshToken, - account: { - ...session.account, - type: MicrosoftAccountType.Unknown - }, - scope: session.scope, - sessionId: session.id - }); - } else { - vscode.window.showErrorMessage(vscode.l10n.t('You have been signed out because reading stored authentication information failed.')); - this._logger.error(e); - await this.removeSessionByIToken({ - accessToken: undefined, - refreshToken: session.refreshToken, - account: { - ...session.account, - type: MicrosoftAccountType.Unknown - }, - scope: session.scope, - sessionId: session.id - }); - } - } - }); - - const result = await Promise.allSettled(refreshes); - for (const res of result) { - if (res.status === 'rejected') { - this._logger.error(`Failed to initialize stored data: ${res.reason}`); - this.clearSessions(); - break; - } - } - - for (const token of this._tokens) { - /* __GDPR__ - "account" : { - "owner": "TylerLeonhardt", - "comment": "Used to determine the usage of the Microsoft Auth Provider.", - "scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }, - "accountType": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what account types are being used." } - } - */ - this._telemetryReporter.sendTelemetryEvent('account', { - // Get rid of guids from telemetry. - scopes: JSON.stringify(token.scope.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}').split(' ')), - accountType: token.account.type - }); - } - } - - //#region session operations - - public get onDidChangeSessions(): vscode.Event { - return this._sessionChangeEmitter.event; - } - - public getSessions(scopes: string[] | undefined, { account, authorizationServer }: vscode.AuthenticationProviderSessionOptions = {}): Promise { - if (!scopes) { - this._logger.info('Getting sessions for all scopes...'); - const sessions = this._tokens - .filter(token => !account?.label || token.account.label === account.label) - .map(token => this.convertToSessionSync(token)); - this._logger.info(`Got ${sessions.length} sessions for all scopes${account ? ` for account '${account.label}'` : ''}...`); - return Promise.resolve(sessions); - } - - let modifiedScopes = [...scopes]; - if (!modifiedScopes.includes('openid')) { - modifiedScopes.push('openid'); - } - if (!modifiedScopes.includes('email')) { - modifiedScopes.push('email'); - } - if (!modifiedScopes.includes('profile')) { - modifiedScopes.push('profile'); - } - if (!modifiedScopes.includes('offline_access')) { - modifiedScopes.push('offline_access'); - } - if (authorizationServer) { - const tenant = authorizationServer.path.split('/')[1]; - if (tenant) { - modifiedScopes.push(`VSCODE_TENANT:${tenant}`); - } - } - modifiedScopes = modifiedScopes.sort(); - - const modifiedScopesStr = modifiedScopes.join(' '); - const clientId = this.getClientId(scopes); - const scopeData: IScopeData = { - clientId, - originalScopes: scopes, - scopes: modifiedScopes, - scopeStr: modifiedScopesStr, - // filter our special scopes - scopesToSend: modifiedScopes.filter(s => !s.startsWith('VSCODE_')).join(' '), - tenant: this.getTenantId(modifiedScopes), - }; - - this._logger.trace(`[${scopeData.scopeStr}] Queued getting sessions` + account ? ` for ${account?.label}` : ''); - return this._sequencer.queue(modifiedScopesStr, () => this.doGetSessions(scopeData, account)); - } - - private async doGetSessions(scopeData: IScopeData, account?: vscode.AuthenticationSessionAccountInformation): Promise { - this._logger.info(`[${scopeData.scopeStr}] Getting sessions` + account ? ` for ${account?.label}` : ''); - - const matchingTokens = this._tokens - .filter(token => token.scope === scopeData.scopeStr) - .filter(token => !account?.label || token.account.label === account.label); - // If we still don't have a matching token try to get a new token from an existing token by using - // the refreshToken. This is documented here: - // https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#refresh-the-access-token - // "Refresh tokens are valid for all permissions that your client has already received consent for." - if (!matchingTokens.length) { - // Get a token with the correct client id and account. - let token: IToken | undefined; - for (const t of this._tokens) { - // No refresh token, so we can't make a new token from this session - if (!t.refreshToken) { - continue; - } - // Need to make sure the account matches if we were provided one - if (account?.label && t.account.label !== account.label) { - continue; - } - // If the client id is the default client id, then check for the absence of the VSCODE_CLIENT_ID scope - if (scopeData.clientId === DEFAULT_CLIENT_ID && !t.scope.includes('VSCODE_CLIENT_ID')) { - token = t; - break; - } - // If the client id is not the default client id, then check for the matching VSCODE_CLIENT_ID scope - if (scopeData.clientId !== DEFAULT_CLIENT_ID && t.scope.includes(`VSCODE_CLIENT_ID:${scopeData.clientId}`)) { - token = t; - break; - } - } - - if (token) { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Found a matching token with a different scopes '${token.scope}'. Attempting to get a new session using the existing session.`); - try { - const itoken = await this.doRefreshToken(token.refreshToken, scopeData); - this._sessionChangeEmitter.fire({ added: [this.convertToSessionSync(itoken)], removed: [], changed: [] }); - matchingTokens.push(itoken); - } catch (err) { - this._logger.error(`[${scopeData.scopeStr}] Attempted to get a new session using the existing session with scopes '${token.scope}' but it failed due to: ${err.message ?? err}`); - } - } - } - - this._logger.info(`[${scopeData.scopeStr}] Got ${matchingTokens.length} sessions`); - const results = await Promise.allSettled(matchingTokens.map(token => this.convertToSession(token, scopeData))); - return results - .filter(result => result.status === 'fulfilled') - .map(result => (result as PromiseFulfilledResult).value); - } - - public createSession(scopes: string[], { account, authorizationServer }: vscode.AuthenticationProviderSessionOptions = {}): Promise { - let modifiedScopes = [...scopes]; - if (!modifiedScopes.includes('openid')) { - modifiedScopes.push('openid'); - } - if (!modifiedScopes.includes('email')) { - modifiedScopes.push('email'); - } - if (!modifiedScopes.includes('profile')) { - modifiedScopes.push('profile'); - } - if (!modifiedScopes.includes('offline_access')) { - modifiedScopes.push('offline_access'); - } - if (authorizationServer) { - const tenant = authorizationServer.path.split('/')[1]; - if (tenant) { - modifiedScopes.push(`VSCODE_TENANT:${tenant}`); - } - } - modifiedScopes = modifiedScopes.sort(); - const scopeData: IScopeData = { - originalScopes: scopes, - scopes: modifiedScopes, - scopeStr: modifiedScopes.join(' '), - // filter our special scopes - scopesToSend: modifiedScopes.filter(s => !s.startsWith('VSCODE_')).join(' '), - clientId: this.getClientId(scopes), - tenant: this.getTenantId(modifiedScopes), - }; - - this._logger.trace(`[${scopeData.scopeStr}] Queued creating session`); - return this._sequencer.queue(scopeData.scopeStr, () => this.doCreateSession(scopeData, account)); - } - - private async doCreateSession(scopeData: IScopeData, account?: vscode.AuthenticationSessionAccountInformation): Promise { - this._logger.info(`[${scopeData.scopeStr}] Creating session` + account ? ` for ${account?.label}` : ''); - - const runsRemote = vscode.env.remoteName !== undefined; - const runsServerless = vscode.env.remoteName === undefined && vscode.env.uiKind === vscode.UIKind.Web; - - if (runsServerless && this._env.activeDirectoryEndpointUrl !== defaultActiveDirectoryEndpointUrl) { - throw new Error('Sign in to non-public clouds is not supported on the web.'); - } - - return await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: vscode.l10n.t('Signing in to your account...'), cancellable: true }, async (_progress, token) => { - if (runsRemote || runsServerless) { - return await this.createSessionWithoutLocalServer(scopeData, account?.label, token); - } - - try { - return await this.createSessionWithLocalServer(scopeData, account?.label, token); - } catch (e) { - this._logger.error(`[${scopeData.scopeStr}] Error creating session: ${e}`); - - // If the error was about starting the server, try directly hitting the login endpoint instead - if (e.message === 'Error listening to server' || e.message === 'Closed' || e.message === 'Timeout waiting for port') { - return this.createSessionWithoutLocalServer(scopeData, account?.label, token); - } - - throw e; - } - }); - } - - private async createSessionWithLocalServer(scopeData: IScopeData, loginHint: string | undefined, token: vscode.CancellationToken): Promise { - this._logger.trace(`[${scopeData.scopeStr}] Starting login flow with local server`); - const codeVerifier = generateCodeVerifier(); - const codeChallenge = await generateCodeChallenge(codeVerifier); - const qs = new URLSearchParams({ - response_type: 'code', - response_mode: 'query', - client_id: scopeData.clientId, - redirect_uri: redirectUrl, - scope: scopeData.scopesToSend, - code_challenge_method: 'S256', - code_challenge: codeChallenge, - }); - if (loginHint) { - qs.set('login_hint', loginHint); - } else { - qs.set('prompt', 'select_account'); - } - const loginUrl = new URL(`${scopeData.tenant}/oauth2/v2.0/authorize?${qs.toString()}`, this._env.activeDirectoryEndpointUrl).toString(); - const server = new LoopbackAuthServer(path.join(__dirname, '../media'), loginUrl); - await server.start(); - - let codeToExchange; - try { - vscode.env.openExternal(vscode.Uri.parse(`http://127.0.0.1:${server.port}/signin?nonce=${encodeURIComponent(server.nonce)}`)); - const { code } = await raceCancellationAndTimeoutError(server.waitForOAuthResponse(), token, 1000 * 60 * 5); // 5 minutes - codeToExchange = code; - } finally { - setTimeout(() => { - void server.stop(); - }, 5000); - } - - const session = await this.exchangeCodeForSession(codeToExchange, codeVerifier, scopeData); - this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' Sending change event for added session`); - this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); - this._logger.info(`[${scopeData.scopeStr}] '${session.id}' session successfully created!`); - return session; - } - - private async createSessionWithoutLocalServer(scopeData: IScopeData, loginHint: string | undefined, token: vscode.CancellationToken): Promise { - this._logger.trace(`[${scopeData.scopeStr}] Starting login flow without local server`); - let callbackUri = await vscode.env.asExternalUri(vscode.Uri.parse(`${vscode.env.uriScheme}://vscode.microsoft-authentication`)); - const nonce = generateCodeVerifier(); - const callbackQuery = new URLSearchParams(callbackUri.query); - callbackQuery.set('nonce', encodeURIComponent(nonce)); - callbackUri = callbackUri.with({ - query: callbackQuery.toString() - }); - const state = encodeURIComponent(callbackUri.toString(true)); - const codeVerifier = generateCodeVerifier(); - const codeChallenge = await generateCodeChallenge(codeVerifier); - const signInUrl = new URL(`${scopeData.tenant}/oauth2/v2.0/authorize`, this._env.activeDirectoryEndpointUrl); - const qs = new URLSearchParams({ - response_type: 'code', - client_id: encodeURIComponent(scopeData.clientId), - response_mode: 'query', - redirect_uri: redirectUrl, - state, - scope: scopeData.scopesToSend, - code_challenge_method: 'S256', - code_challenge: codeChallenge, - }); - if (loginHint) { - qs.append('login_hint', loginHint); - } else { - qs.append('prompt', 'select_account'); - } - signInUrl.search = qs.toString(); - const uri = vscode.Uri.parse(signInUrl.toString()); - vscode.env.openExternal(uri); - - - const existingNonces = this._pendingNonces.get(scopeData.scopeStr) || []; - this._pendingNonces.set(scopeData.scopeStr, [...existingNonces, nonce]); - - // Register a single listener for the URI callback, in case the user starts the login process multiple times - // before completing it. - let existingPromise = this._codeExchangePromises.get(scopeData.scopeStr); - let inputBox: vscode.InputBox | undefined; - if (!existingPromise) { - if (isSupportedEnvironment(callbackUri)) { - existingPromise = this.handleCodeResponse(scopeData); - } else { - // This code path shouldn't be hit often, so just surface an error. - throw new Error('Unsupported environment for authentication'); - } - this._codeExchangePromises.set(scopeData.scopeStr, existingPromise); - } - - this._codeVerfifiers.set(nonce, codeVerifier); - - return await raceCancellationAndTimeoutError(existingPromise, token, 1000 * 60 * 5) // 5 minutes - .finally(() => { - this._pendingNonces.delete(scopeData.scopeStr); - this._codeExchangePromises.delete(scopeData.scopeStr); - this._codeVerfifiers.delete(nonce); - inputBox?.dispose(); - }); - } - - public async removeSessionById(sessionId: string, writeToDisk: boolean = true): Promise { - const tokenIndex = this._tokens.findIndex(token => token.sessionId === sessionId); - if (tokenIndex === -1) { - this._logger.warn(`'${sessionId}' Session not found to remove`); - return Promise.resolve(undefined); - } - - const token = this._tokens.splice(tokenIndex, 1)[0]; - this._logger.trace(`[${token.scope}] '${sessionId}' Queued removing session`); - return this._sequencer.queue(token.scope, () => this.removeSessionByIToken(token, writeToDisk)); - } - - public async clearSessions() { - this._logger.trace('Logging out of all sessions'); - this._tokens = []; - await this._tokenStorage.deleteAll(item => this.sessionMatchesEndpoint(item)); - - this._refreshTimeouts.forEach(timeout => { - clearTimeout(timeout); - }); - - this._refreshTimeouts.clear(); - this._logger.trace('All sessions logged out'); - } - - private async removeSessionByIToken(token: IToken, writeToDisk: boolean = true): Promise { - this._logger.info(`[${token.scope}] '${token.sessionId}' Logging out of session`); - this.removeSessionTimeout(token.sessionId); - - if (writeToDisk) { - await this._tokenStorage.delete(token.sessionId); - } - - const tokenIndex = this._tokens.findIndex(t => t.sessionId === token.sessionId); - if (tokenIndex !== -1) { - this._tokens.splice(tokenIndex, 1); - } - - const session = this.convertToSessionSync(token); - this._logger.trace(`[${token.scope}] '${token.sessionId}' Sending change event for session that was removed`); - this._sessionChangeEmitter.fire({ added: [], removed: [session], changed: [] }); - this._logger.info(`[${token.scope}] '${token.sessionId}' Logged out of session successfully!`); - return session; - } - - //#endregion - - //#region timeout - - private setSessionTimeout(sessionId: string, refreshToken: string, scopeData: IScopeData, timeout: number) { - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Setting refresh timeout for ${timeout} milliseconds`); - this.removeSessionTimeout(sessionId); - this._refreshTimeouts.set(sessionId, setTimeout(async () => { - try { - const refreshedToken = await this.refreshToken(refreshToken, scopeData, sessionId); - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Sending change event for session that was refreshed`); - this._sessionChangeEmitter.fire({ added: [], removed: [], changed: [this.convertToSessionSync(refreshedToken)] }); - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' refresh timeout complete`); - } catch (e) { - if (e.message !== REFRESH_NETWORK_FAILURE) { - vscode.window.showErrorMessage(vscode.l10n.t('You have been signed out because reading stored authentication information failed.')); - await this.removeSessionById(sessionId); - } - } - }, timeout)); - } - - private removeSessionTimeout(sessionId: string): void { - const timeout = this._refreshTimeouts.get(sessionId); - if (timeout) { - clearTimeout(timeout); - this._refreshTimeouts.delete(sessionId); - } - } - - //#endregion - - //#region convert operations - - private convertToTokenSync(json: ITokenResponse, scopeData: IScopeData, existingId?: string): IToken { - let claims = undefined; - this._logger.trace(`[${scopeData.scopeStr}] '${existingId ?? 'new'}' Attempting to parse token response.`); - - try { - if (json.id_token) { - claims = JSON.parse(base64Decode(json.id_token.split('.')[1])); - } else { - this._logger.warn(`[${scopeData.scopeStr}] '${existingId ?? 'new'}' Attempting to parse access_token instead since no id_token was included in the response.`); - claims = JSON.parse(base64Decode(json.access_token.split('.')[1])); - } - } catch (e) { - throw e; - } - - const id = `${claims.tid}/${(claims.oid ?? (claims.altsecid ?? '' + claims.ipd))}`; - const sessionId = existingId || `${id}/${randomUUID()}`; - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId}' Token response parsed successfully.`); - return { - expiresIn: json.expires_in, - expiresAt: json.expires_in ? Date.now() + json.expires_in * 1000 : undefined, - accessToken: json.access_token, - idToken: json.id_token, - refreshToken: json.refresh_token, - scope: scopeData.scopeStr, - sessionId, - account: { - label: claims.preferred_username ?? claims.email ?? claims.unique_name ?? 'user@example.com', - id, - type: claims.tid === MSA_TID || claims.tid === MSA_PASSTHRU_TID ? MicrosoftAccountType.MSA : MicrosoftAccountType.AAD - } - }; - } - - /** - * Return a session object without checking for expiry and potentially refreshing. - * @param token The token information. - */ - private convertToSessionSync(token: IToken): vscode.AuthenticationSession { - return { - id: token.sessionId, - accessToken: token.accessToken!, - idToken: token.idToken, - account: token.account, - scopes: token.scope.split(' ') - }; - } - - private async convertToSession(token: IToken, scopeData: IScopeData): Promise { - if (token.accessToken && (!token.expiresAt || token.expiresAt > Date.now())) { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token available from cache${token.expiresAt ? `, expires in ${token.expiresAt - Date.now()} milliseconds` : ''}.`); - return { - id: token.sessionId, - accessToken: token.accessToken, - idToken: token.idToken, - account: token.account, - scopes: scopeData.originalScopes ?? scopeData.scopes - }; - } - - try { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token expired or unavailable, trying refresh`); - const refreshedToken = await this.refreshToken(token.refreshToken, scopeData, token.sessionId); - if (refreshedToken.accessToken) { - return { - id: token.sessionId, - accessToken: refreshedToken.accessToken, - idToken: refreshedToken.idToken, - account: token.account, - // We always prefer the original scopes requested since that array is used as a key in the AuthService - scopes: scopeData.originalScopes ?? scopeData.scopes - }; - } else { - throw new Error(); - } - } catch (e) { - throw new Error('Unavailable due to network problems'); - } - } - - //#endregion - - //#region refresh logic - - private refreshToken(refreshToken: string, scopeData: IScopeData, sessionId?: string): Promise { - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Queued refreshing token`); - return this._sequencer.queue(scopeData.scopeStr, () => this.doRefreshToken(refreshToken, scopeData, sessionId)); - } - - private async doRefreshToken(refreshToken: string, scopeData: IScopeData, sessionId?: string): Promise { - this._logger.trace(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Refreshing token`); - const postData = new URLSearchParams({ - refresh_token: refreshToken, - client_id: scopeData.clientId, - grant_type: 'refresh_token', - scope: scopeData.scopesToSend - }).toString(); - - try { - const json = await this.fetchTokenResponse(postData, scopeData); - const token = this.convertToTokenSync(json, scopeData, sessionId); - if (token.expiresIn) { - this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER); - } - this.setToken(token, scopeData); - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Token refresh success`); - return token; - } catch (e) { - if (e.message === REFRESH_NETWORK_FAILURE) { - // We were unable to refresh because of a network failure (i.e. the user lost internet access). - // so set up a timeout to try again later. We only do this if we have a session id to reference later. - if (sessionId) { - this.setSessionTimeout(sessionId, refreshToken, scopeData, AzureActiveDirectoryService.POLLING_CONSTANT); - } - throw e; - } - this._logger.error(`[${scopeData.scopeStr}] '${sessionId ?? 'new'}' Refreshing token failed: ${e.message}`); - throw e; - } - } - - //#endregion - - //#region scope parsers - - private getClientId(scopes: string[]) { - return scopes.reduce((prev, current) => { - if (current.startsWith('VSCODE_CLIENT_ID:')) { - return current.split('VSCODE_CLIENT_ID:')[1]; - } - return prev; - }, undefined) ?? DEFAULT_CLIENT_ID; - } - - private getTenantId(scopes: string[]) { - return scopes.reduce((prev, current) => { - if (current.startsWith('VSCODE_TENANT:')) { - return current.split('VSCODE_TENANT:')[1]; - } - return prev; - }, undefined) ?? DEFAULT_TENANT; - } - - //#endregion - - //#region oauth flow - - private async handleCodeResponse(scopeData: IScopeData): Promise { - let uriEventListener: vscode.Disposable; - return new Promise((resolve: (value: vscode.AuthenticationSession) => void, reject) => { - uriEventListener = this._uriHandler.event(async (uri: vscode.Uri) => { - try { - const query = new URLSearchParams(uri.query); - let code = query.get('code'); - let nonce = query.get('nonce'); - if (Array.isArray(code)) { - code = code[0]; - } - if (!code) { - throw new Error('No code included in query'); - } - if (Array.isArray(nonce)) { - nonce = nonce[0]; - } - if (!nonce) { - throw new Error('No nonce included in query'); - } - - const acceptedStates = this._pendingNonces.get(scopeData.scopeStr) || []; - // Workaround double encoding issues of state in web - if (!acceptedStates.includes(nonce) && !acceptedStates.includes(decodeURIComponent(nonce))) { - throw new Error('Nonce does not match.'); - } - - const verifier = this._codeVerfifiers.get(nonce) ?? this._codeVerfifiers.get(decodeURIComponent(nonce)); - if (!verifier) { - throw new Error('No available code verifier'); - } - - const session = await this.exchangeCodeForSession(code, verifier, scopeData); - this._sessionChangeEmitter.fire({ added: [session], removed: [], changed: [] }); - this._logger.info(`[${scopeData.scopeStr}] '${session.id}' session successfully created!`); - resolve(session); - } catch (err) { - reject(err); - } - }); - }).then(result => { - uriEventListener.dispose(); - return result; - }).catch(err => { - uriEventListener.dispose(); - throw err; - }); - } - - private async exchangeCodeForSession(code: string, codeVerifier: string, scopeData: IScopeData): Promise { - this._logger.trace(`[${scopeData.scopeStr}] Exchanging login code for session`); - let token: IToken | undefined; - try { - const postData = new URLSearchParams({ - grant_type: 'authorization_code', - code: code, - client_id: scopeData.clientId, - scope: scopeData.scopesToSend, - code_verifier: codeVerifier, - redirect_uri: redirectUrl - }).toString(); - - const json = await this.fetchTokenResponse(postData, scopeData); - this._logger.trace(`[${scopeData.scopeStr}] Exchanging code for token succeeded!`); - token = this.convertToTokenSync(json, scopeData); - } catch (e) { - this._logger.error(`[${scopeData.scopeStr}] Error exchanging code for token: ${e}`); - throw e; - } - - if (token.expiresIn) { - this.setSessionTimeout(token.sessionId, token.refreshToken, scopeData, token.expiresIn * AzureActiveDirectoryService.REFRESH_TIMEOUT_MODIFIER); - } - this.setToken(token, scopeData); - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Exchanging login code for session succeeded!`); - return await this.convertToSession(token, scopeData); - } - - private async fetchTokenResponse(postData: string, scopeData: IScopeData): Promise { - let endpointUrl: string; - if (this._env.activeDirectoryEndpointUrl !== defaultActiveDirectoryEndpointUrl) { - // If this is for sovereign clouds, don't try using the proxy endpoint, which supports only public cloud - endpointUrl = this._env.activeDirectoryEndpointUrl; - } else { - const proxyEndpoints: { [providerId: string]: string } | undefined = await vscode.commands.executeCommand('workbench.getCodeExchangeProxyEndpoints'); - endpointUrl = proxyEndpoints?.microsoft || this._env.activeDirectoryEndpointUrl; - } - const endpoint = new URL(`${scopeData.tenant}/oauth2/v2.0/token`, endpointUrl); - - let attempts = 0; - while (attempts <= 3) { - attempts++; - let result; - let errorMessage: string | undefined; - try { - result = await fetch(endpoint.toString(), { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - body: postData - }); - } catch (e) { - errorMessage = e.message ?? e; - } - - if (!result || result.status > 499) { - if (attempts > 3) { - this._logger.error(`[${scopeData.scopeStr}] Fetching token failed: ${result ? await result.text() : errorMessage}`); - break; - } - // Exponential backoff - await new Promise(resolve => setTimeout(resolve, 5 * attempts * attempts * 1000)); - continue; - } else if (!result.ok) { - // For 4XX errors, the user may actually have an expired token or have changed - // their password recently which is throwing a 4XX. For this, we throw an error - // so that the user can be prompted to sign in again. - throw new Error(await result.text()); - } - - return await result.json() as ITokenResponse; - } - - throw new Error(REFRESH_NETWORK_FAILURE); - } - - //#endregion - - //#region storage operations - - private setToken(token: IToken, scopeData: IScopeData): void { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Setting token`); - - const existingTokenIndex = this._tokens.findIndex(t => t.sessionId === token.sessionId); - if (existingTokenIndex > -1) { - this._tokens.splice(existingTokenIndex, 1, token); - } else { - this._tokens.push(token); - } - - // Don't await because setting the token is only useful for any new windows that open. - void this.storeToken(token, scopeData); - } - - private async storeToken(token: IToken, scopeData: IScopeData): Promise { - if (!vscode.window.state.focused) { - if (this._pendingTokensToStore.has(token.sessionId)) { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Window is not focused, replacing token to be stored`); - } else { - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Window is not focused, pending storage of token`); - } - this._pendingTokensToStore.set(token.sessionId, token); - return; - } - - await this._tokenStorage.store(token.sessionId, { - id: token.sessionId, - refreshToken: token.refreshToken, - scope: token.scope, - account: token.account, - endpoint: this._env.activeDirectoryEndpointUrl, - }); - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Stored token`); - } - - private async storePendingTokens(): Promise { - if (this._pendingTokensToStore.size === 0) { - this._logger.trace('No pending tokens to store'); - return; - } - - const tokens = [...this._pendingTokensToStore.values()]; - this._pendingTokensToStore.clear(); - - this._logger.trace(`Storing ${tokens.length} pending tokens...`); - await Promise.allSettled(tokens.map(async token => { - this._logger.trace(`[${token.scope}] '${token.sessionId}' Storing pending token`); - await this._tokenStorage.store(token.sessionId, { - id: token.sessionId, - refreshToken: token.refreshToken, - scope: token.scope, - account: token.account, - endpoint: this._env.activeDirectoryEndpointUrl, - }); - this._logger.trace(`[${token.scope}] '${token.sessionId}' Stored pending token`); - })); - this._logger.trace('Done storing pending tokens'); - } - - private async checkForUpdates(e: IDidChangeInOtherWindowEvent): Promise { - for (const key of e.added) { - const session = await this._tokenStorage.get(key); - if (!session) { - this._logger.error('session not found that was apparently just added'); - continue; - } - - if (!this.sessionMatchesEndpoint(session)) { - // If the session wasn't made for this login endpoint, ignore this update - continue; - } - - const matchesExisting = this._tokens.some(token => token.scope === session.scope && token.sessionId === session.id); - if (!matchesExisting && session.refreshToken) { - try { - const scopes = session.scope.split(' '); - const scopeData: IScopeData = { - scopes, - scopeStr: session.scope, - // filter our special scopes - scopesToSend: scopes.filter(s => !s.startsWith('VSCODE_')).join(' '), - clientId: this.getClientId(scopes), - tenant: this.getTenantId(scopes), - }; - this._logger.trace(`[${scopeData.scopeStr}] '${session.id}' Session added in another window`); - const token = await this.refreshToken(session.refreshToken, scopeData, session.id); - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Sending change event for session that was added`); - this._sessionChangeEmitter.fire({ added: [this.convertToSessionSync(token)], removed: [], changed: [] }); - this._logger.trace(`[${scopeData.scopeStr}] '${token.sessionId}' Session added in another window added here`); - continue; - } catch (e) { - // Network failures will automatically retry on next poll. - if (e.message !== REFRESH_NETWORK_FAILURE) { - vscode.window.showErrorMessage(vscode.l10n.t('You have been signed out because reading stored authentication information failed.')); - await this.removeSessionById(session.id); - } - continue; - } - } - } - - for (const { value } of e.removed) { - this._logger.trace(`[${value.scope}] '${value.id}' Session removed in another window`); - if (!this.sessionMatchesEndpoint(value)) { - // If the session wasn't made for this login endpoint, ignore this update - this._logger.trace(`[${value.scope}] '${value.id}' Session doesn't match endpoint. Skipping...`); - continue; - } - - await this.removeSessionById(value.id, false); - this._logger.trace(`[${value.scope}] '${value.id}' Session removed in another window removed here`); - } - - // NOTE: We don't need to handle changed sessions because all that really would give us is a new refresh token - // because access tokens are not stored in Secret Storage due to their short lifespan. This new refresh token - // is not useful in this window because we really only care about the lifetime of the _access_ token which we - // are already managing (see usages of `setSessionTimeout`). - // However, in order to minimize the amount of times we store tokens, if a token was stored via another window, - // we cancel any pending token storage operations. - for (const sessionId of e.updated) { - if (this._pendingTokensToStore.delete(sessionId)) { - this._logger.trace(`'${sessionId}' Cancelled pending token storage because token was updated in another window`); - } - } - } - - private sessionMatchesEndpoint(session: IStoredSession): boolean { - // For older sessions with no endpoint set, it can be assumed to be the default endpoint - session.endpoint ||= defaultActiveDirectoryEndpointUrl; - - return session.endpoint === this._env.activeDirectoryEndpointUrl; - } - - //#endregion -} diff --git a/extensions/microsoft-authentication/src/browser/authProvider.ts b/extensions/microsoft-authentication/src/browser/authProvider.ts deleted file mode 100644 index 3b4da5b18fa..00000000000 --- a/extensions/microsoft-authentication/src/browser/authProvider.ts +++ /dev/null @@ -1,29 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AuthenticationProvider, AuthenticationProviderAuthenticationSessionsChangeEvent, AuthenticationSession, EventEmitter } from 'vscode'; - -export class MsalAuthProvider implements AuthenticationProvider { - private _onDidChangeSessions = new EventEmitter(); - onDidChangeSessions = this._onDidChangeSessions.event; - - initialize(): Thenable { - throw new Error('Method not implemented.'); - } - - getSessions(): Thenable { - throw new Error('Method not implemented.'); - } - createSession(): Thenable { - throw new Error('Method not implemented.'); - } - removeSession(): Thenable { - throw new Error('Method not implemented.'); - } - - dispose() { - this._onDidChangeSessions.dispose(); - } -} diff --git a/extensions/microsoft-authentication/src/browser/buffer.ts b/extensions/microsoft-authentication/src/browser/buffer.ts deleted file mode 100644 index 794bb19f579..00000000000 --- a/extensions/microsoft-authentication/src/browser/buffer.ts +++ /dev/null @@ -1,17 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -export function base64Encode(text: string): string { - return btoa(text); -} - -export function base64Decode(text: string): string { - // modification of https://stackoverflow.com/a/38552302 - const replacedCharacters = text.replace(/-/g, '+').replace(/_/g, '/'); - const decodedText = decodeURIComponent(atob(replacedCharacters).split('').map(function (c) { - return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); - }).join('')); - return decodedText; -} diff --git a/extensions/microsoft-authentication/src/common/telemetryReporter.ts b/extensions/microsoft-authentication/src/common/telemetryReporter.ts index 67b202982ce..c4df9e4c080 100644 --- a/extensions/microsoft-authentication/src/common/telemetryReporter.ts +++ b/extensions/microsoft-authentication/src/common/telemetryReporter.ts @@ -43,17 +43,6 @@ export class MicrosoftAuthenticationTelemetryReporter implements IExperimentatio this._telemetryReporter.sendTelemetryEvent('activatingmsalnobroker'); } - sendActivatedWithClassicImplementationEvent(reason: 'setting' | 'web'): void { - /* __GDPR__ - "activatingClassic" : { - "owner": "TylerLeonhardt", - "comment": "Used to determine how often users use the classic login flow.", - "reason": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "Why classic was used" } - } - */ - this._telemetryReporter.sendTelemetryEvent('activatingClassic', { reason }); - } - sendLoginEvent(scopes: readonly string[]): void { /* __GDPR__ "login" : { diff --git a/extensions/microsoft-authentication/src/extension.ts b/extensions/microsoft-authentication/src/extension.ts index 620a10e1a29..7076f828033 100644 --- a/extensions/microsoft-authentication/src/extension.ts +++ b/extensions/microsoft-authentication/src/extension.ts @@ -3,13 +3,71 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { commands, ExtensionContext, l10n, window, workspace } from 'vscode'; -import * as extensionV1 from './extensionV1'; -import * as extensionV2 from './extensionV2'; -import { MicrosoftAuthenticationTelemetryReporter } from './common/telemetryReporter'; +import { Environment, EnvironmentParameters } from '@azure/ms-rest-azure-env'; +import Logger from './logger'; +import { MsalAuthProvider } from './node/authProvider'; +import { UriEventHandler } from './UriEventHandler'; +import { authentication, commands, ExtensionContext, l10n, window, workspace, Disposable, Uri } from 'vscode'; +import { MicrosoftAuthenticationTelemetryReporter, MicrosoftSovereignCloudAuthenticationTelemetryReporter } from './common/telemetryReporter'; -let implementation: 'msal' | 'msal-no-broker' | 'classic' = 'msal'; -const getImplementation = () => workspace.getConfiguration('microsoft-authentication').get<'msal' | 'msal-no-broker' | 'classic'>('implementation') ?? 'msal'; +let implementation: 'msal' | 'msal-no-broker' = 'msal'; +const getImplementation = () => workspace.getConfiguration('microsoft-authentication').get<'msal' | 'msal-no-broker'>('implementation') ?? 'msal'; + +async function initMicrosoftSovereignCloudAuthProvider( + context: ExtensionContext, + uriHandler: UriEventHandler +): Promise { + const environment = workspace.getConfiguration('microsoft-sovereign-cloud').get('environment'); + let authProviderName: string | undefined; + if (!environment) { + return undefined; + } + + if (environment === 'custom') { + const customEnv = workspace.getConfiguration('microsoft-sovereign-cloud').get('customEnvironment'); + if (!customEnv) { + const res = await window.showErrorMessage(l10n.t('You must also specify a custom environment in order to use the custom environment auth provider.'), l10n.t('Open settings')); + if (res) { + await commands.executeCommand('workbench.action.openSettingsJson', 'microsoft-sovereign-cloud.customEnvironment'); + } + return undefined; + } + try { + Environment.add(customEnv); + } catch (e) { + const res = await window.showErrorMessage(l10n.t('Error validating custom environment setting: {0}', e.message), l10n.t('Open settings')); + if (res) { + await commands.executeCommand('workbench.action.openSettings', 'microsoft-sovereign-cloud.customEnvironment'); + } + return undefined; + } + authProviderName = customEnv.name; + } else { + authProviderName = environment; + } + + const env = Environment.get(authProviderName); + if (!env) { + await window.showErrorMessage(l10n.t('The environment `{0}` is not a valid environment.', authProviderName), l10n.t('Open settings')); + return undefined; + } + + const authProvider = await MsalAuthProvider.create( + context, + new MicrosoftSovereignCloudAuthenticationTelemetryReporter(context.extension.packageJSON.aiKey), + window.createOutputChannel(l10n.t('Microsoft Sovereign Cloud Authentication'), { log: true }), + uriHandler, + env + ); + const disposable = authentication.registerAuthenticationProvider( + 'microsoft-sovereign-cloud', + authProviderName, + authProvider, + { supportsMultipleAccounts: true, supportsChallenges: true } + ); + context.subscriptions.push(disposable); + return disposable; +} export async function activate(context: ExtensionContext) { const mainTelemetryReporter = new MicrosoftAuthenticationTelemetryReporter(context.extension.packageJSON.aiKey); @@ -39,34 +97,46 @@ export async function activate(context: ExtensionContext) { commands.executeCommand('workbench.action.reloadWindow'); } })); - const isNodeEnvironment = typeof process !== 'undefined' && typeof process?.versions?.node === 'string'; - - // Only activate the new extension if we are not running in a browser environment - if (!isNodeEnvironment) { - mainTelemetryReporter.sendActivatedWithClassicImplementationEvent('web'); - return await extensionV1.activate(context, mainTelemetryReporter.telemetryReporter); - } switch (implementation) { case 'msal-no-broker': mainTelemetryReporter.sendActivatedWithMsalNoBrokerEvent(); - await extensionV2.activate(context, mainTelemetryReporter); - break; - case 'classic': - mainTelemetryReporter.sendActivatedWithClassicImplementationEvent('setting'); - await extensionV1.activate(context, mainTelemetryReporter.telemetryReporter); break; case 'msal': default: - await extensionV2.activate(context, mainTelemetryReporter); break; } + + const uriHandler = new UriEventHandler(); + context.subscriptions.push(uriHandler); + const authProvider = await MsalAuthProvider.create( + context, + mainTelemetryReporter, + Logger, + uriHandler + ); + context.subscriptions.push(authentication.registerAuthenticationProvider( + 'microsoft', + 'Microsoft', + authProvider, + { + supportsMultipleAccounts: true, + supportsChallenges: true, + supportedAuthorizationServers: [ + Uri.parse('https://login.microsoftonline.com/*'), + Uri.parse('https://login.microsoftonline.com/*/v2.0') + ] + } + )); + + let microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, uriHandler); + + context.subscriptions.push(workspace.onDidChangeConfiguration(async e => { + if (e.affectsConfiguration('microsoft-sovereign-cloud')) { + microsoftSovereignCloudAuthProviderDisposable?.dispose(); + microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, uriHandler); + } + })); } -export function deactivate() { - if (implementation !== 'classic') { - extensionV2.deactivate(); - } else { - extensionV1.deactivate(); - } -} +export function deactivate() { } diff --git a/extensions/microsoft-authentication/src/extensionV1.ts b/extensions/microsoft-authentication/src/extensionV1.ts deleted file mode 100644 index 02248dd989d..00000000000 --- a/extensions/microsoft-authentication/src/extensionV1.ts +++ /dev/null @@ -1,193 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { Environment, EnvironmentParameters } from '@azure/ms-rest-azure-env'; -import { AzureActiveDirectoryService, IStoredSession } from './AADHelper'; -import { BetterTokenStorage } from './betterSecretStorage'; -import { UriEventHandler } from './UriEventHandler'; -import TelemetryReporter from '@vscode/extension-telemetry'; -import Logger from './logger'; - -async function initMicrosoftSovereignCloudAuthProvider(context: vscode.ExtensionContext, telemetryReporter: TelemetryReporter, uriHandler: UriEventHandler, tokenStorage: BetterTokenStorage): Promise { - const environment = vscode.workspace.getConfiguration('microsoft-sovereign-cloud').get('environment'); - let authProviderName: string | undefined; - if (!environment) { - return undefined; - } - - if (environment === 'custom') { - const customEnv = vscode.workspace.getConfiguration('microsoft-sovereign-cloud').get('customEnvironment'); - if (!customEnv) { - const res = await vscode.window.showErrorMessage(vscode.l10n.t('You must also specify a custom environment in order to use the custom environment auth provider.'), vscode.l10n.t('Open settings')); - if (res) { - await vscode.commands.executeCommand('workbench.action.openSettingsJson', 'microsoft-sovereign-cloud.customEnvironment'); - } - return undefined; - } - try { - Environment.add(customEnv); - } catch (e) { - const res = await vscode.window.showErrorMessage(vscode.l10n.t('Error validating custom environment setting: {0}', e.message), vscode.l10n.t('Open settings')); - if (res) { - await vscode.commands.executeCommand('workbench.action.openSettings', 'microsoft-sovereign-cloud.customEnvironment'); - } - return undefined; - } - authProviderName = customEnv.name; - } else { - authProviderName = environment; - } - - const env = Environment.get(authProviderName); - if (!env) { - const res = await vscode.window.showErrorMessage(vscode.l10n.t('The environment `{0}` is not a valid environment.', authProviderName), vscode.l10n.t('Open settings')); - return undefined; - } - - const aadService = new AzureActiveDirectoryService( - vscode.window.createOutputChannel(vscode.l10n.t('Microsoft Sovereign Cloud Authentication'), { log: true }), - context, - uriHandler, - tokenStorage, - telemetryReporter, - env); - await aadService.initialize(); - - const disposable = vscode.authentication.registerAuthenticationProvider('microsoft-sovereign-cloud', authProviderName, { - onDidChangeSessions: aadService.onDidChangeSessions, - getSessions: (scopes: string[]) => aadService.getSessions(scopes), - createSession: async (scopes: string[]) => { - try { - /* __GDPR__ - "loginMicrosoftSovereignCloud" : { - "owner": "TylerLeonhardt", - "comment": "Used to determine the usage of the Microsoft Sovereign Cloud Auth Provider.", - "scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." } - } - */ - telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloud', { - // Get rid of guids from telemetry. - scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))), - }); - - return await aadService.createSession(scopes); - } catch (e) { - /* __GDPR__ - "loginMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." } - */ - telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloudFailed'); - - throw e; - } - }, - removeSession: async (id: string) => { - try { - /* __GDPR__ - "logoutMicrosoftSovereignCloud" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." } - */ - telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloud'); - - await aadService.removeSessionById(id); - } catch (e) { - /* __GDPR__ - "logoutMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." } - */ - telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloudFailed'); - } - } - }, { supportsMultipleAccounts: true }); - - context.subscriptions.push(disposable); - return disposable; -} - -export async function activate(context: vscode.ExtensionContext, telemetryReporter: TelemetryReporter) { - // If we ever activate the old flow, then mark that we will need to migrate when the user upgrades to v2. - // TODO: MSAL Migration. Remove this when we remove the old flow. - context.globalState.update('msalMigration', false); - - const uriHandler = new UriEventHandler(); - context.subscriptions.push(uriHandler); - const betterSecretStorage = new BetterTokenStorage('microsoft.login.keylist', context); - - const loginService = new AzureActiveDirectoryService( - Logger, - context, - uriHandler, - betterSecretStorage, - telemetryReporter, - Environment.AzureCloud); - await loginService.initialize(); - - context.subscriptions.push(vscode.authentication.registerAuthenticationProvider( - 'microsoft', - 'Microsoft', - { - onDidChangeSessions: loginService.onDidChangeSessions, - getSessions: (scopes: string[], options?: vscode.AuthenticationProviderSessionOptions) => loginService.getSessions(scopes, options), - createSession: async (scopes: string[], options?: vscode.AuthenticationProviderSessionOptions) => { - try { - /* __GDPR__ - "login" : { - "owner": "TylerLeonhardt", - "comment": "Used to determine the usage of the Microsoft Auth Provider.", - "scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." } - } - */ - telemetryReporter.sendTelemetryEvent('login', { - // Get rid of guids from telemetry. - scopes: JSON.stringify(scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'))), - }); - - return await loginService.createSession(scopes, options); - } catch (e) { - /* __GDPR__ - "loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." } - */ - telemetryReporter.sendTelemetryEvent('loginFailed'); - - throw e; - } - }, - removeSession: async (id: string) => { - try { - /* __GDPR__ - "logout" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." } - */ - telemetryReporter.sendTelemetryEvent('logout'); - - await loginService.removeSessionById(id); - } catch (e) { - /* __GDPR__ - "logoutFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." } - */ - telemetryReporter.sendTelemetryEvent('logoutFailed'); - } - } - }, - { - supportsMultipleAccounts: true, - supportedAuthorizationServers: [ - vscode.Uri.parse('https://login.microsoftonline.com/*'), - vscode.Uri.parse('https://login.microsoftonline.com/*/v2.0') - ] - } - )); - - let microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, telemetryReporter, uriHandler, betterSecretStorage); - - context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(async e => { - if (e.affectsConfiguration('microsoft-sovereign-cloud')) { - microsoftSovereignCloudAuthProviderDisposable?.dispose(); - microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, telemetryReporter, uriHandler, betterSecretStorage); - } - })); - - return; -} - -// this method is called when your extension is deactivated -export function deactivate() { } diff --git a/extensions/microsoft-authentication/src/extensionV2.ts b/extensions/microsoft-authentication/src/extensionV2.ts deleted file mode 100644 index bafc8454f8c..00000000000 --- a/extensions/microsoft-authentication/src/extensionV2.ts +++ /dev/null @@ -1,102 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { Environment, EnvironmentParameters } from '@azure/ms-rest-azure-env'; -import Logger from './logger'; -import { MsalAuthProvider } from './node/authProvider'; -import { UriEventHandler } from './UriEventHandler'; -import { authentication, commands, ExtensionContext, l10n, window, workspace, Disposable, Uri } from 'vscode'; -import { MicrosoftAuthenticationTelemetryReporter, MicrosoftSovereignCloudAuthenticationTelemetryReporter } from './common/telemetryReporter'; - -async function initMicrosoftSovereignCloudAuthProvider( - context: ExtensionContext, - uriHandler: UriEventHandler -): Promise { - const environment = workspace.getConfiguration('microsoft-sovereign-cloud').get('environment'); - let authProviderName: string | undefined; - if (!environment) { - return undefined; - } - - if (environment === 'custom') { - const customEnv = workspace.getConfiguration('microsoft-sovereign-cloud').get('customEnvironment'); - if (!customEnv) { - const res = await window.showErrorMessage(l10n.t('You must also specify a custom environment in order to use the custom environment auth provider.'), l10n.t('Open settings')); - if (res) { - await commands.executeCommand('workbench.action.openSettingsJson', 'microsoft-sovereign-cloud.customEnvironment'); - } - return undefined; - } - try { - Environment.add(customEnv); - } catch (e) { - const res = await window.showErrorMessage(l10n.t('Error validating custom environment setting: {0}', e.message), l10n.t('Open settings')); - if (res) { - await commands.executeCommand('workbench.action.openSettings', 'microsoft-sovereign-cloud.customEnvironment'); - } - return undefined; - } - authProviderName = customEnv.name; - } else { - authProviderName = environment; - } - - const env = Environment.get(authProviderName); - if (!env) { - await window.showErrorMessage(l10n.t('The environment `{0}` is not a valid environment.', authProviderName), l10n.t('Open settings')); - return undefined; - } - - const authProvider = await MsalAuthProvider.create( - context, - new MicrosoftSovereignCloudAuthenticationTelemetryReporter(context.extension.packageJSON.aiKey), - window.createOutputChannel(l10n.t('Microsoft Sovereign Cloud Authentication'), { log: true }), - uriHandler, - env - ); - const disposable = authentication.registerAuthenticationProvider( - 'microsoft-sovereign-cloud', - authProviderName, - authProvider, - { supportsMultipleAccounts: true, supportsChallenges: true } - ); - context.subscriptions.push(disposable); - return disposable; -} - -export async function activate(context: ExtensionContext, mainTelemetryReporter: MicrosoftAuthenticationTelemetryReporter) { - const uriHandler = new UriEventHandler(); - context.subscriptions.push(uriHandler); - const authProvider = await MsalAuthProvider.create( - context, - mainTelemetryReporter, - Logger, - uriHandler - ); - context.subscriptions.push(authentication.registerAuthenticationProvider( - 'microsoft', - 'Microsoft', - authProvider, - { - supportsMultipleAccounts: true, - supportsChallenges: true, - supportedAuthorizationServers: [ - Uri.parse('https://login.microsoftonline.com/*'), - Uri.parse('https://login.microsoftonline.com/*/v2.0') - ] - } - )); - - let microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, uriHandler); - - context.subscriptions.push(workspace.onDidChangeConfiguration(async e => { - if (e.affectsConfiguration('microsoft-sovereign-cloud')) { - microsoftSovereignCloudAuthProviderDisposable?.dispose(); - microsoftSovereignCloudAuthProviderDisposable = await initMicrosoftSovereignCloudAuthProvider(context, uriHandler); - } - })); -} - -export function deactivate() { } diff --git a/extensions/microsoft-authentication/src/node/authProvider.ts b/extensions/microsoft-authentication/src/node/authProvider.ts index ac57bf0680b..334196e7160 100644 --- a/extensions/microsoft-authentication/src/node/authProvider.ts +++ b/extensions/microsoft-authentication/src/node/authProvider.ts @@ -12,7 +12,6 @@ import { MicrosoftAccountType, MicrosoftAuthenticationTelemetryReporter } from ' import { ScopeData } from '../common/scopeData'; import { EventBufferer } from '../common/event'; import { BetterTokenStorage } from '../betterSecretStorage'; -import { IStoredSession } from '../AADHelper'; import { ExtensionHost, getMsalFlows } from './flows'; import { base64Decode } from './buffer'; import { Config } from '../common/config'; @@ -21,6 +20,22 @@ import { isSupportedClient } from '../common/env'; const MSA_TID = '9188040d-6c67-4c5b-b112-36a304b66dad'; const MSA_PASSTHRU_TID = 'f8cdef31-a31e-4b4a-93e4-5f571e91255a'; +/** + * Interface for sessions stored from the old authentication flow. + * Used for migration purposes when upgrading to MSAL. + * TODO: Remove this after one or two releases. + */ +export interface IStoredSession { + id: string; + refreshToken: string; + scope: string; // Scopes are alphabetized and joined with a space + account: { + label: string; + id: string; + }; + endpoint: string | undefined; +} + export class MsalAuthProvider implements AuthenticationProvider { private readonly _disposables: { dispose(): void }[]; @@ -209,12 +224,9 @@ export class MsalAuthProvider implements AuthenticationProvider { } }; - const isNodeEnvironment = typeof process !== 'undefined' && typeof process?.versions?.node === 'string'; const callbackUri = await env.asExternalUri(Uri.parse(`${env.uriScheme}://vscode.microsoft-authentication`)); const flows = getMsalFlows({ - extensionHost: isNodeEnvironment - ? this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote - : ExtensionHost.WebWorker, + extensionHost: this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote, supportedClient: isSupportedClient(callbackUri), isBrokerSupported: cachedPca.isBrokerAvailable }); @@ -348,12 +360,9 @@ export class MsalAuthProvider implements AuthenticationProvider { } }; - const isNodeEnvironment = typeof process !== 'undefined' && typeof process?.versions?.node === 'string'; const callbackUri = await env.asExternalUri(Uri.parse(`${env.uriScheme}://vscode.microsoft-authentication`)); const flows = getMsalFlows({ - extensionHost: isNodeEnvironment - ? this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote - : ExtensionHost.WebWorker, + extensionHost: this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote, isBrokerSupported: cachedPca.isBrokerAvailable, supportedClient: isSupportedClient(callbackUri) }); diff --git a/extensions/microsoft-authentication/src/node/flows.ts b/extensions/microsoft-authentication/src/node/flows.ts index 4a3c877691b..22782330bd6 100644 --- a/extensions/microsoft-authentication/src/node/flows.ts +++ b/extensions/microsoft-authentication/src/node/flows.ts @@ -14,14 +14,12 @@ import { Config } from '../common/config'; const DEFAULT_REDIRECT_URI = 'https://vscode.dev/redirect'; export const enum ExtensionHost { - WebWorker, Remote, Local } interface IMsalFlowOptions { supportsRemoteExtensionHost: boolean; - supportsWebWorkerExtensionHost: boolean; supportsUnsupportedClient: boolean; supportsBroker: boolean; } @@ -48,7 +46,6 @@ class DefaultLoopbackFlow implements IMsalFlow { label = 'default'; options: IMsalFlowOptions = { supportsRemoteExtensionHost: false, - supportsWebWorkerExtensionHost: false, supportsUnsupportedClient: true, supportsBroker: true }; @@ -78,7 +75,6 @@ class UrlHandlerFlow implements IMsalFlow { label = 'protocol handler'; options: IMsalFlowOptions = { supportsRemoteExtensionHost: true, - supportsWebWorkerExtensionHost: false, supportsUnsupportedClient: false, supportsBroker: false }; @@ -108,7 +104,6 @@ class DeviceCodeFlow implements IMsalFlow { label = 'device code'; options: IMsalFlowOptions = { supportsRemoteExtensionHost: true, - supportsWebWorkerExtensionHost: false, supportsUnsupportedClient: true, supportsBroker: false }; @@ -139,13 +134,8 @@ export function getMsalFlows(query: IMsalFlowQuery): IMsalFlow[] { const flows = []; for (const flow of allFlows) { let useFlow: boolean = true; - switch (query.extensionHost) { - case ExtensionHost.Remote: - useFlow &&= flow.options.supportsRemoteExtensionHost; - break; - case ExtensionHost.WebWorker: - useFlow &&= flow.options.supportsWebWorkerExtensionHost; - break; + if (query.extensionHost === ExtensionHost.Remote) { + useFlow &&= flow.options.supportsRemoteExtensionHost; } useFlow &&= flow.options.supportsBroker || !query.isBrokerSupported; useFlow &&= flow.options.supportsUnsupportedClient || query.supportedClient; diff --git a/extensions/microsoft-authentication/src/node/test/flows.test.ts b/extensions/microsoft-authentication/src/node/test/flows.test.ts index 1cd4bd6077a..b2685e783cc 100644 --- a/extensions/microsoft-authentication/src/node/test/flows.test.ts +++ b/extensions/microsoft-authentication/src/node/test/flows.test.ts @@ -43,16 +43,6 @@ suite('getMsalFlows', () => { assert.strictEqual(flows[1].label, 'device code'); }); - test('should return no flows for web worker extension host', () => { - const query: IMsalFlowQuery = { - extensionHost: ExtensionHost.WebWorker, - supportedClient: true, - isBrokerSupported: false - }; - const flows = getMsalFlows(query); - assert.strictEqual(flows.length, 0); - }); - test('should return only default and device code flows for local extension host with unsupported client and no broker', () => { const query: IMsalFlowQuery = { extensionHost: ExtensionHost.Local, diff --git a/extensions/microsoft-authentication/tsconfig.json b/extensions/microsoft-authentication/tsconfig.json index f9713b530cc..e9a3ade3ed5 100644 --- a/extensions/microsoft-authentication/tsconfig.json +++ b/extensions/microsoft-authentication/tsconfig.json @@ -4,15 +4,11 @@ "outDir": "./out", "noFallthroughCasesInSwitch": true, "noUnusedLocals": false, - "skipLibCheck": true, - "lib": [ - "WebWorker" - ] + "skipLibCheck": true }, "include": [ "src/**/*", "../../src/vscode-dts/vscode.d.ts", - "../../src/vscode-dts/vscode.proposed.idToken.d.ts", "../../src/vscode-dts/vscode.proposed.nativeWindowHandle.d.ts", "../../src/vscode-dts/vscode.proposed.authIssuers.d.ts", "../../src/vscode-dts/vscode.proposed.authenticationChallenges.d.ts" diff --git a/extensions/notebook-renderers/src/index.ts b/extensions/notebook-renderers/src/index.ts index 6c3205fa7b7..09d4129e817 100644 --- a/extensions/notebook-renderers/src/index.ts +++ b/extensions/notebook-renderers/src/index.ts @@ -65,8 +65,7 @@ const domEval = (container: Element) => { for (const key of preservedScriptAttributes) { const val = node[key] || node.getAttribute && node.getAttribute(key); if (val) { - // eslint-disable-next-line local/code-no-any-casts - scriptTag.setAttribute(key, val as any); + scriptTag.setAttribute(key, val as unknown as string); } } @@ -76,8 +75,8 @@ const domEval = (container: Element) => { }; function getAltText(outputInfo: OutputItem) { - const metadata = outputInfo.metadata; - if (typeof metadata === 'object' && metadata && 'vscode_altText' in metadata && typeof metadata.vscode_altText === 'string') { + const metadata = outputInfo.metadata as Record | undefined; + if (typeof metadata === 'object' && metadata && typeof metadata.vscode_altText === 'string') { return metadata.vscode_altText; } return undefined; @@ -337,9 +336,9 @@ function findScrolledHeight(container: HTMLElement): number | undefined { } function scrollingEnabled(output: OutputItem, options: RenderOptions) { - const metadata = output.metadata; + const metadata = output.metadata as Record | undefined; return (typeof metadata === 'object' && metadata - && 'scrollable' in metadata && typeof metadata.scrollable === 'boolean') ? + && typeof metadata.scrollable === 'boolean') ? metadata.scrollable : options.outputScrolling; } diff --git a/extensions/notebook-renderers/src/test/linkify.test.ts b/extensions/notebook-renderers/src/test/linkify.test.ts index cae8f569423..d24145a2b62 100644 --- a/extensions/notebook-renderers/src/test/linkify.test.ts +++ b/extensions/notebook-renderers/src/test/linkify.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { JSDOM } from "jsdom"; +import { JSDOM } from 'jsdom'; import { LinkDetector, linkify } from '../linkify'; const dom = new JSDOM(); diff --git a/extensions/notebook-renderers/src/test/notebookRenderer.test.ts b/extensions/notebook-renderers/src/test/notebookRenderer.test.ts index def7a1282ab..a193ce38d72 100644 --- a/extensions/notebook-renderers/src/test/notebookRenderer.test.ts +++ b/extensions/notebook-renderers/src/test/notebookRenderer.test.ts @@ -7,7 +7,7 @@ import * as assert from 'assert'; import { activate } from '..'; import { RendererApi } from 'vscode-notebook-renderer'; import { IDisposable, IRichRenderContext, OutputWithAppend, RenderOptions } from '../rendererTypes'; -import { JSDOM } from "jsdom"; +import { JSDOM } from 'jsdom'; import { LinkDetector } from '../linkify'; const dom = new JSDOM(); @@ -16,12 +16,12 @@ global.document = dom.window.document; suite('Notebook builtin output renderer', () => { const error = { - name: "TypeError", - message: "Expected type `str`, but received type ``", - stack: "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m" + - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)" + - "\u001b[1;32mc:\\src\\test\\ws1\\testing.py\u001b[0m in \u001b[0;36mline 2\n\u001b[0;32m 35\u001b[0m \u001b[39m# %%\u001b[39;00m\n\u001b[1;32m----> 36\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mTypeError\u001b[39;00m(\u001b[39m'\u001b[39m\u001b[39merror = f\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mExpected type `str`, but received type `\u001b[39m\u001b[39m{\u001b[39m\u001b[39mtype(name)}`\u001b[39m\u001b[39m\"\u001b[39m\u001b[39m'\u001b[39m)\n" + - "\u001b[1;31mTypeError\u001b[0m: Expected type `str`, but received type ``\"" + name: 'TypeError', + message: 'Expected type `str`, but received type ``', + stack: '\u001b[1;31m---------------------------------------------------------------------------\u001b[0m' + + '\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)' + + '\u001b[1;32mc:\\src\\test\\ws1\\testing.py\u001b[0m in \u001b[0;36mline 2\n\u001b[0;32m 35\u001b[0m \u001b[39m# %%\u001b[39;00m\n\u001b[1;32m----> 36\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mTypeError\u001b[39;00m(\u001b[39m\'\u001b[39m\u001b[39merror = f\u001b[39m\u001b[39m"\u001b[39m\u001b[39mExpected type `str`, but received type `\u001b[39m\u001b[39m{\u001b[39m\u001b[39mtype(name)}`\u001b[39m\u001b[39m"\u001b[39m\u001b[39m\'\u001b[39m)\n' + + '\u001b[1;31mTypeError\u001b[0m: Expected type `str`, but received type ``"' }; const errorMimeType = 'application/vnd.code.notebook.error'; @@ -127,15 +127,13 @@ suite('Notebook builtin output renderer', () => { return text; }, blob() { - // eslint-disable-next-line local/code-no-any-casts - return [] as any; + return new Blob([text], { type: mime }); }, json() { return '{ }'; }, data() { - // eslint-disable-next-line local/code-no-any-casts - return [] as any; + return new Uint8Array(); }, metadata: {} }; @@ -489,13 +487,13 @@ suite('Notebook builtin output renderer', () => { }); const rawIPythonError = { - name: "NameError", - message: "name 'x' is not defined", - stack: "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m" + - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)" + - "Cell \u001b[1;32mIn[2], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mmyfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n" + - "Cell \u001b[1;32mIn[1], line 2\u001b[0m, in \u001b[0;36mmyfunc\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmyfunc\u001b[39m():\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mx\u001b[49m)\n" + - "\u001b[1;31mNameError\u001b[0m: name 'x' is not defined" + name: 'NameError', + message: `name 'x' is not defined`, + stack: '\u001b[1;31m---------------------------------------------------------------------------\u001b[0m' + + '\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)' + + 'Cell \u001b[1;32mIn[2], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[43mmyfunc\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n' + + 'Cell \u001b[1;32mIn[1], line 2\u001b[0m, in \u001b[0;36mmyfunc\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmyfunc\u001b[39m():\n\u001b[1;32m----> 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43mx\u001b[49m)\n' + + `\u001b[1;31mNameError\u001b[0m: name 'x' is not defined` }; test(`Should clean up raw IPython error stack traces`, async () => { diff --git a/extensions/prompt-basics/package.json b/extensions/prompt-basics/package.json index 91ea0c081b0..cd53e185bb6 100644 --- a/extensions/prompt-basics/package.json +++ b/extensions/prompt-basics/package.json @@ -20,8 +20,7 @@ "prompt" ], "extensions": [ - ".prompt.md", - "copilot-instructions.md" + ".prompt.md" ], "configuration": "./language-configuration.json" }, @@ -38,14 +37,18 @@ "configuration": "./language-configuration.json" }, { - "id": "chatmode", + "id": "chatagent", "aliases": [ - "Chat Mode", - "chat mode" + "Agent", + "chat agent" ], "extensions": [ + ".agent.md", ".chatmode.md" ], + "filenamePatterns": [ + "**/.github/agents/*.md" + ], "configuration": "./language-configuration.json" } ], @@ -69,7 +72,7 @@ ] }, { - "language": "chatmode", + "language": "chatagent", "path": "./syntaxes/prompt.tmLanguage.json", "scopeName": "text.html.markdown.prompt", "unbalancedBracketScopes": [ @@ -80,6 +83,9 @@ ], "configurationDefaults": { "[prompt]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.autoIndent": "advanced", "editor.unicodeHighlight.ambiguousCharacters": false, "editor.unicodeHighlight.invisibleCharacters": false, "diffEditor.ignoreTrimWhitespace": false, @@ -91,6 +97,9 @@ } }, "[instructions]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.autoIndent": "advanced", "editor.unicodeHighlight.ambiguousCharacters": false, "editor.unicodeHighlight.invisibleCharacters": false, "diffEditor.ignoreTrimWhitespace": false, @@ -101,7 +110,10 @@ "other": "off" } }, - "[chatmode]": { + "[chatagent]": { + "editor.insertSpaces": true, + "editor.tabSize": 2, + "editor.autoIndent": "advanced", "editor.unicodeHighlight.ambiguousCharacters": false, "editor.unicodeHighlight.invisibleCharacters": false, "diffEditor.ignoreTrimWhitespace": false, diff --git a/extensions/search-result/package.json b/extensions/search-result/package.json index 155ed6ae658..1119636313f 100644 --- a/extensions/search-result/package.json +++ b/extensions/search-result/package.json @@ -16,7 +16,7 @@ ], "scripts": { "generate-grammar": "node ./syntaxes/generateTMLanguage.js", - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:search-result ./tsconfig.json" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:search-result ./tsconfig.json" }, "capabilities": { "virtualWorkspaces": true, diff --git a/extensions/shellscript/package.json b/extensions/shellscript/package.json index ab9be7b29ad..9cad54150bb 100644 --- a/extensions/shellscript/package.json +++ b/extensions/shellscript/package.json @@ -69,9 +69,6 @@ "bashrc_Apple_Terminal", "zshrc_Apple_Terminal" ], - "filenamePatterns": [ - ".env.*" - ], "firstLine": "^#!.*\\b(bash|fish|zsh|sh|ksh|dtksh|pdksh|mksh|ash|dash|yash|sh|csh|jcsh|tcsh|itcsh).*|^#\\s*-\\*-[^*]*mode:\\s*shell-script[^*]*-\\*-", "configuration": "./language-configuration.json", "mimetypes": [ diff --git a/extensions/simple-browser/package-lock.json b/extensions/simple-browser/package-lock.json index c6d9b23636a..8aa3894ba1e 100644 --- a/extensions/simple-browser/package-lock.json +++ b/extensions/simple-browser/package-lock.json @@ -12,6 +12,7 @@ "@vscode/extension-telemetry": "^0.9.8" }, "devDependencies": { + "@types/node": "22.x", "@types/vscode-webview": "^1.57.0", "@vscode/codicons": "^0.0.36" }, @@ -143,6 +144,16 @@ "integrity": "sha512-OUUJTh3fnaUSzg9DEHgv3d7jC+DnPL65mIO7RaR+jWve7+MmcgIvF79gY97DPQ4frH+IpNR78YAYd/dW4gK3kg==", "license": "MIT" }, + "node_modules/@types/node": { + "version": "22.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.13.tgz", + "integrity": "sha512-Bo45YKIjnmFtv6I1TuC8AaHBbqXtIo+Om5fE4QiU1Tj8QR/qt+8O3BAtOimG5IFmwaWiPmB3Mv3jtYzBA4Us2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, "node_modules/@types/vscode-webview": { "version": "1.57.0", "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.0.tgz", @@ -169,6 +180,13 @@ "engines": { "vscode": "^1.75.0" } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" } } } diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json index 5e081c4bbd2..79802e73668 100644 --- a/extensions/simple-browser/package.json +++ b/extensions/simple-browser/package.json @@ -60,7 +60,7 @@ "compile": "gulp compile-extension:simple-browser && npm run build-preview", "watch": "npm run build-preview && gulp watch-extension:simple-browser", "vscode:prepublish": "npm run build-ext && npm run build-preview", - "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:simple-browser ./tsconfig.json", + "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:simple-browser ./tsconfig.json", "build-preview": "node ./esbuild-preview.mjs", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" @@ -69,6 +69,7 @@ "@vscode/extension-telemetry": "^0.9.8" }, "devDependencies": { + "@types/node": "22.x", "@types/vscode-webview": "^1.57.0", "@vscode/codicons": "^0.0.36" }, diff --git a/extensions/simple-browser/src/extension.ts b/extensions/simple-browser/src/extension.ts index 927167a851d..885afe28712 100644 --- a/extensions/simple-browser/src/extension.ts +++ b/extensions/simple-browser/src/extension.ts @@ -86,6 +86,5 @@ export function activate(context: vscode.ExtensionContext) { } function isWeb(): boolean { - // @ts-expect-error return !(typeof process === 'object' && !!process.versions.node) && vscode.env.uiKind === vscode.UIKind.Web; } diff --git a/extensions/simple-browser/src/simpleBrowserView.ts b/extensions/simple-browser/src/simpleBrowserView.ts index 5725dcf4f9b..56c5aff5c8a 100644 --- a/extensions/simple-browser/src/simpleBrowserView.ts +++ b/extensions/simple-browser/src/simpleBrowserView.ts @@ -5,6 +5,7 @@ import * as vscode from 'vscode'; import { Disposable } from './dispose'; +import { generateUuid } from './uuid'; export interface ShowOptions { @@ -112,7 +113,7 @@ export class SimpleBrowserView extends Disposable { private getHtml(url: string) { const configuration = vscode.workspace.getConfiguration('simpleBrowser'); - const nonce = getNonce(); + const nonce = generateUuid(); const mainJs = this.extensionResourceUrl('media', 'index.js'); const mainCss = this.extensionResourceUrl('media', 'main.css'); @@ -181,12 +182,3 @@ export class SimpleBrowserView extends Disposable { function escapeAttribute(value: string | vscode.Uri): string { return value.toString().replace(/"/g, '"'); } - -function getNonce() { - let text = ''; - const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 64; i++) { - text += possible.charAt(Math.floor(Math.random() * possible.length)); - } - return text; -} diff --git a/extensions/simple-browser/src/uuid.ts b/extensions/simple-browser/src/uuid.ts new file mode 100644 index 00000000000..ca420b3b6af --- /dev/null +++ b/extensions/simple-browser/src/uuid.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Copied from src/vs/base/common/uuid.ts + */ +export function generateUuid(): string { + // use `randomUUID` if possible + if (typeof crypto.randomUUID === 'function') { + // see https://developer.mozilla.org/en-US/docs/Web/API/Window/crypto + // > Although crypto is available on all windows, the returned Crypto object only has one + // > usable feature in insecure contexts: the getRandomValues() method. + // > In general, you should use this API only in secure contexts. + + return crypto.randomUUID.bind(crypto)(); + } + + // prep-work + const _data = new Uint8Array(16); + const _hex: string[] = []; + for (let i = 0; i < 256; i++) { + _hex.push(i.toString(16).padStart(2, '0')); + } + + // get data + crypto.getRandomValues(_data); + + // set version bits + _data[6] = (_data[6] & 0x0f) | 0x40; + _data[8] = (_data[8] & 0x3f) | 0x80; + + // print as string + let i = 0; + let result = ''; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += '-'; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + result += _hex[_data[i++]]; + return result; +} diff --git a/extensions/simple-browser/tsconfig.json b/extensions/simple-browser/tsconfig.json index 60b13d71670..43ed762ce7d 100644 --- a/extensions/simple-browser/tsconfig.json +++ b/extensions/simple-browser/tsconfig.json @@ -2,7 +2,6 @@ "extends": "../tsconfig.base.json", "compilerOptions": { "outDir": "./out", - "types": [], "typeRoots": [ "./node_modules/@types" ] diff --git a/extensions/terminal-suggest/package.json b/extensions/terminal-suggest/package.json index 2151c48ae6f..66e99b20e11 100644 --- a/extensions/terminal-suggest/package.json +++ b/extensions/terminal-suggest/package.json @@ -28,8 +28,7 @@ "terminal": { "completionProviders": [ { - "id": "terminal-suggest", - "description": "Provides completions for terminal commands, arguments, flags, and file paths based upon the Fig spec." + "description": "Show suggestions for commands, arguments, flags, and file paths based upon the Fig spec." } ] } diff --git a/extensions/terminal-suggest/src/completions/azd.ts b/extensions/terminal-suggest/src/completions/azd.ts new file mode 100644 index 00000000000..1b5609b0433 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/azd.ts @@ -0,0 +1,1808 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +interface AzdEnvListItem { + Name: string; + DotEnvPath: string; + HasLocal: boolean; + HasRemote: boolean; + IsDefault: boolean; +} + +interface AzdTemplateListItem { + name: string; + description: string; + repositoryPath: string; + tags: string[]; +} + +interface AzdExtensionListItem { + id: string; + name: string; + namespace: string; + version: string; + installedVersion: string; + source: string; +} + +const azdGenerators: Record = { + listEnvironments: { + script: ['azd', 'env', 'list', '--output', 'json'], + postProcess: (out) => { + try { + const envs: AzdEnvListItem[] = JSON.parse(out); + return envs.map((env) => ({ + name: env.Name, + displayName: env.IsDefault ? 'Default' : undefined, + })); + } catch { + return []; + } + }, + }, + listEnvironmentVariables: { + script: ['azd', 'env', 'get-values', '--output', 'json'], + postProcess: (out) => { + try { + const envVars: Record = JSON.parse(out); + return Object.keys(envVars).map((key) => ({ + name: key, + })); + } catch { + return []; + } + }, + }, + listTemplates: { + script: ['azd', 'template', 'list', '--output', 'json'], + postProcess: (out) => { + try { + const templates: AzdTemplateListItem[] = JSON.parse(out); + return templates.map((template) => ({ + name: template.repositoryPath, + description: template.name, + })); + } catch { + return []; + } + }, + cache: { + strategy: 'stale-while-revalidate', + } + }, + listTemplateTags: { + script: ['azd', 'template', 'list', '--output', 'json'], + postProcess: (out) => { + try { + const templates: AzdTemplateListItem[] = JSON.parse(out); + const tagsSet = new Set(); + + // Collect all unique tags from all templates + templates.forEach((template) => { + if (template.tags && Array.isArray(template.tags)) { + template.tags.forEach((tag) => tagsSet.add(tag)); + } + }); + + // Convert set to array and return as suggestions + return Array.from(tagsSet).sort().map((tag) => ({ + name: tag, + })); + } catch { + return []; + } + }, + cache: { + strategy: 'stale-while-revalidate', + } + }, + listTemplatesFiltered: { + custom: async (tokens, executeCommand, generatorContext) => { + // Find if there's a -f or --filter flag in the tokens + let filterValue: string | undefined; + for (let i = 0; i < tokens.length; i++) { + if ((tokens[i] === '-f' || tokens[i] === '--filter') && i + 1 < tokens.length) { + filterValue = tokens[i + 1]; + break; + } + } + + // Build the azd command with filter if present + const args = ['template', 'list', '--output', 'json']; + if (filterValue) { + args.push('--filter', filterValue); + } + + try { + const { stdout } = await executeCommand({ + command: 'azd', + args: args, + }); + + const templates: AzdTemplateListItem[] = JSON.parse(stdout); + return templates.map((template) => ({ + name: template.repositoryPath, + description: template.name, + })); + } catch { + return []; + } + }, + cache: { + strategy: 'stale-while-revalidate', + } + }, + listExtensions: { + script: ['azd', 'ext', 'list', '--output', 'json'], + postProcess: (out) => { + try { + const extensions: AzdExtensionListItem[] = JSON.parse(out); + const uniqueExtensions = new Map(); + + extensions.forEach((ext) => { + if (!uniqueExtensions.has(ext.id)) { + uniqueExtensions.set(ext.id, ext); + } + }); + + return Array.from(uniqueExtensions.values()).map((ext) => ({ + name: ext.id, + description: ext.name, + })); + } catch { + return []; + } + }, + cache: { + strategy: 'stale-while-revalidate', + } + }, + listInstalledExtensions: { + script: ['azd', 'ext', 'list', '--installed', '--output', 'json'], + postProcess: (out) => { + try { + const extensions: AzdExtensionListItem[] = JSON.parse(out); + const uniqueExtensions = new Map(); + + extensions.forEach((ext) => { + if (!uniqueExtensions.has(ext.id)) { + uniqueExtensions.set(ext.id, ext); + } + }); + + return Array.from(uniqueExtensions.values()).map((ext) => ({ + name: ext.id, + description: ext.name, + })); + } catch { + return []; + } + }, + }, +}; + +const completionSpec: Fig.Spec = { + name: 'azd', + description: 'Azure Developer CLI', + subcommands: [ + { + name: ['add'], + description: 'Add a component to your project.', + }, + { + name: ['auth'], + description: 'Authenticate with Azure.', + subcommands: [ + { + name: ['login'], + description: 'Log in to Azure.', + options: [ + { + name: ['--check-status'], + description: 'Checks the log-in status instead of logging in.', + }, + { + name: ['--client-certificate'], + description: 'The path to the client certificate for the service principal to authenticate with.', + args: [ + { + name: 'client-certificate', + }, + ], + }, + { + name: ['--client-id'], + description: 'The client id for the service principal to authenticate with.', + args: [ + { + name: 'client-id', + }, + ], + }, + { + name: ['--client-secret'], + description: 'The client secret for the service principal to authenticate with. Set to the empty string to read the value from the console.', + args: [ + { + name: 'client-secret', + }, + ], + }, + { + name: ['--federated-credential-provider'], + description: 'The provider to use to acquire a federated token to authenticate with. Supported values: github, azure-pipelines, oidc', + args: [ + { + name: 'federated-credential-provider', + suggestions: ['github', 'azure-pipelines', 'oidc'], + }, + ], + }, + { + name: ['--managed-identity'], + description: 'Use a managed identity to authenticate.', + }, + { + name: ['--redirect-port'], + description: 'Choose the port to be used as part of the redirect URI during interactive login.', + args: [ + { + name: 'redirect-port', + }, + ], + }, + { + name: ['--tenant-id'], + description: 'The tenant id or domain name to authenticate with.', + args: [ + { + name: 'tenant-id', + }, + ], + }, + { + name: ['--use-device-code'], + description: 'When true, log in by using a device code instead of a browser.', + }, + ], + }, + { + name: ['logout'], + description: 'Log out of Azure.', + }, + ], + }, + { + name: ['completion'], + description: 'Generate shell completion scripts.', + subcommands: [ + { + name: ['bash'], + description: 'Generate bash completion script.', + }, + { + name: ['fig'], + description: 'Generate Fig autocomplete spec.', + }, + { + name: ['fish'], + description: 'Generate fish completion script.', + }, + { + name: ['powershell'], + description: 'Generate PowerShell completion script.', + }, + { + name: ['zsh'], + description: 'Generate zsh completion script.', + }, + ], + }, + { + name: ['config'], + description: 'Manage azd configurations (ex: default Azure subscription, location).', + subcommands: [ + { + name: ['get'], + description: 'Gets a configuration.', + args: { + name: 'path', + }, + }, + { + name: ['list-alpha'], + description: 'Display the list of available features in alpha stage.', + }, + { + name: ['reset'], + description: 'Resets configuration to default.', + options: [ + { + name: ['--force', '-f'], + description: 'Force reset without confirmation.', + isDangerous: true, + }, + ], + }, + { + name: ['set'], + description: 'Sets a configuration.', + args: [ + { + name: 'path', + }, + { + name: 'value', + }, + ], + }, + { + name: ['show'], + description: 'Show all the configuration values.', + }, + { + name: ['unset'], + description: 'Unsets a configuration.', + args: { + name: 'path', + }, + }, + ], + }, + { + name: ['deploy'], + description: 'Deploy your project code to Azure.', + options: [ + { + name: ['--all'], + description: 'Deploys all services that are listed in azure.yaml', + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--from-package'], + description: 'Deploys the packaged service located at the provided path. Supports zipped file packages (file path) or container images (image tag).', + args: [ + { + name: 'file-path|image-tag', + }, + ], + }, + ], + args: { + name: 'service', + isOptional: true, + }, + }, + { + name: ['down'], + description: 'Delete your project\'s Azure resources.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--force'], + description: 'Does not require confirmation before it deletes resources.', + isDangerous: true, + }, + { + name: ['--purge'], + description: 'Does not require confirmation before it permanently deletes resources that are soft-deleted by default (for example, key vaults).', + isDangerous: true, + }, + ], + }, + { + name: ['env'], + description: 'Manage environments (ex: default environment, environment variables).', + subcommands: [ + { + name: ['get-value'], + description: 'Get specific environment value.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + ], + args: { + name: 'keyName', + generators: azdGenerators.listEnvironmentVariables, + }, + }, + { + name: ['get-values'], + description: 'Get all environment values.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + ], + }, + { + name: ['list', 'ls'], + description: 'List environments.', + }, + { + name: ['new'], + description: 'Create a new environment and set it as the default.', + options: [ + { + name: ['--location', '-l'], + description: 'Azure location for the new environment', + args: [ + { + name: 'location', + }, + ], + }, + { + name: ['--subscription'], + description: 'Name or ID of an Azure subscription to use for the new environment', + args: [ + { + name: 'subscription', + }, + ], + }, + ], + args: { + name: 'environment', + }, + }, + { + name: ['refresh'], + description: 'Refresh environment values by using information from a previous infrastructure provision.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--hint'], + description: 'Hint to help identify the environment to refresh', + args: [ + { + name: 'hint', + }, + ], + }, + ], + args: { + name: 'environment', + }, + }, + { + name: ['select'], + description: 'Set the default environment.', + args: { + name: 'environment', + generators: azdGenerators.listEnvironments, + }, + }, + { + name: ['set'], + description: 'Set one or more environment values.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--file'], + description: 'Path to .env formatted file to load environment values from.', + args: [ + { + name: 'file', + }, + ], + }, + ], + args: [ + { + name: 'key', + isOptional: true, + }, + { + name: 'value', + isOptional: true, + }, + ], + }, + { + name: ['set-secret'], + description: 'Set a name as a reference to a Key Vault secret in the environment.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + ], + args: { + name: 'name', + }, + }, + ], + }, + { + name: ['extension', 'ext'], + description: 'Manage azd extensions.', + subcommands: [ + { + name: ['install'], + description: 'Installs specified extensions.', + options: [ + { + name: ['--force', '-f'], + description: 'Force installation even if it would downgrade the current version', + isDangerous: true, + }, + { + name: ['--source', '-s'], + description: 'The extension source to use for installs', + args: [ + { + name: 'source', + }, + ], + }, + { + name: ['--version', '-v'], + description: 'The version of the extension to install', + args: [ + { + name: 'version', + }, + ], + }, + ], + args: { + name: 'extension-id', + generators: azdGenerators.listExtensions, + }, + }, + { + name: ['list'], + description: 'List available extensions.', + options: [ + { + name: ['--installed'], + description: 'List installed extensions', + }, + { + name: ['--source'], + description: 'Filter extensions by source', + args: [ + { + name: 'source', + }, + ], + }, + { + name: ['--tags'], + description: 'Filter extensions by tags', + isRepeatable: true, + args: [ + { + name: 'tags', + }, + ], + }, + ], + }, + { + name: ['show'], + description: 'Show details for a specific extension.', + options: [ + { + name: ['--source', '-s'], + description: 'The extension source to use.', + args: [ + { + name: 'source', + }, + ], + }, + ], + args: { + name: 'extension-name', + }, + }, + { + name: ['source'], + description: 'View and manage extension sources', + subcommands: [ + { + name: ['add'], + description: 'Add an extension source with the specified name', + options: [ + { + name: ['--location', '-l'], + description: 'The location of the extension source', + args: [ + { + name: 'location', + }, + ], + }, + { + name: ['--name', '-n'], + description: 'The name of the extension source', + args: [ + { + name: 'name', + }, + ], + }, + { + name: ['--type', '-t'], + description: 'The type of the extension source. Supported types are \'file\' and \'url\'', + args: [ + { + name: 'type', + }, + ], + }, + ], + }, + { + name: ['list'], + description: 'List extension sources', + }, + { + name: ['remove'], + description: 'Remove an extension source with the specified name', + args: { + name: 'name', + }, + }, + ], + }, + { + name: ['uninstall'], + description: 'Uninstall specified extensions.', + options: [ + { + name: ['--all'], + description: 'Uninstall all installed extensions', + }, + ], + args: { + name: 'extension-id', + isOptional: true, + generators: azdGenerators.listInstalledExtensions, + }, + }, + { + name: ['upgrade'], + description: 'Upgrade specified extensions.', + options: [ + { + name: ['--all'], + description: 'Upgrade all installed extensions', + }, + { + name: ['--source', '-s'], + description: 'The extension source to use for upgrades', + args: [ + { + name: 'source', + }, + ], + }, + { + name: ['--version', '-v'], + description: 'The version of the extension to upgrade to', + args: [ + { + name: 'version', + }, + ], + }, + ], + args: { + name: 'extension-id', + isOptional: true, + generators: azdGenerators.listInstalledExtensions, + }, + }, + ], + }, + { + name: ['hooks'], + description: 'Develop, test and run hooks for a project.', + subcommands: [ + { + name: ['run'], + description: 'Runs the specified hook for the project and services', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--platform'], + description: 'Forces hooks to run for the specified platform.', + args: [ + { + name: 'platform', + }, + ], + }, + { + name: ['--service'], + description: 'Only runs hooks for the specified service.', + args: [ + { + name: 'service', + }, + ], + }, + ], + args: { + name: 'name', + suggestions: [ + 'prebuild', + 'postbuild', + 'predeploy', + 'postdeploy', + 'predown', + 'postdown', + 'prepackage', + 'postpackage', + 'preprovision', + 'postprovision', + 'prepublish', + 'postpublish', + 'prerestore', + 'postrestore', + 'preup', + 'postup', + ], + }, + }, + ], + }, + { + name: ['infra'], + description: 'Manage your Infrastructure as Code (IaC).', + subcommands: [ + { + name: ['generate', 'gen', 'synth'], + description: 'Write IaC for your project to disk, allowing you to manually manage it.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--force'], + description: 'Overwrite any existing files without prompting', + isDangerous: true, + }, + ], + }, + ], + }, + { + name: ['init'], + description: 'Initialize a new application.', + options: [ + { + name: ['--branch', '-b'], + description: 'The template branch to initialize from. Must be used with a template argument (--template or -t).', + args: [ + { + name: 'branch', + }, + ], + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--filter', '-f'], + description: 'The tag(s) used to filter template results. Supports comma-separated values.', + isRepeatable: true, + args: [ + { + name: 'filter', + generators: azdGenerators.listTemplateTags, + }, + ], + }, + { + name: ['--from-code'], + description: 'Initializes a new application from your existing code.', + }, + { + name: ['--location', '-l'], + description: 'Azure location for the new environment', + args: [ + { + name: 'location', + }, + ], + }, + { + name: ['--minimal', '-m'], + description: 'Initializes a minimal project.', + }, + { + name: ['--subscription', '-s'], + description: 'Name or ID of an Azure subscription to use for the new environment', + args: [ + { + name: 'subscription', + }, + ], + }, + { + name: ['--template', '-t'], + description: 'Initializes a new application from a template. You can use Full URI, /, or if it\'s part of the azure-samples organization.', + args: [ + { + name: 'template', + generators: azdGenerators.listTemplatesFiltered, + }, + ], + }, + { + name: ['--up'], + description: 'Provision and deploy to Azure after initializing the project from a template.', + }, + ], + }, + { + name: ['mcp'], + description: 'Manage Model Context Protocol (MCP) server. (Alpha)', + subcommands: [ + { + name: ['consent'], + description: 'Manage MCP tool consent.', + subcommands: [ + { + name: ['grant'], + description: 'Grant consent trust rules.', + options: [ + { + name: ['--action'], + description: 'Action type: \'all\' or \'readonly\'', + args: [ + { + name: 'action', + suggestions: ['all', 'readonly'], + }, + ], + }, + { + name: ['--global'], + description: 'Apply globally to all servers', + }, + { + name: ['--operation'], + description: 'Operation type: \'tool\' or \'sampling\'', + args: [ + { + name: 'operation', + suggestions: ['tool', 'sampling'], + }, + ], + }, + { + name: ['--permission'], + description: 'Permission: \'allow\', \'deny\', or \'prompt\'', + args: [ + { + name: 'permission', + suggestions: ['allow', 'deny', 'prompt'], + }, + ], + }, + { + name: ['--scope'], + description: 'Rule scope: \'global\', or \'project\'', + args: [ + { + name: 'scope', + suggestions: ['global', 'project'], + }, + ], + }, + { + name: ['--server'], + description: 'Server name', + args: [ + { + name: 'server', + }, + ], + }, + { + name: ['--tool'], + description: 'Specific tool name (requires --server)', + args: [ + { + name: 'tool', + }, + ], + }, + ], + }, + { + name: ['list'], + description: 'List consent rules.', + options: [ + { + name: ['--action'], + description: 'Action type to filter by (readonly, any)', + args: [ + { + name: 'action', + suggestions: ['all', 'readonly'], + }, + ], + }, + { + name: ['--operation'], + description: 'Operation to filter by (tool, sampling)', + args: [ + { + name: 'operation', + suggestions: ['tool', 'sampling'], + }, + ], + }, + { + name: ['--permission'], + description: 'Permission to filter by (allow, deny, prompt)', + args: [ + { + name: 'permission', + suggestions: ['allow', 'deny', 'prompt'], + }, + ], + }, + { + name: ['--scope'], + description: 'Consent scope to filter by (global, project). If not specified, lists rules from all scopes.', + args: [ + { + name: 'scope', + suggestions: ['global', 'project'], + }, + ], + }, + { + name: ['--target'], + description: 'Specific target to operate on (server/tool format)', + args: [ + { + name: 'target', + }, + ], + }, + ], + }, + { + name: ['revoke'], + description: 'Revoke consent rules.', + options: [ + { + name: ['--action'], + description: 'Action type to filter by (readonly, any)', + args: [ + { + name: 'action', + suggestions: ['all', 'readonly'], + }, + ], + }, + { + name: ['--operation'], + description: 'Operation to filter by (tool, sampling)', + args: [ + { + name: 'operation', + suggestions: ['tool', 'sampling'], + }, + ], + }, + { + name: ['--permission'], + description: 'Permission to filter by (allow, deny, prompt)', + args: [ + { + name: 'permission', + suggestions: ['allow', 'deny', 'prompt'], + }, + ], + }, + { + name: ['--scope'], + description: 'Consent scope to filter by (global, project). If not specified, revokes rules from all scopes.', + args: [ + { + name: 'scope', + suggestions: ['global', 'project'], + }, + ], + }, + { + name: ['--target'], + description: 'Specific target to operate on (server/tool format)', + args: [ + { + name: 'target', + }, + ], + }, + ], + }, + ], + }, + { + name: ['start'], + description: 'Starts the MCP server.', + }, + ], + }, + { + name: ['monitor'], + description: 'Monitor a deployed project.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--live'], + description: 'Open a browser to Application Insights Live Metrics. Live Metrics is currently not supported for Python apps.', + }, + { + name: ['--logs'], + description: 'Open a browser to Application Insights Logs.', + }, + { + name: ['--overview'], + description: 'Open a browser to Application Insights Overview Dashboard.', + }, + ], + }, + { + name: ['package'], + description: 'Packages the project\'s code to be deployed to Azure.', + options: [ + { + name: ['--all'], + description: 'Packages all services that are listed in azure.yaml', + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--output-path'], + description: 'File or folder path where the generated packages will be saved.', + args: [ + { + name: 'output-path', + }, + ], + }, + ], + args: { + name: 'service', + isOptional: true, + }, + }, + { + name: ['pipeline'], + description: 'Manage and configure your deployment pipelines.', + subcommands: [ + { + name: ['config'], + description: 'Configure your deployment pipeline to connect securely to Azure. (Beta)', + options: [ + { + name: ['--applicationServiceManagementReference', '-m'], + description: 'Service Management Reference. References application or service contact information from a Service or Asset Management database. This value must be a Universally Unique Identifier (UUID). You can set this value globally by running azd config set pipeline.config.applicationServiceManagementReference .', + args: [ + { + name: 'applicationServiceManagementReference', + }, + ], + }, + { + name: ['--auth-type'], + description: 'The authentication type used between the pipeline provider and Azure for deployment (Only valid for GitHub provider). Valid values: federated, client-credentials.', + args: [ + { + name: 'auth-type', + suggestions: ['federated', 'client-credentials'], + }, + ], + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--principal-id'], + description: 'The client id of the service principal to use to grant access to Azure resources as part of the pipeline.', + args: [ + { + name: 'principal-id', + }, + ], + }, + { + name: ['--principal-name'], + description: 'The name of the service principal to use to grant access to Azure resources as part of the pipeline.', + args: [ + { + name: 'principal-name', + }, + ], + }, + { + name: ['--principal-role'], + description: 'The roles to assign to the service principal. By default the service principal will be granted the Contributor and User Access Administrator roles.', + isRepeatable: true, + args: [ + { + name: 'principal-role', + }, + ], + }, + { + name: ['--provider'], + description: 'The pipeline provider to use (github for Github Actions and azdo for Azure Pipelines).', + args: [ + { + name: 'provider', + suggestions: ['github', 'azdo'], + }, + ], + }, + { + name: ['--remote-name'], + description: 'The name of the git remote to configure the pipeline to run on.', + args: [ + { + name: 'remote-name', + }, + ], + }, + ], + }, + ], + }, + { + name: ['provision'], + description: 'Provision Azure resources for your project.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--no-state'], + description: '(Bicep only) Forces a fresh deployment based on current Bicep template files, ignoring any stored deployment state.', + }, + { + name: ['--preview'], + description: 'Preview changes to Azure resources.', + }, + ], + }, + { + name: ['publish'], + description: 'Publish a service to a container registry.', + options: [ + { + name: ['--all'], + description: 'Publishes all services that are listed in azure.yaml', + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--from-package'], + description: 'Publishes the service from a container image (image tag).', + args: [ + { + name: 'image-tag', + }, + ], + }, + { + name: ['--to'], + description: 'The target container image in the form \'[registry/]repository[:tag]\' to publish to.', + args: [ + { + name: 'image-tag', + }, + ], + }, + ], + args: { + name: 'service', + isOptional: true, + }, + }, + { + name: ['restore'], + description: 'Restores the project\'s dependencies.', + options: [ + { + name: ['--all'], + description: 'Restores all services that are listed in azure.yaml', + }, + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + ], + args: { + name: 'service', + isOptional: true, + }, + }, + { + name: ['show'], + description: 'Display information about your project and its resources.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + { + name: ['--show-secrets'], + description: 'Unmask secrets in output.', + isDangerous: true, + }, + ], + args: { + name: 'resource-name|resource-id', + isOptional: true, + }, + }, + { + name: ['template'], + description: 'Find and view template details.', + subcommands: [ + { + name: ['list', 'ls'], + description: 'Show list of sample azd templates. (Beta)', + options: [ + { + name: ['--filter', '-f'], + description: 'The tag(s) used to filter template results. Supports comma-separated values.', + isRepeatable: true, + args: [ + { + name: 'filter', + generators: azdGenerators.listTemplateTags, + }, + ], + }, + { + name: ['--source', '-s'], + description: 'Filters templates by source.', + args: [ + { + name: 'source', + }, + ], + }, + ], + }, + { + name: ['show'], + description: 'Show details for a given template. (Beta)', + args: { + name: 'template', + generators: azdGenerators.listTemplates, + }, + }, + { + name: ['source'], + description: 'View and manage template sources. (Beta)', + subcommands: [ + { + name: ['add'], + description: 'Adds an azd template source with the specified key. (Beta)', + options: [ + { + name: ['--location', '-l'], + description: 'Location of the template source. Required when using type flag.', + args: [ + { + name: 'location', + }, + ], + }, + { + name: ['--name', '-n'], + description: 'Display name of the template source.', + args: [ + { + name: 'name', + }, + ], + }, + { + name: ['--type', '-t'], + description: 'Kind of the template source. Supported types are \'file\', \'url\' and \'gh\'.', + args: [ + { + name: 'type', + }, + ], + }, + ], + args: { + name: 'key', + }, + }, + { + name: ['list', 'ls'], + description: 'Lists the configured azd template sources. (Beta)', + }, + { + name: ['remove'], + description: 'Removes the specified azd template source (Beta)', + args: { + name: 'key', + }, + }, + ], + }, + ], + }, + { + name: ['up'], + description: 'Provision and deploy your project to Azure with a single command.', + options: [ + { + name: ['--environment', '-e'], + description: 'The name of the environment to use.', + args: [ + { + name: 'environment', + }, + ], + }, + ], + }, + { + name: ['version'], + description: 'Print the version number of Azure Developer CLI.', + }, + { + name: ['help'], + description: 'Help about any command', + subcommands: [ + { + name: ['add'], + description: 'Add a component to your project.', + }, + { + name: ['auth'], + description: 'Authenticate with Azure.', + subcommands: [ + { + name: ['login'], + description: 'Log in to Azure.', + }, + { + name: ['logout'], + description: 'Log out of Azure.', + }, + ], + }, + { + name: ['completion'], + description: 'Generate shell completion scripts.', + subcommands: [ + { + name: ['bash'], + description: 'Generate bash completion script.', + }, + { + name: ['fig'], + description: 'Generate Fig autocomplete spec.', + }, + { + name: ['fish'], + description: 'Generate fish completion script.', + }, + { + name: ['powershell'], + description: 'Generate PowerShell completion script.', + }, + { + name: ['zsh'], + description: 'Generate zsh completion script.', + }, + ], + }, + { + name: ['config'], + description: 'Manage azd configurations (ex: default Azure subscription, location).', + subcommands: [ + { + name: ['get'], + description: 'Gets a configuration.', + }, + { + name: ['list-alpha'], + description: 'Display the list of available features in alpha stage.', + }, + { + name: ['reset'], + description: 'Resets configuration to default.', + }, + { + name: ['set'], + description: 'Sets a configuration.', + }, + { + name: ['show'], + description: 'Show all the configuration values.', + }, + { + name: ['unset'], + description: 'Unsets a configuration.', + }, + ], + }, + { + name: ['deploy'], + description: 'Deploy your project code to Azure.', + }, + { + name: ['down'], + description: 'Delete your project\'s Azure resources.', + }, + { + name: ['env'], + description: 'Manage environments (ex: default environment, environment variables).', + subcommands: [ + { + name: ['get-value'], + description: 'Get specific environment value.', + }, + { + name: ['get-values'], + description: 'Get all environment values.', + }, + { + name: ['list', 'ls'], + description: 'List environments.', + }, + { + name: ['new'], + description: 'Create a new environment and set it as the default.', + }, + { + name: ['refresh'], + description: 'Refresh environment values by using information from a previous infrastructure provision.', + }, + { + name: ['select'], + description: 'Set the default environment.', + }, + { + name: ['set'], + description: 'Set one or more environment values.', + }, + { + name: ['set-secret'], + description: 'Set a name as a reference to a Key Vault secret in the environment.', + }, + ], + }, + { + name: ['extension', 'ext'], + description: 'Manage azd extensions.', + subcommands: [ + { + name: ['install'], + description: 'Installs specified extensions.', + }, + { + name: ['list'], + description: 'List available extensions.', + }, + { + name: ['show'], + description: 'Show details for a specific extension.', + }, + { + name: ['source'], + description: 'View and manage extension sources', + subcommands: [ + { + name: ['add'], + description: 'Add an extension source with the specified name', + }, + { + name: ['list'], + description: 'List extension sources', + }, + { + name: ['remove'], + description: 'Remove an extension source with the specified name', + }, + ], + }, + { + name: ['uninstall'], + description: 'Uninstall specified extensions.', + }, + { + name: ['upgrade'], + description: 'Upgrade specified extensions.', + }, + ], + }, + { + name: ['hooks'], + description: 'Develop, test and run hooks for a project.', + subcommands: [ + { + name: ['run'], + description: 'Runs the specified hook for the project and services', + }, + ], + }, + { + name: ['infra'], + description: 'Manage your Infrastructure as Code (IaC).', + subcommands: [ + { + name: ['generate', 'gen', 'synth'], + description: 'Write IaC for your project to disk, allowing you to manually manage it.', + }, + ], + }, + { + name: ['init'], + description: 'Initialize a new application.', + }, + { + name: ['mcp'], + description: 'Manage Model Context Protocol (MCP) server. (Alpha)', + subcommands: [ + { + name: ['consent'], + description: 'Manage MCP tool consent.', + subcommands: [ + { + name: ['grant'], + description: 'Grant consent trust rules.', + }, + { + name: ['list'], + description: 'List consent rules.', + }, + { + name: ['revoke'], + description: 'Revoke consent rules.', + }, + ], + }, + { + name: ['start'], + description: 'Starts the MCP server.', + }, + ], + }, + { + name: ['monitor'], + description: 'Monitor a deployed project.', + }, + { + name: ['package'], + description: 'Packages the project\'s code to be deployed to Azure.', + }, + { + name: ['pipeline'], + description: 'Manage and configure your deployment pipelines.', + subcommands: [ + { + name: ['config'], + description: 'Configure your deployment pipeline to connect securely to Azure. (Beta)', + }, + ], + }, + { + name: ['provision'], + description: 'Provision Azure resources for your project.', + }, + { + name: ['publish'], + description: 'Publish a service to a container registry.', + }, + { + name: ['restore'], + description: 'Restores the project\'s dependencies.', + }, + { + name: ['show'], + description: 'Display information about your project and its resources.', + }, + { + name: ['template'], + description: 'Find and view template details.', + subcommands: [ + { + name: ['list', 'ls'], + description: 'Show list of sample azd templates. (Beta)', + }, + { + name: ['show'], + description: 'Show details for a given template. (Beta)', + }, + { + name: ['source'], + description: 'View and manage template sources. (Beta)', + subcommands: [ + { + name: ['add'], + description: 'Adds an azd template source with the specified key. (Beta)', + }, + { + name: ['list', 'ls'], + description: 'Lists the configured azd template sources. (Beta)', + }, + { + name: ['remove'], + description: 'Removes the specified azd template source (Beta)', + }, + ], + }, + ], + }, + { + name: ['up'], + description: 'Provision and deploy your project to Azure with a single command.', + }, + { + name: ['version'], + description: 'Print the version number of Azure Developer CLI.', + }, + ], + }, + ], + options: [ + { + name: ['--cwd', '-C'], + description: 'Sets the current working directory.', + isPersistent: true, + args: [ + { + name: 'cwd', + }, + ], + }, + { + name: ['--debug'], + description: 'Enables debugging and diagnostics logging.', + isPersistent: true, + }, + { + name: ['--no-prompt'], + description: 'Accepts the default value instead of prompting, or it fails if there is no default.', + isPersistent: true, + }, + { + name: ['--docs'], + description: 'Opens the documentation for azd in your web browser.', + isPersistent: true, + }, + { + name: ['--help', '-h'], + description: 'Gets help for azd.', + isPersistent: true, + }, + ], +}; + +export default completionSpec; diff --git a/extensions/terminal-suggest/src/completions/copilot.ts b/extensions/terminal-suggest/src/completions/copilot.ts new file mode 100644 index 00000000000..6457479e708 --- /dev/null +++ b/extensions/terminal-suggest/src/completions/copilot.ts @@ -0,0 +1,164 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +const copilotSpec: Fig.Spec = { + name: 'copilot', + description: 'GitHub Copilot CLI - An AI-powered coding assistant', + options: [ + { + name: '--add-dir', + description: 'Add a directory to the allowed list for file access (can be used multiple times)', + args: { + name: 'directory', + template: 'folders' + }, + isRepeatable: true + }, + { + name: '--additional-mcp-config', + description: 'Additional MCP servers configuration as JSON string or file path (prefix with @)', + args: { + name: 'json', + description: 'JSON string or file path (prefix with @)' + }, + isRepeatable: true + }, + { + name: '--allow-all-paths', + description: 'Disable file path verification and allow access to any path' + }, + { + name: '--allow-all-tools', + description: 'Allow all tools to run automatically without confirmation; required for non-interactive mode' + }, + { + name: '--allow-tool', + description: 'Allow specific tools', + args: { + name: 'tools', + isVariadic: true, + isOptional: true + } + }, + { + name: '--banner', + description: 'Show the startup banner' + }, + { + name: '--continue', + description: 'Resume the most recent session' + }, + { + name: '--deny-tool', + description: 'Deny specific tools, takes precedence over --allow-tool or --allow-all-tools', + args: { + name: 'tools', + isVariadic: true, + isOptional: true + } + }, + { + name: '--disable-builtin-mcps', + description: 'Disable all built-in MCP servers (currently: github-mcp-server)' + }, + { + name: '--disable-mcp-server', + description: 'Disable a specific MCP server (can be used multiple times)', + args: { + name: 'server-name' + }, + isRepeatable: true + }, + { + name: '--disable-parallel-tools-execution', + description: 'Disable parallel execution of tools (LLM can still make parallel tool calls, but they will be executed sequentially)' + }, + { + name: '--disallow-temp-dir', + description: 'Prevent automatic access to the system temporary directory' + }, + { + name: ['-h', '--help'], + description: 'Display help for command' + }, + { + name: '--log-dir', + description: 'Set log file directory (default: ~/.copilot/logs/)', + args: { + name: 'directory', + template: 'folders' + } + }, + { + name: '--log-level', + description: 'Set the log level', + args: { + name: 'level', + suggestions: ['none', 'error', 'warning', 'info', 'debug', 'all', 'default'] + } + }, + { + name: '--model', + description: 'Set the AI model to use', + args: { + name: 'model', + suggestions: ['claude-sonnet-4.5', 'claude-sonnet-4', 'claude-haiku-4.5', 'gpt-5'] + } + }, + { + name: '--no-color', + description: 'Disable all color output' + }, + { + name: '--no-custom-instructions', + description: 'Disable loading of custom instructions from AGENTS.md and related files' + }, + { + name: ['-p', '--prompt'], + description: 'Execute a prompt directly without interactive mode', + args: { + name: 'text', + description: 'The prompt text to execute' + } + }, + { + name: '--resume', + description: 'Resume from a previous session (optionally specify session ID)', + args: { + name: 'sessionId', + isOptional: true + } + }, + { + name: '--screen-reader', + description: 'Enable screen reader optimizations' + }, + { + name: '--stream', + description: 'Enable or disable streaming mode', + args: { + name: 'mode', + suggestions: ['on', 'off'] + } + }, + { + name: ['-v', '--version'], + description: 'Show version information' + } + ], + subcommands: [ + { + name: 'help', + description: 'Display help information', + args: { + name: 'topic', + isOptional: true, + suggestions: ['config', 'commands', 'environment', 'logging', 'permissions'] + } + } + ] +}; + +export default copilotSpec; diff --git a/extensions/terminal-suggest/src/completions/git.ts b/extensions/terminal-suggest/src/completions/git.ts index 7c0f74fb843..21beac98c0c 100644 --- a/extensions/terminal-suggest/src/completions/git.ts +++ b/extensions/terminal-suggest/src/completions/git.ts @@ -74,46 +74,67 @@ const postProcessBranches = const seen = new Set(); return output .split("\n") - .filter((line) => !line.trim().startsWith("HEAD")) + .filter((line) => line.trim() && !line.trim().startsWith("HEAD")) .map((branch) => { - let name = branch.trim(); - const parts = branch.match(/\S+/g); - if (parts && parts.length > 1) { - if (parts[0] === "*") { - // We are in a detached HEAD state - if (branch.includes("HEAD detached")) { - return null; + // Parse the format: branchName|author|hash|subject|timeAgo + const parts = branch.split("|"); + if (parts.length < 5) { + // Fallback to old parsing if format doesn't match + let name = branch.trim(); + const oldParts = branch.match(/\S+/g); + if (oldParts && oldParts.length > 1) { + if (oldParts[0] === "*") { + if (branch.includes("HEAD detached")) { + return null; + } + return { + name: branch.replaceAll("*", "").trim(), + description: "Current branch", + priority: 100, + icon: `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}` + }; + } else if (oldParts[0] === "+") { + name = branch.replaceAll("+", "").trim(); } - // Current branch - return { - name: branch.replace("*", "").trim(), - description: "Current branch", - priority: 100, - icon: `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}` - }; - } else if (parts[0] === "+") { - // Branch checked out in another worktree. - name = branch.replace("+", "").trim(); } + + let description = "Branch"; + if (insertWithoutRemotes && name.startsWith("remotes/")) { + name = name.slice(name.indexOf("/", 8) + 1); + description = "Remote branch"; + } + + const space = name.indexOf(" "); + if (space !== -1) { + name = name.slice(0, space); + } + + return { + name, + description, + icon: `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}`, + priority: 75, + }; } - let description = "Branch"; + let name = parts[0].trim(); + const author = parts[1].trim(); + const hash = parts[2].trim(); + const subject = parts[3].trim(); + const timeAgo = parts[4].trim(); + + const description = `${timeAgo} • ${author} • ${hash} • ${subject}`; + const priority = 75; if (insertWithoutRemotes && name.startsWith("remotes/")) { name = name.slice(name.indexOf("/", 8) + 1); - description = "Remote branch"; - } - - const space = name.indexOf(" "); - if (space !== -1) { - name = name.slice(0, space); } return { name, description, icon: `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}`, - priority: 75, + priority, }; }) .filter((suggestion) => { @@ -128,6 +149,15 @@ const postProcessBranches = }); }; +// Common git for-each-ref arguments for branch queries with commit details +const gitBranchForEachRefArgs = [ + "git", + "--no-optional-locks", + "for-each-ref", + "--sort=-committerdate", + "--format=%(refname:short)|%(authorname)|%(objectname:short)|%(subject)|%(committerdate:relative)", +] as const; + export const gitGenerators = { // Commit history commits: { @@ -252,23 +282,17 @@ export const gitGenerators = { // All branches remoteLocalBranches: { script: [ - "git", - "--no-optional-locks", - "branch", - "-a", - "--no-color", - "--sort=-committerdate", + ...gitBranchForEachRefArgs, + "refs/heads/", + "refs/remotes/", ], postProcess: postProcessBranches({ insertWithoutRemotes: true }), } satisfies Fig.Generator, localBranches: { script: [ - "git", - "--no-optional-locks", - "branch", - "--no-color", - "--sort=-committerdate", + ...gitBranchForEachRefArgs, + "refs/heads/", ], postProcess: postProcessBranches({ insertWithoutRemotes: true }), } satisfies Fig.Generator, @@ -278,37 +302,19 @@ export const gitGenerators = { localOrRemoteBranches: { custom: async (tokens, executeShellCommand) => { const pp = postProcessBranches({ insertWithoutRemotes: true }); - if (tokens.includes("-r")) { - return pp?.( - ( - await executeShellCommand({ - command: "git", - args: [ - "--no-optional-locks", - "-r", - "--no-color", - "--sort=-committerdate", - ], - }) - ).stdout, - tokens - ); - } else { - return pp?.( - ( - await executeShellCommand({ - command: "git", - args: [ - "--no-optional-locks", - "branch", - "--no-color", - "--sort=-committerdate", - ], - }) - ).stdout, - tokens - ); - } + const refs = tokens.includes("-r") ? "refs/remotes/" : "refs/heads/"; + return pp?.( + ( + await executeShellCommand({ + command: gitBranchForEachRefArgs[0], + args: [ + ...gitBranchForEachRefArgs.slice(1), + refs, + ], + }) + ).stdout, + tokens + ); }, } satisfies Fig.Generator, @@ -6450,7 +6456,7 @@ const completionSpec: Fig.Spec = { }, { name: ["rm", "remove"], - description: "Removes given remote [name]", + description: "Removes the given remote", args: { name: "remote", generators: gitGenerators.remotes, @@ -6459,7 +6465,7 @@ const completionSpec: Fig.Spec = { }, { name: "rename", - description: "Removes given remote [name]", + description: "Renames the given remote", args: [ { name: "old remote", diff --git a/extensions/terminal-suggest/src/env/pathExecutableCache.ts b/extensions/terminal-suggest/src/env/pathExecutableCache.ts index 6576bb59894..9ca3d0ea588 100644 --- a/extensions/terminal-suggest/src/env/pathExecutableCache.ts +++ b/extensions/terminal-suggest/src/env/pathExecutableCache.ts @@ -10,8 +10,6 @@ import { osIsWindows } from '../helpers/os'; import type { ICompletionResource } from '../types'; import { getFriendlyResourcePath } from '../helpers/uri'; import { SettingsIds } from '../constants'; -import * as filesystem from 'fs'; -import * as path from 'path'; import { TerminalShellType } from '../terminalSuggestMain'; const isWindows = osIsWindows(); @@ -220,46 +218,4 @@ export class PathExecutableCache implements vscode.Disposable { } } -export async function watchPathDirectories(context: vscode.ExtensionContext, env: ITerminalEnvironment, pathExecutableCache: PathExecutableCache | undefined): Promise { - const pathDirectories = new Set(); - - const envPath = env.PATH; - if (envPath) { - envPath.split(path.delimiter).forEach(p => pathDirectories.add(p)); - } - - const activeWatchers = new Set(); - - // Watch each directory - for (const dir of pathDirectories) { - try { - if (activeWatchers.has(dir)) { - // Skip if already watching or directory doesn't exist - continue; - } - - const stat = await fs.stat(dir); - if (!stat.isDirectory()) { - continue; - } - - const watcher = filesystem.watch(dir, { persistent: false }, () => { - if (pathExecutableCache) { - // Refresh cache when directory contents change - pathExecutableCache.refresh(dir); - } - }); - - activeWatchers.add(dir); - - context.subscriptions.push(new vscode.Disposable(() => { - try { - watcher.close(); - activeWatchers.delete(dir); - } catch { } { } - })); - } catch { } - } -} - export type ITerminalEnvironment = { [key: string]: string | undefined }; diff --git a/extensions/terminal-suggest/src/fig/figInterface.ts b/extensions/terminal-suggest/src/fig/figInterface.ts index 387eaa340ef..a3b8db665a7 100644 --- a/extensions/terminal-suggest/src/fig/figInterface.ts +++ b/extensions/terminal-suggest/src/fig/figInterface.ts @@ -341,6 +341,7 @@ export async function collectCompletionItemResult( } if (parsedArguments.suggestionFlags & SuggestionFlag.Options) { await addSuggestions(parsedArguments.completionObj.options, vscode.TerminalCompletionItemKind.Flag, parsedArguments); + await addSuggestions(parsedArguments.completionObj.persistentOptions, vscode.TerminalCompletionItemKind.Flag, parsedArguments); } return { showFiles, showFolders, fileExtensions }; diff --git a/extensions/terminal-suggest/src/fig/shell-parser/test/command.test.ts b/extensions/terminal-suggest/src/fig/shell-parser/test/command.test.ts index cc050512374..46d22dd6533 100644 --- a/extensions/terminal-suggest/src/fig/shell-parser/test/command.test.ts +++ b/extensions/terminal-suggest/src/fig/shell-parser/test/command.test.ts @@ -4,35 +4,35 @@ *--------------------------------------------------------------------------------------------*/ import { deepStrictEqual } from 'node:assert'; -import { getCommand, Command } from "../command"; +import { getCommand, Command } from '../command'; -suite("fig/shell-parser/ getCommand", () => { +suite('fig/shell-parser/ getCommand', () => { const aliases = { - woman: "man", - quote: "'q'", - g: "git", + woman: 'man', + quote: `'q'`, + g: 'git', }; const getTokenText = (command: Command | null) => command?.tokens.map((token) => token.text) ?? []; - test("works without matching aliases", () => { - deepStrictEqual(getTokenText(getCommand("git co ", {})), ["git", "co", ""]); - deepStrictEqual(getTokenText(getCommand("git co ", aliases)), ["git", "co", ""]); - deepStrictEqual(getTokenText(getCommand("woman ", {})), ["woman", ""]); - deepStrictEqual(getTokenText(getCommand("another string ", aliases)), [ - "another", - "string", - "", + test('works without matching aliases', () => { + deepStrictEqual(getTokenText(getCommand('git co ', {})), ['git', 'co', '']); + deepStrictEqual(getTokenText(getCommand('git co ', aliases)), ['git', 'co', '']); + deepStrictEqual(getTokenText(getCommand('woman ', {})), ['woman', '']); + deepStrictEqual(getTokenText(getCommand('another string ', aliases)), [ + 'another', + 'string', + '', ]); }); - test("works with regular aliases", () => { + test('works with regular aliases', () => { // Don't change a single token. - deepStrictEqual(getTokenText(getCommand("woman", aliases)), ["woman"]); + deepStrictEqual(getTokenText(getCommand('woman', aliases)), ['woman']); // Change first token if length > 1. - deepStrictEqual(getTokenText(getCommand("woman ", aliases)), ["man", ""]); + deepStrictEqual(getTokenText(getCommand('woman ', aliases)), ['man', '']); // Don't change later tokens. - deepStrictEqual(getTokenText(getCommand("man woman ", aliases)), ["man", "woman", ""]); + deepStrictEqual(getTokenText(getCommand('man woman ', aliases)), ['man', 'woman', '']); // Handle quotes - deepStrictEqual(getTokenText(getCommand("quote ", aliases)), ["q", ""]); + deepStrictEqual(getTokenText(getCommand('quote ', aliases)), ['q', '']); }); }); diff --git a/extensions/terminal-suggest/src/helpers/completionItem.ts b/extensions/terminal-suggest/src/helpers/completionItem.ts index 7cb174223c1..b5dba9a2874 100644 --- a/extensions/terminal-suggest/src/helpers/completionItem.ts +++ b/extensions/terminal-suggest/src/helpers/completionItem.ts @@ -13,8 +13,7 @@ export function createCompletionItem(cursorPosition: number, currentCommandStrin label: commandResource.label, detail: detail ?? commandResource.detail ?? '', documentation, - replacementIndex: cursorPosition - lastWord.length, - replacementLength: lastWord.length, + replacementRange: [cursorPosition - lastWord.length, cursorPosition], kind: kind ?? commandResource.kind ?? vscode.TerminalCompletionItemKind.Method }; } diff --git a/extensions/terminal-suggest/src/terminalSuggestMain.ts b/extensions/terminal-suggest/src/terminalSuggestMain.ts index 45805d9def4..0b379eb57f8 100644 --- a/extensions/terminal-suggest/src/terminalSuggestMain.ts +++ b/extensions/terminal-suggest/src/terminalSuggestMain.ts @@ -4,18 +4,22 @@ *--------------------------------------------------------------------------------------------*/ import { ExecOptionsWithStringEncoding } from 'child_process'; +import * as fs from 'fs'; +import { basename, delimiter } from 'path'; import * as vscode from 'vscode'; +import azdSpec from './completions/azd'; import cdSpec from './completions/cd'; import codeCompletionSpec from './completions/code'; import codeInsidersCompletionSpec from './completions/code-insiders'; import codeTunnelCompletionSpec from './completions/code-tunnel'; import codeTunnelInsidersCompletionSpec from './completions/code-tunnel-insiders'; +import copilotSpec from './completions/copilot'; import gitCompletionSpec from './completions/git'; import ghCompletionSpec from './completions/gh'; import npxCompletionSpec from './completions/npx'; import setLocationSpec from './completions/set-location'; import { upstreamSpecs } from './constants'; -import { ITerminalEnvironment, PathExecutableCache, watchPathDirectories } from './env/pathExecutableCache'; +import { ITerminalEnvironment, PathExecutableCache } from './env/pathExecutableCache'; import { executeCommand, executeCommandTimeout, IFigExecuteExternals } from './fig/execute'; import { getFigSuggestions } from './fig/figInterface'; import { createCompletionItem } from './helpers/completionItem'; @@ -28,8 +32,6 @@ import { getPwshGlobals } from './shell/pwsh'; import { getZshGlobals } from './shell/zsh'; import { defaultShellTypeResetChars, getTokenType, shellTypeResetChars, TokenType } from './tokens'; import type { ICompletionResource } from './types'; -import { basename } from 'path'; - export const enum TerminalShellType { Bash = 'bash', Fish = 'fish', @@ -58,11 +60,13 @@ function getCacheKey(machineId: string, remoteAuthority: string | undefined, she } export const availableSpecs: Fig.Spec[] = [ + azdSpec, cdSpec, codeInsidersCompletionSpec, codeCompletionSpec, codeTunnelCompletionSpec, codeTunnelInsidersCompletionSpec, + copilotSpec, gitCompletionSpec, ghCompletionSpec, npxCompletionSpec, @@ -317,13 +321,63 @@ export async function activate(context: vscode.ExtensionContext) { return result.items; } }, '/', '\\')); - await watchPathDirectories(context, currentTerminalEnv, pathExecutableCache); + watchPathDirectories(context, currentTerminalEnv, pathExecutableCache); context.subscriptions.push(vscode.commands.registerCommand('terminal.integrated.suggest.clearCachedGlobals', () => { cachedGlobals.clear(); })); } +async function watchPathDirectories(context: vscode.ExtensionContext, env: ITerminalEnvironment, pathExecutableCache: PathExecutableCache | undefined): Promise { + const pathDirectories = new Set(); + + const envPath = env.PATH; + if (envPath) { + envPath.split(delimiter).forEach(p => pathDirectories.add(p)); + } + + const activeWatchers = new Set(); + + let debounceTimer: NodeJS.Timeout | undefined; // debounce in case many file events fire at once + function handleChange() { + if (debounceTimer) { + clearTimeout(debounceTimer); + } + debounceTimer = setTimeout(() => { + pathExecutableCache?.refresh(); + debounceTimer = undefined; + }, 300); + } + + // Watch each directory + for (const dir of pathDirectories) { + if (activeWatchers.has(dir)) { + // Skip if already watching this directory + continue; + } + + try { + const stat = await fs.promises.stat(dir); + if (!stat.isDirectory()) { + continue; + } + } catch { + // File not found + continue; + } + + const watcher = vscode.workspace.createFileSystemWatcher(new vscode.RelativePattern(vscode.Uri.file(dir), '*')); + context.subscriptions.push( + watcher, + watcher.onDidCreate(() => handleChange()), + watcher.onDidChange(() => handleChange()), + watcher.onDidDelete(() => handleChange()) + ); + + activeWatchers.add(dir); + } +} + /** * Adjusts the current working directory based on a given current command string if it is a folder. * @param currentCommandString - The current command string, which might contain a folder path prefix. @@ -493,13 +547,9 @@ export async function getCompletionItemsFromSpecs( } showFiles = true; showFolders = true; - } - // For arguments when no fig suggestions are found these are fallback suggestions - else if (!items.length && !showFiles && !showFolders && !hasCurrentArg) { - if (terminalContext.allowFallbackCompletions) { - showFiles = true; - showFolders = true; - } + } else if (!items.length && !showFiles && !showFolders && !hasCurrentArg) { + showFiles = true; + showFolders = true; } let cwd: vscode.Uri | undefined; @@ -507,7 +557,7 @@ export async function getCompletionItemsFromSpecs( cwd = await resolveCwdFromCurrentCommandString(currentCommandString, shellIntegrationCwd); } - return { items, showFiles: showFiles, showFolders: showFolders, fileExtensions, cwd }; + return { items, showFiles, showFolders, fileExtensions, cwd }; } function getEnvAsRecord(shellIntegrationEnv: ITerminalEnvironment): Record { diff --git a/extensions/terminal-suggest/src/test/completions/git-branch.test.ts b/extensions/terminal-suggest/src/test/completions/git-branch.test.ts new file mode 100644 index 00000000000..20d140c3e7c --- /dev/null +++ b/extensions/terminal-suggest/src/test/completions/git-branch.test.ts @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import 'mocha'; +import * as vscode from 'vscode'; +import { gitGenerators } from '../../completions/git'; + +suite('Git Branch Completions', () => { + test('postProcessBranches should parse git for-each-ref output with commit details', () => { + const input = `main|John Doe|abc1234|Fix response codeblock in debug view|2 days ago +feature/test|Jane Smith|def5678|Add new feature|1 week ago`; + + const result = gitGenerators.localBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 2); + assert.ok(result[0]); + assert.strictEqual(result[0].name, 'main'); + assert.strictEqual(result[0].description, '2 days ago • John Doe • abc1234 • Fix response codeblock in debug view'); + assert.strictEqual(result[0].icon, `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}`); + + assert.ok(result[1]); + assert.strictEqual(result[1].name, 'feature/test'); + assert.strictEqual(result[1].description, '1 week ago • Jane Smith • def5678 • Add new feature'); + assert.strictEqual(result[1].icon, `vscode://icon?type=${vscode.TerminalCompletionItemKind.ScmBranch}`); + }); + + test('postProcessBranches should handle remote branches', () => { + const input = `remotes/origin/main|John Doe|abc1234|Fix bug|2 days ago +remotes/origin/feature|Jane Smith|def5678|Add feature|1 week ago`; + + const result = gitGenerators.remoteLocalBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 2); + assert.ok(result[0]); + assert.strictEqual(result[0].name, 'main'); + assert.strictEqual(result[0].description, '2 days ago • John Doe • abc1234 • Fix bug'); + + assert.ok(result[1]); + assert.strictEqual(result[1].name, 'feature'); + assert.strictEqual(result[1].description, '1 week ago • Jane Smith • def5678 • Add feature'); + }); + + test('postProcessBranches should filter out HEAD branches', () => { + const input = `main|John Doe|abc1234|Fix bug|2 days ago +HEAD -> main|John Doe|abc1234|Fix bug|2 days ago`; + + const result = gitGenerators.localBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 1); + assert.ok(result[0]); + assert.strictEqual(result[0].name, 'main'); + }); + + test('postProcessBranches should handle empty input', () => { + const input = ''; + + const result = gitGenerators.localBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 0); + }); + + test('postProcessBranches should handle git error output', () => { + const input = 'fatal: not a git repository'; + + const result = gitGenerators.localBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 0); + }); + + test('postProcessBranches should deduplicate branches', () => { + const input = `main|John Doe|abc1234|Fix bug|2 days ago +main|John Doe|abc1234|Fix bug|2 days ago`; + + const result = gitGenerators.localBranches.postProcess!(input, []); + + assert.ok(result); + assert.strictEqual(result.length, 1); + assert.ok(result[0]); + assert.strictEqual(result[0].name, 'main'); + }); +}); diff --git a/extensions/terminal-suggest/src/test/fig.test.ts b/extensions/terminal-suggest/src/test/fig.test.ts index b8144219e88..c3aeee4fcf1 100644 --- a/extensions/terminal-suggest/src/test/fig.test.ts +++ b/extensions/terminal-suggest/src/test/fig.test.ts @@ -183,6 +183,56 @@ export const figGenericTestSuites: ISuiteSpec[] = [ { input: 'foo b|', expectedCompletions: ['b', 'foo'] }, { input: 'foo c|', expectedCompletions: ['c', 'foo'] }, ] + }, + { + name: 'Fig persistent options', + completionSpecs: [ + { + name: 'foo', + description: 'Foo', + options: [ + { name: '--help', description: 'Show help', isPersistent: true }, + { name: '--docs', description: 'Show docs' }, + { name: '--version', description: 'Version info', isPersistent: false } + ], + subcommands: [ + { + name: 'bar', + description: 'Bar subcommand', + options: [ + { name: '--local', description: 'Local option' } + ] + }, + { + name: 'baz', + description: 'Baz subcommand', + options: [ + { name: '--another', description: 'Another option' } + ], + subcommands: [ + { + name: 'nested', + description: 'Nested subcommand' + } + ] + } + ] + } + ], + availableCommands: 'foo', + testSpecs: [ + // Top-level should show all options including persistent + { input: 'foo |', expectedCompletions: ['--help', '--docs', '--version', 'bar', 'baz'] }, + // First-level subcommand should only inherit persistent options (not --docs or --version) + { input: 'foo bar |', expectedCompletions: ['--help', '--local'] }, + // Another first-level subcommand should also inherit only persistent options + { input: 'foo baz |', expectedCompletions: ['--help', '--another', 'nested'] }, + // Nested subcommand should inherit persistent options from top level + { input: 'foo baz nested |', expectedCompletions: ['--help'] }, + // Persistent options should be available even after using local options + { input: 'foo bar --local |', expectedCompletions: ['--help'] }, + ] } ]; + diff --git a/extensions/terminal-suggest/src/test/terminalSuggestMain.test.ts b/extensions/terminal-suggest/src/test/terminalSuggestMain.test.ts index e60099c6089..cb4cbbddd5d 100644 --- a/extensions/terminal-suggest/src/test/terminalSuggestMain.test.ts +++ b/extensions/terminal-suggest/src/test/terminalSuggestMain.test.ts @@ -95,7 +95,7 @@ suite('Terminal Suggest', () => { const currentCommandString = getCurrentCommandAndArgs(commandLine, cursorIndex, undefined); const showFiles = testSpec.expectedResourceRequests?.type === 'files' || testSpec.expectedResourceRequests?.type === 'both'; const showFolders = testSpec.expectedResourceRequests?.type === 'folders' || testSpec.expectedResourceRequests?.type === 'both'; - const terminalContext = { commandLine, cursorIndex, allowFallbackCompletions: true }; + const terminalContext = { commandLine, cursorIndex }; const result = await getCompletionItemsFromSpecs( completionSpecs, terminalContext, diff --git a/extensions/theme-defaults/themes/dark_plus.json b/extensions/theme-defaults/themes/dark_plus.json index 29a82195861..8328860a9ff 100644 --- a/extensions/theme-defaults/themes/dark_plus.json +++ b/extensions/theme-defaults/themes/dark_plus.json @@ -83,7 +83,7 @@ "entity.name.operator" ], "settings": { - "foreground": "#CE92A4" + "foreground": "#C586C0" } }, { @@ -197,7 +197,7 @@ } ], "semanticTokenColors": { - "newOperator":"#CE92A4", + "newOperator":"#C586C0", "stringLiteral":"#ce9178", "customLiteral": "#DCDCAA", "numberLiteral": "#b5cea8", diff --git a/extensions/theme-seti/cgmanifest.json b/extensions/theme-seti/cgmanifest.json index 6d2b5fb51c7..0a12c2c7baa 100644 --- a/extensions/theme-seti/cgmanifest.json +++ b/extensions/theme-seti/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "seti-ui", "repositoryUrl": "https://github.com/jesseweed/seti-ui", - "commitHash": "1cac4f30f93cc898103c62dde41823a09b0d7b74" + "commitHash": "2d6c5e68b4ded73c92dac291845ee44e1182d511" } }, "version": "0.1.0" diff --git a/extensions/theme-seti/icons/seti.woff b/extensions/theme-seti/icons/seti.woff index edc69c7cf89..6a8a3da7cf0 100644 Binary files a/extensions/theme-seti/icons/seti.woff and b/extensions/theme-seti/icons/seti.woff differ diff --git a/extensions/theme-seti/icons/vs-seti-icon-theme.json b/extensions/theme-seti/icons/vs-seti-icon-theme.json index 444f22780b4..f7c55c96d9e 100644 --- a/extensions/theme-seti/icons/vs-seti-icon-theme.json +++ b/extensions/theme-seti/icons/vs-seti-icon-theme.json @@ -1784,7 +1784,6 @@ "stylelintrc.js": "_stylelint", "stylelintignore": "_stylelint_1", "direnv": "_config", - "env": "_config", "static": "_config", "slugignore": "_config", "tmp": "_clock_1", @@ -1912,6 +1911,7 @@ "css": "_css", "dart": "_dart", "dockerfile": "_docker", + "dotenv": "_config", "ignore": "_git", "fsharp": "_f-sharp", "git-commit": "_git", @@ -2210,7 +2210,6 @@ "stylelintrc.js": "_stylelint_light", "stylelintignore": "_stylelint_1_light", "direnv": "_config_light", - "env": "_config_light", "static": "_config_light", "slugignore": "_config_light", "tmp": "_clock_1_light", @@ -2235,6 +2234,7 @@ "css": "_css_light", "dart": "_dart_light", "dockerfile": "_docker_light", + "dotenv": "_config_light", "ignore": "_git_light", "fsharp": "_f-sharp_light", "git-commit": "_git_light", @@ -2402,5 +2402,5 @@ "npm-debug.log": "_npm_ignored_light" } }, - "version": "https://github.com/jesseweed/seti-ui/commit/1cac4f30f93cc898103c62dde41823a09b0d7b74" + "version": "https://github.com/jesseweed/seti-ui/commit/2d6c5e68b4ded73c92dac291845ee44e1182d511" } \ No newline at end of file diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index b48ba9ea67a..b4706482fb6 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -53,7 +53,7 @@ "@types/semver": "^5.5.0" }, "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:typescript-language-features", + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:typescript-language-features", "compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none", "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch" }, @@ -218,6 +218,12 @@ "description": "%typescript.implementationsCodeLens.showOnInterfaceMethods%", "scope": "window" }, + "typescript.implementationsCodeLens.showOnAllClassMethods": { + "type": "boolean", + "default": false, + "description": "%typescript.implementationsCodeLens.showOnAllClassMethods%", + "scope": "window" + }, "typescript.reportStyleChecksAsWarnings": { "type": "boolean", "default": true, @@ -1632,7 +1638,7 @@ }, { "command": "typescript.goToProjectConfig", - "when": "editorLangId == typescriptreact" + "when": "editorLangId == typescriptreact && typescript.isManagedFile" }, { "command": "javascript.goToProjectConfig", @@ -1682,7 +1688,7 @@ "editor/context": [ { "command": "typescript.goToSourceDefinition", - "when": "tsSupportsSourceDefinition && (resourceLangId == typescript || resourceLangId == typescriptreact || resourceLangId == javascript || resourceLangId == javascriptreact)", + "when": "!config.typescript.experimental.useTsgo && tsSupportsSourceDefinition && (resourceLangId == typescript || resourceLangId == typescriptreact || resourceLangId == javascript || resourceLangId == javascriptreact)", "group": "navigation@1.41" } ], @@ -1778,6 +1784,27 @@ ], "pattern": "$tsc" }, + { + "name": "tsgo-watch", + "label": "%typescript.problemMatchers.tsgo-watch.label%", + "owner": "typescript", + "source": "ts", + "applyTo": "closedDocuments", + "fileLocation": [ + "relative", + "${cwd}" + ], + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "^build starting at .*$" + }, + "endsPattern": { + "regexp": "^build finished in .*$" + } + } + }, { "name": "tsc-watch", "label": "%typescript.problemMatchers.tscWatch.label%", diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index ceb221b137b..fb28b2a4eb2 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -56,6 +56,7 @@ "typescript.referencesCodeLens.showOnAllFunctions": "Enable/disable references CodeLens on all functions in TypeScript files.", "typescript.implementationsCodeLens.enabled": "Enable/disable implementations CodeLens. This CodeLens shows the implementers of an interface.", "typescript.implementationsCodeLens.showOnInterfaceMethods": "Enable/disable implementations CodeLens on interface methods.", + "typescript.implementationsCodeLens.showOnAllClassMethods": "Enable/disable showing implementations CodeLens above all class methods instead of only on abstract methods.", "typescript.openTsServerLog.title": "Open TS Server log", "typescript.restartTsServer": "Restart TS Server", "typescript.selectTypeScriptVersion.title": "Select TypeScript Version...", @@ -69,6 +70,7 @@ "typescript.tsc.autoDetect.build": "Only create single run compile tasks.", "typescript.tsc.autoDetect.watch": "Only create compile and watch tasks.", "typescript.problemMatchers.tsc.label": "TypeScript problems", + "typescript.problemMatchers.tsgo-watch.label": "TypeScript problems (watch mode)", "typescript.problemMatchers.tscWatch.label": "TypeScript problems (watch mode)", "configuration.suggest.paths": "Enable/disable suggestions for paths in import statements and require calls.", "configuration.tsserver.useSeparateSyntaxServer": "Enable/disable spawning a separate TypeScript server that can more quickly respond to syntax related operations, such as calculating folding or computing document symbols.", diff --git a/extensions/typescript-language-features/src/languageFeatures/codeLens/implementationsCodeLens.ts b/extensions/typescript-language-features/src/languageFeatures/codeLens/implementationsCodeLens.ts index 6088292f8d0..d012a6ab9d9 100644 --- a/extensions/typescript-language-features/src/languageFeatures/codeLens/implementationsCodeLens.ts +++ b/extensions/typescript-language-features/src/languageFeatures/codeLens/implementationsCodeLens.ts @@ -25,7 +25,8 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip super(client, _cachedResponse); this._register( vscode.workspace.onDidChangeConfiguration(evt => { - if (evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnInterfaceMethods`)) { + if (evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnInterfaceMethods`) || + evt.affectsConfiguration(`${language.id}.implementationsCodeLens.showOnAllClassMethods`)) { this.changeEmitter.fire(); } }) @@ -87,23 +88,48 @@ export default class TypeScriptImplementationsCodeLensProvider extends TypeScrip item: Proto.NavigationTree, parent: Proto.NavigationTree | undefined ): vscode.Range | undefined { - if (item.kind === PConst.Kind.method && parent && parent.kind === PConst.Kind.interface && vscode.workspace.getConfiguration(this.language.id).get('implementationsCodeLens.showOnInterfaceMethods')) { + const cfg = vscode.workspace.getConfiguration(this.language.id); + + // Always show on interfaces + if (item.kind === PConst.Kind.interface) { return getSymbolRange(document, item); } - switch (item.kind) { - case PConst.Kind.interface: - return getSymbolRange(document, item); - case PConst.Kind.class: - case PConst.Kind.method: - case PConst.Kind.memberVariable: - case PConst.Kind.memberGetAccessor: - case PConst.Kind.memberSetAccessor: - if (item.kindModifiers.match(/\babstract\b/g)) { - return getSymbolRange(document, item); - } - break; + // Always show on abstract classes/properties + if ( + (item.kind === PConst.Kind.class || + item.kind === PConst.Kind.method || + item.kind === PConst.Kind.memberVariable || + item.kind === PConst.Kind.memberGetAccessor || + item.kind === PConst.Kind.memberSetAccessor) && + /\babstract\b/.test(item.kindModifiers ?? '') + ) { + return getSymbolRange(document, item); } + + // If configured, show on interface methods + if ( + item.kind === PConst.Kind.method && + parent?.kind === PConst.Kind.interface && + cfg.get('implementationsCodeLens.showOnInterfaceMethods', false) + ) { + return getSymbolRange(document, item); + } + + + // If configured, show on all class methods + if ( + item.kind === PConst.Kind.method && + parent?.kind === PConst.Kind.class && + cfg.get('implementationsCodeLens.showOnAllClassMethods', false) + ) { + // But not private ones as these can never be overridden + if (/\bprivate\b/.test(item.kindModifiers ?? '')) { + return undefined; + } + return getSymbolRange(document, item); + } + return undefined; } } diff --git a/extensions/typescript-language-features/src/languageFeatures/fileReferences.ts b/extensions/typescript-language-features/src/languageFeatures/fileReferences.ts index 3a475ac257b..c9d47d6ebff 100644 --- a/extensions/typescript-language-features/src/languageFeatures/fileReferences.ts +++ b/extensions/typescript-language-features/src/languageFeatures/fileReferences.ts @@ -79,11 +79,14 @@ export function register( client: ITypeScriptServiceClient, commandManager: CommandManager ) { - function updateContext() { - vscode.commands.executeCommand('setContext', FileReferencesCommand.context, client.apiVersion.gte(FileReferencesCommand.minVersion)); + function updateContext(overrideValue?: boolean) { + vscode.commands.executeCommand('setContext', FileReferencesCommand.context, overrideValue ?? client.apiVersion.gte(FileReferencesCommand.minVersion)); } updateContext(); commandManager.register(new FileReferencesCommand(client)); - return client.onTsServerStarted(() => updateContext()); + return vscode.Disposable.from( + client.onTsServerStarted(() => updateContext()), + new vscode.Disposable(() => updateContext(false)), + ); } diff --git a/extensions/typescript-language-features/src/languageFeatures/quickFix.ts b/extensions/typescript-language-features/src/languageFeatures/quickFix.ts index c0e3221be2e..c0c89670d1d 100644 --- a/extensions/typescript-language-features/src/languageFeatures/quickFix.ts +++ b/extensions/typescript-language-features/src/languageFeatures/quickFix.ts @@ -367,7 +367,7 @@ class TypeScriptQuickFixProvider implements vscode.CodeActionProvider updateContext()); + return vscode.Disposable.from( + client.onTsServerStarted(() => updateContext()), + new vscode.Disposable(() => updateContext(false)), + ); } diff --git a/extensions/typescript-language-features/src/test/smoke/implementationsCodeLens.test.ts b/extensions/typescript-language-features/src/test/smoke/implementationsCodeLens.test.ts new file mode 100644 index 00000000000..463f9a202fe --- /dev/null +++ b/extensions/typescript-language-features/src/test/smoke/implementationsCodeLens.test.ts @@ -0,0 +1,169 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import * as vscode from 'vscode'; +import { disposeAll } from '../../utils/dispose'; +import { joinLines, withRandomFileEditor } from '../testUtils'; +import { updateConfig, VsCodeConfiguration } from './referencesCodeLens.test'; + +const Config = { + referencesCodeLens: 'typescript.referencesCodeLens.enabled', + implementationsCodeLens: 'typescript.implementationsCodeLens.enabled', + showOnAllClassMethods: 'typescript.implementationsCodeLens.showOnAllClassMethods', +}; + +function getCodeLenses(doc: vscode.TextDocument) { + return vscode.commands.executeCommand('vscode.executeCodeLensProvider', doc.uri); +} + +suite('TypeScript Implementations CodeLens', () => { + const configDefaults = Object.freeze({ + [Config.referencesCodeLens]: false, + [Config.implementationsCodeLens]: true, + [Config.showOnAllClassMethods]: false, + }); + + const _disposables: vscode.Disposable[] = []; + let oldConfig: { [key: string]: any } = {}; + + setup(async () => { + // the tests assume that typescript features are registered + await vscode.extensions.getExtension('vscode.typescript-language-features')!.activate(); + + // Save off config and apply defaults + oldConfig = await updateConfig(configDefaults); + }); + + teardown(async () => { + disposeAll(_disposables); + + // Restore config + await updateConfig(oldConfig); + + return vscode.commands.executeCommand('workbench.action.closeAllEditors'); + }); + + test('Should show on interfaces and abstract classes', async () => { + await withRandomFileEditor( + joinLines( + 'interface IFoo {}', + 'class Foo implements IFoo {}', + 'abstract class AbstractBase {}', + 'class Concrete extends AbstractBase {}' + ), + 'ts', + async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => { + const lenses = await getCodeLenses(doc); + assert.strictEqual(lenses?.length, 2); + + assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected interface IFoo to have a CodeLens'); + assert.strictEqual(lenses?.[1].range.start.line, 2, 'Expected abstract class AbstractBase to have a CodeLens'); + }, + ); + }); + + test('Should show on abstract methods, properties, and getters', async () => { + await withRandomFileEditor( + joinLines( + 'abstract class Base {', + ' abstract method(): void;', + ' abstract property: string;', + ' abstract get getter(): number;', + '}', + 'class Derived extends Base {', + ' method() {}', + ' property = "test";', + ' get getter() { return 42; }', + '}', + ), + 'ts', + async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => { + const lenses = await getCodeLenses(doc); + assert.strictEqual(lenses?.length, 4); + + assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected abstract class to have a CodeLens'); + assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected abstract method to have a CodeLens'); + assert.strictEqual(lenses?.[2].range.start.line, 2, 'Expected abstract property to have a CodeLens'); + assert.strictEqual(lenses?.[3].range.start.line, 3, 'Expected abstract getter to have a CodeLens'); + }, + ); + }); + + test('Should not show implementations on methods by default', async () => { + await withRandomFileEditor( + joinLines( + 'abstract class A {', + ' foo() {}', + '}', + 'class B extends A {', + ' foo() {}', + '}', + ), + 'ts', + async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => { + const lenses = await getCodeLenses(doc); + assert.strictEqual(lenses?.length, 1); + }, + ); + }); + + test('should show on all methods when showOnAllClassMethods is enabled', async () => { + await updateConfig({ + [Config.showOnAllClassMethods]: true + }); + + await withRandomFileEditor( + joinLines( + 'abstract class A {', + ' foo() {}', + '}', + 'class B extends A {', + ' foo() {}', + '}', + ), + 'ts', + async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => { + const lenses = await getCodeLenses(doc); + assert.strictEqual(lenses?.length, 3); + + assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected class A to have a CodeLens'); + assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected method A.foo to have a CodeLens'); + assert.strictEqual(lenses?.[2].range.start.line, 4, 'Expected method B.foo to have a CodeLens'); + }, + ); + }); + + test('should not show on private methods when showOnAllClassMethods is enabled', async () => { + await updateConfig({ + [Config.showOnAllClassMethods]: true + }); + + await withRandomFileEditor( + joinLines( + 'abstract class A {', + ' public foo() {}', + ' private bar() {}', + ' protected baz() {}', + '}', + 'class B extends A {', + ' public foo() {}', + ' protected baz() {}', + '}', + ), + 'ts', + async (_editor: vscode.TextEditor, doc: vscode.TextDocument) => { + const lenses = await getCodeLenses(doc); + assert.strictEqual(lenses?.length, 5); + + assert.strictEqual(lenses?.[0].range.start.line, 0, 'Expected class A to have a CodeLens'); + assert.strictEqual(lenses?.[1].range.start.line, 1, 'Expected method A.foo to have a CodeLens'); + assert.strictEqual(lenses?.[2].range.start.line, 3, 'Expected method A.baz to have a CodeLens'); + assert.strictEqual(lenses?.[3].range.start.line, 6, 'Expected method B.foo to have a CodeLens'); + assert.strictEqual(lenses?.[4].range.start.line, 7, 'Expected method B.baz to have a CodeLens'); + }, + ); + }); +}); diff --git a/extensions/typescript-language-features/src/test/smoke/referencesCodeLens.test.ts b/extensions/typescript-language-features/src/test/smoke/referencesCodeLens.test.ts index f6259e0d276..7e068249a2e 100644 --- a/extensions/typescript-language-features/src/test/smoke/referencesCodeLens.test.ts +++ b/extensions/typescript-language-features/src/test/smoke/referencesCodeLens.test.ts @@ -10,9 +10,9 @@ import { createTestEditor, wait } from '../../test/testUtils'; import { disposeAll } from '../../utils/dispose'; -type VsCodeConfiguration = { [key: string]: any }; +export type VsCodeConfiguration = { [key: string]: any }; -async function updateConfig(newConfig: VsCodeConfiguration): Promise { +export async function updateConfig(newConfig: VsCodeConfiguration): Promise { const oldConfig: VsCodeConfiguration = {}; const config = vscode.workspace.getConfiguration(undefined); for (const configKey of Object.keys(newConfig)) { diff --git a/extensions/typescript-language-features/src/test/unit/functionCallSnippet.test.ts b/extensions/typescript-language-features/src/test/unit/functionCallSnippet.test.ts index 00f006a05a4..f0f1874a639 100644 --- a/extensions/typescript-language-features/src/test/unit/functionCallSnippet.test.ts +++ b/extensions/typescript-language-features/src/test/unit/functionCallSnippet.test.ts @@ -139,7 +139,7 @@ suite('typescript function call snippets', () => { assert.strictEqual( snippetForFunctionCall( { label: 'foobar', }, - [{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foobar", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "alpha", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "beta", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "gamma", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }] + [{ 'text': 'function', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'foobar', 'kind': 'functionName' }, { 'text': '(', 'kind': 'punctuation' }, { 'text': 'alpha', 'kind': 'parameterName' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'string', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'beta', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'gamma', 'kind': 'parameterName' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'string', 'kind': 'keyword' }, { 'text': ')', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'void', 'kind': 'keyword' }] ).snippet.value, 'foobar(${1:alpha}, ${2:beta}, ${3:gamma}$4)$0'); }); @@ -148,7 +148,7 @@ suite('typescript function call snippets', () => { assert.strictEqual( snippetForFunctionCall( { label: 'foobar', }, - [{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foobar", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "alpha", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "beta", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "gamma", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }] + [{ 'text': 'function', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'foobar', 'kind': 'functionName' }, { 'text': '(', 'kind': 'punctuation' }, { 'text': 'alpha', 'kind': 'parameterName' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'string', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'beta', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'gamma', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ')', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'void', 'kind': 'keyword' }] ).snippet.value, 'foobar(${1:alpha}$2)$0'); }); @@ -158,9 +158,9 @@ suite('typescript function call snippets', () => { assert.strictEqual( snippetForFunctionCall( { label: 'foobar', }, - [{ "text": "function", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "foobar", "kind": "functionName" }, { "text": "(", "kind": "punctuation" }, { "text": "a", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "b", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "c", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, - { "text": "d", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "e", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "f", "kind": "parameterName" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "string", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, - { "text": "g", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ",", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "h", "kind": "parameterName" }, { "text": "?", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "number", "kind": "keyword" }, { "text": " ", "kind": "space" }, { "text": "|", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "undefined", "kind": "keyword" }, { "text": ")", "kind": "punctuation" }, { "text": ":", "kind": "punctuation" }, { "text": " ", "kind": "space" }, { "text": "void", "kind": "keyword" }] + [{ 'text': 'function', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'foobar', 'kind': 'functionName' }, { 'text': '(', 'kind': 'punctuation' }, { 'text': 'a', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'b', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'c', 'kind': 'parameterName' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'string', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, + { 'text': 'd', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'e', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'f', 'kind': 'parameterName' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'string', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, + { 'text': 'g', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ',', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'h', 'kind': 'parameterName' }, { 'text': '?', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'number', 'kind': 'keyword' }, { 'text': ' ', 'kind': 'space' }, { 'text': '|', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'undefined', 'kind': 'keyword' }, { 'text': ')', 'kind': 'punctuation' }, { 'text': ':', 'kind': 'punctuation' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'void', 'kind': 'keyword' }] ).snippet.value, 'foobar(${1:a}, ${2:b}, ${3:c}, ${4:d}, ${5:e}, ${6:f}$7)$0'); }); diff --git a/extensions/typescript-language-features/src/test/unit/textRendering.test.ts b/extensions/typescript-language-features/src/test/unit/textRendering.test.ts index 278bf9de412..f4245b59297 100644 --- a/extensions/typescript-language-features/src/test/unit/textRendering.test.ts +++ b/extensions/typescript-language-features/src/test/unit/textRendering.test.ts @@ -29,7 +29,7 @@ suite('typescript.previewer', () => { assert.strictEqual( documentationToMarkdown( // 'x {@link http://www.example.com/foo} y {@link https://api.jquery.com/bind/#bind-eventType-eventData-handler} z', - [{ "text": "x ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "http://www.example.com/foo", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " y ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "https://api.jquery.com/bind/#bind-eventType-eventData-handler", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " z", "kind": "text" }], + [{ 'text': 'x ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'http://www.example.com/foo', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' y ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'https://api.jquery.com/bind/#bind-eventType-eventData-handler', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' z', 'kind': 'text' }], [], noopToResource, undefined ).value, @@ -40,7 +40,7 @@ suite('typescript.previewer', () => { assert.strictEqual( documentationToMarkdown( // 'x {@link http://www.example.com/foo abc xyz} y {@link http://www.example.com/bar|b a z} z', - [{ "text": "x ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "http://www.example.com/foo abc xyz", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " y ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "http://www.example.com/bar b a z", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " z", "kind": "text" }], + [{ 'text': 'x ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'http://www.example.com/foo abc xyz', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' y ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'http://www.example.com/bar b a z', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' z', 'kind': 'text' }], [], noopToResource, undefined ).value, @@ -51,7 +51,7 @@ suite('typescript.previewer', () => { assert.strictEqual( documentationToMarkdown( // 'x {@linkcode http://www.example.com/foo} y {@linkplain http://www.example.com/bar} z', - [{ "text": "x ", "kind": "text" }, { "text": "{@linkcode ", "kind": "link" }, { "text": "http://www.example.com/foo", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " y ", "kind": "text" }, { "text": "{@linkplain ", "kind": "link" }, { "text": "http://www.example.com/bar", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " z", "kind": "text" }], + [{ 'text': 'x ', 'kind': 'text' }, { 'text': '{@linkcode ', 'kind': 'link' }, { 'text': 'http://www.example.com/foo', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' y ', 'kind': 'text' }, { 'text': '{@linkplain ', 'kind': 'link' }, { 'text': 'http://www.example.com/bar', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' z', 'kind': 'text' }], [], noopToResource, undefined ).value, @@ -64,7 +64,7 @@ suite('typescript.previewer', () => { { name: 'param', // a x {@link http://www.example.com/foo abc xyz} y {@link http://www.example.com/bar|b a z} z - text: [{ "text": "a", "kind": "parameterName" }, { "text": " ", "kind": "space" }, { "text": "x ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "http://www.example.com/foo abc xyz", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " y ", "kind": "text" }, { "text": "{@link ", "kind": "link" }, { "text": "http://www.example.com/bar b a z", "kind": "linkText" }, { "text": "}", "kind": "link" }, { "text": " z", "kind": "text" }], + text: [{ 'text': 'a', 'kind': 'parameterName' }, { 'text': ' ', 'kind': 'space' }, { 'text': 'x ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'http://www.example.com/foo abc xyz', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' y ', 'kind': 'text' }, { 'text': '{@link ', 'kind': 'link' }, { 'text': 'http://www.example.com/bar b a z', 'kind': 'linkText' }, { 'text': '}', 'kind': 'link' }, { 'text': ' z', 'kind': 'text' }], } ], noopToResource), '*@param* `a` — x [abc xyz](http://www.example.com/foo) y [b a z](http://www.example.com/bar) z'); @@ -133,23 +133,23 @@ suite('typescript.previewer', () => { assert.strictEqual( tagsToMarkdown([ { - "name": "example", - "text": [ + 'name': 'example', + 'text': [ { - "text": "1 + 1 ", - "kind": "text" + 'text': '1 + 1 ', + 'kind': 'text' }, { - "text": "{@link ", - "kind": "link" + 'text': '{@link ', + 'kind': 'link' }, { - "text": "foo", - "kind": "linkName" + 'text': 'foo', + 'kind': 'linkName' }, { - "text": "}", - "kind": "link" + 'text': '}', + 'kind': 'link' } ] } @@ -160,19 +160,19 @@ suite('typescript.previewer', () => { test('Should render @linkcode symbol name as code', () => { assert.strictEqual( asPlainTextWithLinks([ - { "text": "a ", "kind": "text" }, - { "text": "{@linkcode ", "kind": "link" }, + { 'text': 'a ', 'kind': 'text' }, + { 'text': '{@linkcode ', 'kind': 'link' }, { - "text": "dog", - "kind": "linkName", - "target": { - "file": "/path/file.ts", - "start": { "line": 7, "offset": 5 }, - "end": { "line": 7, "offset": 13 } + 'text': 'dog', + 'kind': 'linkName', + 'target': { + 'file': '/path/file.ts', + 'start': { 'line': 7, 'offset': 5 }, + 'end': { 'line': 7, 'offset': 13 } } } as SymbolDisplayPart, - { "text": "}", "kind": "link" }, - { "text": " b", "kind": "text" } + { 'text': '}', 'kind': 'link' }, + { 'text': ' b', 'kind': 'text' } ], noopToResource), 'a [`dog`](command:_typescript.openJsDocLink?%5B%7B%22file%22%3A%7B%22path%22%3A%22%2Fpath%2Ffile.ts%22%2C%22scheme%22%3A%22file%22%7D%2C%22position%22%3A%7B%22line%22%3A6%2C%22character%22%3A4%7D%7D%5D) b'); }); @@ -180,20 +180,20 @@ suite('typescript.previewer', () => { test('Should render @linkcode text as code', () => { assert.strictEqual( asPlainTextWithLinks([ - { "text": "a ", "kind": "text" }, - { "text": "{@linkcode ", "kind": "link" }, + { 'text': 'a ', 'kind': 'text' }, + { 'text': '{@linkcode ', 'kind': 'link' }, { - "text": "dog", - "kind": "linkName", - "target": { - "file": "/path/file.ts", - "start": { "line": 7, "offset": 5 }, - "end": { "line": 7, "offset": 13 } + 'text': 'dog', + 'kind': 'linkName', + 'target': { + 'file': '/path/file.ts', + 'start': { 'line': 7, 'offset': 5 }, + 'end': { 'line': 7, 'offset': 13 } } } as SymbolDisplayPart, - { "text": "husky", "kind": "linkText" }, - { "text": "}", "kind": "link" }, - { "text": " b", "kind": "text" } + { 'text': 'husky', 'kind': 'linkText' }, + { 'text': '}', 'kind': 'link' }, + { 'text': ' b', 'kind': 'text' } ], noopToResource), 'a [`husky`](command:_typescript.openJsDocLink?%5B%7B%22file%22%3A%7B%22path%22%3A%22%2Fpath%2Ffile.ts%22%2C%22scheme%22%3A%22file%22%7D%2C%22position%22%3A%7B%22line%22%3A6%2C%22character%22%3A4%7D%7D%5D) b'); }); diff --git a/extensions/typescript-language-features/src/typescriptServiceClient.ts b/extensions/typescript-language-features/src/typescriptServiceClient.ts index dc66ab49fed..207698de92f 100644 --- a/extensions/typescript-language-features/src/typescriptServiceClient.ts +++ b/extensions/typescript-language-features/src/typescriptServiceClient.ts @@ -235,7 +235,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType return this.apiVersion.fullVersionString; }); - this.diagnosticsManager = new DiagnosticsManager('typescript', this._configuration, this.telemetryReporter, onCaseInsensitiveFileSystem); + this.diagnosticsManager = this._register(new DiagnosticsManager('typescript', this._configuration, this.telemetryReporter, onCaseInsensitiveFileSystem)); this.typescriptServerSpawner = new TypeScriptServerSpawner(this.versionProvider, this._versionManager, this._nodeVersionManager, this.logDirectoryProvider, this.pluginPathsProvider, this.logger, this.telemetryReporter, this.tracer, this.processFactory); this._register(this.pluginManager.onDidUpdateConfig(update => { diff --git a/extensions/typescript-language-features/src/ui/managedFileContext.ts b/extensions/typescript-language-features/src/ui/managedFileContext.ts index 1da4588a334..c66b90c9e82 100644 --- a/extensions/typescript-language-features/src/ui/managedFileContext.ts +++ b/extensions/typescript-language-features/src/ui/managedFileContext.ts @@ -18,13 +18,20 @@ export default class ManagedFileContextManager extends Disposable { private isInManagedFileContext: boolean = false; - public constructor(activeJsTsEditorTracker: ActiveJsTsEditorTracker) { + constructor(activeJsTsEditorTracker: ActiveJsTsEditorTracker) { super(); activeJsTsEditorTracker.onDidChangeActiveJsTsEditor(this.onDidChangeActiveTextEditor, this, this._disposables); this.onDidChangeActiveTextEditor(activeJsTsEditorTracker.activeJsTsEditor); } + override dispose() { + // Clear the context + this.updateContext(false); + + super.dispose(); + } + private onDidChangeActiveTextEditor(editor?: vscode.TextEditor): void { if (editor) { this.updateContext(this.isManagedFile(editor)); diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index 74c7eacd7e1..f18cecc4d0d 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -32,7 +32,9 @@ "notebookMessaging", "notebookMime", "portsAttributes", + "quickInputButtonLocation", "quickPickSortByLabel", + "quickPickItemResource", "resolvers", "scmActionButton", "scmSelectedProvider", @@ -51,7 +53,8 @@ "tunnels", "workspaceTrust", "inlineCompletionsAdditions", - "devDeviceId" + "devDeviceId", + "languageModelProxy" ], "private": true, "activationEvents": [], @@ -265,7 +268,7 @@ }, "scripts": { "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-api-tests ./tsconfig.json" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:vscode-api-tests ./tsconfig.json" }, "devDependencies": { "@types/mocha": "^10.0.10", diff --git a/extensions/vscode-api-tests/src/extension.ts b/extensions/vscode-api-tests/src/extension.ts index 3886f5fde75..c49f62a38c2 100644 --- a/extensions/vscode-api-tests/src/extension.ts +++ b/extensions/vscode-api-tests/src/extension.ts @@ -5,8 +5,11 @@ import * as vscode from 'vscode'; +declare global { + var testExtensionContext: vscode.ExtensionContext; +} + export function activate(_context: vscode.ExtensionContext) { // Set context as a global as some tests depend on it - // eslint-disable-next-line local/code-no-any-casts - (global as any).testExtensionContext = _context; + global.testExtensionContext = _context; } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts index d02f71ba045..ff5b49d9b69 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/chat.test.ts @@ -4,8 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; +import * as fs from 'fs'; +import { join } from 'path'; import 'mocha'; -import { ChatContext, ChatRequest, ChatRequestTurn, ChatRequestTurn2, ChatResult, Disposable, Event, EventEmitter, chat, commands, lm } from 'vscode'; +import { ChatContext, ChatRequest, ChatRequestTurn, ChatRequestTurn2, ChatResult, Disposable, env, Event, EventEmitter, chat, commands, lm, UIKind } from 'vscode'; import { DeferredPromise, asPromise, assertNoRpc, closeAllEditors, delay, disposeAll } from '../utils'; suite('chat', () => { @@ -178,8 +180,12 @@ suite('chat', () => { await commands.executeCommand('workbench.action.chat.newChat'); const result = await commands.executeCommand('workbench.action.chat.open', { query: 'hello', blockOnResponse: true }); - // eslint-disable-next-line local/code-no-any-casts - assert.strictEqual((result as any).errorDetails.code, 'rate_limited'); + type PartialChatAgentResult = { + errorDetails: { + code: string; + }; + }; + assert.strictEqual((result).errorDetails.code, 'rate_limited'); }); test('title provider is called for first request', async () => { @@ -210,4 +216,28 @@ suite('chat', () => { // Title provider was not called again assert.strictEqual(calls, 1); }); + + test('can access node-pty module', async function () { + // Required for copilot cli in chat extension. + if (env.uiKind === UIKind.Web) { + this.skip(); + } + const nodePtyModules = [ + join(env.appRoot, 'node_modules.asar', 'node-pty'), + join(env.appRoot, 'node_modules', 'node-pty') + ]; + + for (const modulePath of nodePtyModules) { + // try to stat and require module + try { + await fs.promises.stat(modulePath); + const nodePty = require(modulePath); + assert.ok(nodePty, `Successfully required node-pty from ${modulePath}`); + return; + } catch (err) { + // failed to require, try next + } + } + assert.fail('Failed to find and require node-pty module'); + }); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts index 28f66a0f104..18ae50d3af6 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts @@ -63,7 +63,7 @@ suite('vscode API - debug', function () { assert.strictEqual(functionBreakpoint.functionName, 'func'); }); - test('start debugging', async function () { + test.skip('start debugging', async function () { // Flaky: https://github.com/microsoft/vscode/issues/242033 let stoppedEvents = 0; let variablesReceived: () => void; let initializedReceived: () => void; diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts index b4212bb6103..39179d0d1e3 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/documentPaste.test.ts @@ -208,7 +208,7 @@ suite.skip('vscode API - Copy Paste', function () { }); function reverseString(str: string) { - return str.split("").reverse().join(""); + return str.split('').reverse().join(''); } function getNextDocumentText(disposables: vscode.Disposable[], doc: vscode.TextDocument): Promise { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts index 1bd22369152..ce8e68e0c1e 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { commands, env, Position, Range, Selection, SnippetString, TextDocument, TextEditor, TextEditorCursorStyle, TextEditorLineNumbersStyle, Uri, window, workspace } from 'vscode'; +import { env, Position, Range, Selection, SnippetString, TextDocument, TextEditor, TextEditorCursorStyle, TextEditorLineNumbersStyle, Uri, window, workspace } from 'vscode'; import { assertNoRpc, closeAllEditors, createRandomFile, deleteFile } from '../utils'; suite('vscode API - editors', () => { @@ -167,53 +167,6 @@ suite('vscode API - editors', () => { }); }); - function executeReplace(editor: TextEditor, range: Range, text: string, undoStopBefore: boolean, undoStopAfter: boolean): Thenable { - return editor.edit((builder) => { - builder.replace(range, text); - }, { undoStopBefore: undoStopBefore, undoStopAfter: undoStopAfter }); - } - - test.skip('TextEditor.edit can control undo/redo stack 1', () => { - return withRandomFileEditor('Hello world!', async (editor, doc) => { - const applied1 = await executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false); - assert.ok(applied1); - assert.strictEqual(doc.getText(), 'hello world!'); - assert.ok(doc.isDirty); - - const applied2 = await executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', false, false); - assert.ok(applied2); - assert.strictEqual(doc.getText(), 'hELLO world!'); - assert.ok(doc.isDirty); - - await commands.executeCommand('undo'); - if (doc.getText() === 'hello world!') { - // see https://github.com/microsoft/vscode/issues/109131 - // it looks like an undo stop was inserted in between these two edits - // it is unclear why this happens, but it can happen for a multitude of reasons - await commands.executeCommand('undo'); - } - assert.strictEqual(doc.getText(), 'Hello world!'); - }); - }); - - test.skip('TextEditor.edit can control undo/redo stack 2', () => { - return withRandomFileEditor('Hello world!', (editor, doc) => { - return executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false).then(applied => { - assert.ok(applied); - assert.strictEqual(doc.getText(), 'hello world!'); - assert.ok(doc.isDirty); - return executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', true, false); - }).then(applied => { - assert.ok(applied); - assert.strictEqual(doc.getText(), 'hELLO world!'); - assert.ok(doc.isDirty); - return commands.executeCommand('undo'); - }).then(_ => { - assert.strictEqual(doc.getText(), 'hello world!'); - }); - }); - }); - test('issue #16573: Extension API: insertSpaces and tabSize are undefined', () => { return withRandomFileEditor('Hello world!\n\tHello world!', (editor, _doc) => { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/ipynb.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/ipynb.test.ts index dafd4df1e68..5cfdf8fe8f2 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/ipynb.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/ipynb.test.ts @@ -9,24 +9,24 @@ import * as vscode from 'vscode'; import { assertNoRpc, closeAllEditors, createRandomFile } from '../utils'; const ipynbContent = JSON.stringify({ - "cells": [ + 'cells': [ { - "cell_type": "markdown", - "source": ["## Header"], - "metadata": {} + 'cell_type': 'markdown', + 'source': ['## Header'], + 'metadata': {} }, { - "cell_type": "code", - "execution_count": 2, - "source": ["print('hello 1')\n", "print('hello 2')"], - "outputs": [ + 'cell_type': 'code', + 'execution_count': 2, + 'source': [`print('hello 1')\n`, `print('hello 2')`], + 'outputs': [ { - "output_type": "stream", - "name": "stdout", - "text": ["hello 1\n", "hello 2\n"] + 'output_type': 'stream', + 'name': 'stdout', + 'text': ['hello 1\n', 'hello 2\n'] } ], - "metadata": {} + 'metadata': {} } ] }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.kernel.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.kernel.test.ts index 7cc5e40a100..805c9446086 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.kernel.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.kernel.test.ts @@ -14,9 +14,7 @@ async function createRandomNotebookFile() { } async function openRandomNotebookDocument() { - console.log('Creating a random notebook file'); const uri = await createRandomNotebookFile(); - console.log('Created a random notebook file'); return vscode.workspace.openNotebookDocument(uri); } @@ -121,7 +119,6 @@ const apiTestSerializer: vscode.NotebookSerializer = { } ] }; - console.log('Returning NotebookData in deserializeNotebook'); return dto; } }; diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts index ae3693b7a1a..c0b4f154260 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/proxy.test.ts @@ -13,6 +13,12 @@ import * as vscode from 'vscode'; import { Straightforward, Middleware, RequestContext, ConnectContext, isRequest, isConnect } from 'straightforward'; import assert from 'assert'; +declare module 'https' { + interface Agent { + testCertificates?: string[]; + } +} + (vscode.env.uiKind === vscode.UIKind.Web ? suite.skip : suite)('vscode API - network proxy support', () => { teardown(async function () { @@ -56,8 +62,7 @@ import assert from 'assert'; }); // Using https.globalAgent because it is shared with proxyResolver.ts and mutable. - // eslint-disable-next-line local/code-no-any-casts - (https.globalAgent as any).testCertificates = [certPEM]; + https.globalAgent.testCertificates = [certPEM]; resetCaches(); try { @@ -73,8 +78,7 @@ import assert from 'assert'; .on('error', reject); }); } finally { - // eslint-disable-next-line local/code-no-any-casts - delete (https.globalAgent as any).testCertificates; + delete https.globalAgent.testCertificates; resetCaches(); server.close(); } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts index 4f8331c286f..485e3d85f34 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { commands, Disposable, QuickPick, QuickPickItem, window } from 'vscode'; +import { commands, Disposable, QuickPick, QuickPickItem, window, workspace } from 'vscode'; import { assertNoRpc, closeAllEditors } from '../utils'; interface QuickPickExpected { @@ -248,6 +248,71 @@ suite('vscode API - quick input', function () { quickPick.hide(); await waitForHide(quickPick); }); + + test('createQuickPick, match item by label derived from resourceUri', function (_done) { + let done = (err?: any) => { + done = () => { }; + _done(err); + }; + + const quickPick = createQuickPick({ + events: ['active', 'selection', 'accept', 'hide'], + activeItems: [['']], + selectionItems: [['']], + acceptedItems: { + active: [['']], + selection: [['']], + dispose: [true] + }, + }, (err?: any) => done(err)); + + const baseUri = workspace!.workspaceFolders![0].uri; + quickPick.items = [ + { label: 'a1', resourceUri: baseUri.with({ path: baseUri.path + '/test1.txt' }) }, + { label: '', resourceUri: baseUri.with({ path: baseUri.path + '/test2.txt' }) }, + { label: 'a3', resourceUri: baseUri.with({ path: baseUri.path + '/test3.txt' }) } + ]; + quickPick.value = 'test2.txt'; + quickPick.show(); + + (async () => { + await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); + })() + .catch(err => done(err)); + }); + + test('createQuickPick, match item by description derived from resourceUri', function (_done) { + let done = (err?: any) => { + done = () => { }; + _done(err); + }; + + const quickPick = createQuickPick({ + events: ['active', 'selection', 'accept', 'hide'], + activeItems: [['a2']], + selectionItems: [['a2']], + acceptedItems: { + active: [['a2']], + selection: [['a2']], + dispose: [true] + }, + }, (err?: any) => done(err)); + + const baseUri = workspace!.workspaceFolders![0].uri; + quickPick.items = [ + { label: 'a1', resourceUri: baseUri.with({ path: baseUri.path + '/test1.txt' }) }, + { label: 'a2', resourceUri: baseUri.with({ path: baseUri.path + '/test2.txt' }) }, + { label: 'a3', resourceUri: baseUri.with({ path: baseUri.path + '/test3.txt' }) } + ]; + quickPick.matchOnDescription = true; + quickPick.value = 'test2.txt'; + quickPick.show(); + + (async () => { + await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); + })() + .catch(err => done(err)); + }); }); function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, record = false) { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts index 26d7d0a5485..54e638d5f3b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/state.test.ts @@ -13,8 +13,7 @@ suite('vscode API - globalState / workspaceState', () => { suiteSetup(async () => { // Trigger extension activation and grab the context as some tests depend on it await extensions.getExtension('vscode.vscode-api-tests')?.activate(); - // eslint-disable-next-line local/code-no-any-casts - extensionContext = (global as any).testExtensionContext; + extensionContext = global.testExtensionContext; }); test('state basics', async () => { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts index bb0c59bd32a..de82ba5410d 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -15,8 +15,7 @@ import { assertNoRpc, poll } from '../utils'; suiteSetup(async () => { // Trigger extension activation and grab the context as some tests depend on it await extensions.getExtension('vscode.vscode-api-tests')?.activate(); - // eslint-disable-next-line local/code-no-any-casts - extensionContext = (global as any).testExtensionContext; + extensionContext = global.testExtensionContext; const config = workspace.getConfiguration('terminal.integrated'); // Disable conpty in integration tests because of https://github.com/microsoft/vscode/issues/76548 @@ -28,7 +27,7 @@ import { assertNoRpc, poll } from '../utils'; // Disable env var relaunch for tests to prevent terminals relaunching themselves await config.update('environmentChangesRelaunch', false, ConfigurationTarget.Global); // Disable local echo in case it causes any problems in remote tests - await config.update('localEchoEnabled', "off", ConfigurationTarget.Global); + await config.update('localEchoEnabled', 'off', ConfigurationTarget.Global); await config.update('shellIntegration.enabled', false); }); @@ -927,16 +926,16 @@ import { assertNoRpc, poll } from '../utils'; applyAtProcessCreation: true, applyAtShellIntegration: false }; - deepStrictEqual(collection.get('A'), { value: '~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions }); - deepStrictEqual(collection.get('B'), { value: '~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions }); - deepStrictEqual(collection.get('C'), { value: '~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions }); + deepStrictEqual(collection.get('A'), { value: '~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions, variable: 'A' }); + deepStrictEqual(collection.get('B'), { value: '~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions, variable: 'B' }); + deepStrictEqual(collection.get('C'), { value: '~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions, variable: 'C' }); // Verify forEach const entries: [string, EnvironmentVariableMutator][] = []; collection.forEach((v, m) => entries.push([v, m])); deepStrictEqual(entries, [ - ['A', { value: '~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions }], - ['B', { value: '~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions }], - ['C', { value: '~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions }] + ['A', { value: '~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions, variable: 'A' }], + ['B', { value: '~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions, variable: 'B' }], + ['C', { value: '~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions, variable: 'C' }] ]); }); @@ -957,17 +956,17 @@ import { assertNoRpc, poll } from '../utils'; applyAtShellIntegration: false }; const expectedScopedCollection = collection.getScoped(scope); - deepStrictEqual(expectedScopedCollection.get('A'), { value: 'scoped~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions }); - deepStrictEqual(expectedScopedCollection.get('B'), { value: 'scoped~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions }); - deepStrictEqual(expectedScopedCollection.get('C'), { value: 'scoped~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions }); + deepStrictEqual(expectedScopedCollection.get('A'), { value: 'scoped~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions, variable: 'A' }); + deepStrictEqual(expectedScopedCollection.get('B'), { value: 'scoped~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions, variable: 'B' }); + deepStrictEqual(expectedScopedCollection.get('C'), { value: 'scoped~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions, variable: 'C' }); // Verify forEach const entries: [string, EnvironmentVariableMutator][] = []; expectedScopedCollection.forEach((v, m) => entries.push([v, m])); deepStrictEqual(entries.map(v => v[1]), [ - { value: 'scoped~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions }, - { value: 'scoped~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions }, - { value: 'scoped~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions } + { value: 'scoped~a2~', type: EnvironmentVariableMutatorType.Replace, options: defaultOptions, variable: 'A' }, + { value: 'scoped~b2~', type: EnvironmentVariableMutatorType.Append, options: defaultOptions, variable: 'B' }, + { value: 'scoped~c2~', type: EnvironmentVariableMutatorType.Prepend, options: defaultOptions, variable: 'C' } ]); deepStrictEqual(entries.map(v => v[0]), ['A', 'B', 'C']); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index 3bcaecb2a71..19f72931512 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -1179,40 +1179,6 @@ suite('vscode API - workspace', () => { }); - test.skip('issue #110141 - TextEdit.setEndOfLine applies an edit and invalidates redo stack even when no change is made', async () => { - const file = await createRandomFile('hello\nworld'); - - const document = await vscode.workspace.openTextDocument(file); - await vscode.window.showTextDocument(document); - - // apply edit - { - const we = new vscode.WorkspaceEdit(); - we.insert(file, new vscode.Position(0, 5), '2'); - await vscode.workspace.applyEdit(we); - } - - // check the document - { - assert.strictEqual(document.getText(), 'hello2\nworld'); - assert.strictEqual(document.isDirty, true); - } - - // apply no-op edit - { - const we = new vscode.WorkspaceEdit(); - we.set(file, [vscode.TextEdit.setEndOfLine(vscode.EndOfLine.LF)]); - await vscode.workspace.applyEdit(we); - } - - // undo - { - await vscode.commands.executeCommand('undo'); - assert.strictEqual(document.getText(), 'hello\nworld'); - assert.strictEqual(document.isDirty, false); - } - }); - test('SnippetString in WorkspaceEdit', async function (): Promise { const file = await createRandomFile('hello\nworld'); diff --git a/extensions/vscode-colorize-perf-tests/package.json b/extensions/vscode-colorize-perf-tests/package.json index fb7ce45f613..2ac38c1a995 100644 --- a/extensions/vscode-colorize-perf-tests/package.json +++ b/extensions/vscode-colorize-perf-tests/package.json @@ -14,7 +14,7 @@ }, "icon": "media/icon.png", "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-perf-tests ./tsconfig.json", + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:vscode-colorize-perf-tests ./tsconfig.json", "watch": "gulp watch-extension:vscode-colorize-perf-tests", "compile": "gulp compile-extension:vscode-colorize-perf-tests" }, diff --git a/extensions/vscode-colorize-perf-tests/src/colorizer.test.ts b/extensions/vscode-colorize-perf-tests/src/colorizer.test.ts index 7e1df20ca29..2076a96d6b3 100644 --- a/extensions/vscode-colorize-perf-tests/src/colorizer.test.ts +++ b/extensions/vscode-colorize-perf-tests/src/colorizer.test.ts @@ -131,7 +131,7 @@ suite('Tokenization Performance', () => { suiteSetup(async function () { originalSettingValue = workspace.getConfiguration('editor').get('experimental.preferTreeSitter'); - await workspace.getConfiguration('editor').update('experimental.preferTreeSitter', ["typescript"], ConfigurationTarget.Global); + await workspace.getConfiguration('editor').update('experimental.preferTreeSitter', ['typescript'], ConfigurationTarget.Global); }); suiteTeardown(async function () { await workspace.getConfiguration('editor').update('experimental.preferTreeSitter', originalSettingValue, ConfigurationTarget.Global); diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index 49592763745..1abff3d9862 100644 --- a/extensions/vscode-colorize-tests/package.json +++ b/extensions/vscode-colorize-tests/package.json @@ -14,7 +14,7 @@ }, "icon": "media/icon.png", "scripts": { - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json", + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:vscode-colorize-tests ./tsconfig.json", "watch": "gulp watch-extension:vscode-colorize-tests", "compile": "gulp compile-extension:vscode-colorize-tests" }, diff --git a/extensions/vscode-colorize-tests/test/colorize-fixtures/test.env b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.env new file mode 100644 index 00000000000..b2972ab3751 --- /dev/null +++ b/extensions/vscode-colorize-tests/test/colorize-fixtures/test.env @@ -0,0 +1,3 @@ +# dev +HELLO=123 +GOODBYE=456 diff --git a/extensions/vscode-colorize-tests/test/colorize-results/basic_java.json b/extensions/vscode-colorize-tests/test/colorize-results/basic_java.json index 843740c186f..71a5a901280 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/basic_java.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/basic_java.json @@ -1697,12 +1697,12 @@ "c": "for", "t": "source.java meta.class.java meta.class.body.java meta.method.java meta.method.body.java keyword.control.java", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2243,12 +2243,12 @@ "c": "return", "t": "source.java meta.class.java meta.class.body.java meta.method.java meta.method.body.java keyword.control.java", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2817,12 +2817,12 @@ "c": "new", "t": "source.java meta.class.java meta.class.body.java meta.method.java meta.method.body.java keyword.control.new.java", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/issue-28354_php.json b/extensions/vscode-colorize-tests/test/colorize-results/issue-28354_php.json index 642bf6542ff..77914003b54 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/issue-28354_php.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/issue-28354_php.json @@ -115,12 +115,12 @@ "c": "foreach", "t": "text.html.php meta.embedded.block.html source.js meta.embedded.block.php source.php keyword.control.foreach.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/makefile.json b/extensions/vscode-colorize-tests/test/colorize-results/makefile.json index db94f1063e4..b03ac95a7f9 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/makefile.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/makefile.json @@ -1193,12 +1193,12 @@ "c": "@", "t": "source.makefile meta.scope.recipe.makefile keyword.control.@.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1235,12 +1235,12 @@ "c": "@-+-+", "t": "source.makefile meta.scope.recipe.makefile keyword.control.@-+-+.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1291,12 +1291,12 @@ "c": "@", "t": "source.makefile meta.scope.recipe.makefile keyword.control.@.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1487,12 +1487,12 @@ "c": "@-", "t": "source.makefile meta.scope.recipe.makefile keyword.control.@-.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1515,12 +1515,12 @@ "c": "define", "t": "source.makefile meta.scope.conditional.makefile keyword.control.define.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2075,12 +2075,12 @@ "c": "endef", "t": "source.makefile meta.scope.conditional.makefile keyword.control.override.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2089,12 +2089,12 @@ "c": "ifeq", "t": "source.makefile meta.scope.conditional.makefile keyword.control.ifeq.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2355,12 +2355,12 @@ "c": "endif", "t": "source.makefile meta.scope.conditional.makefile keyword.control.endif.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2369,12 +2369,12 @@ "c": "-include", "t": "source.makefile keyword.control.include.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2453,12 +2453,12 @@ "c": "ifeq", "t": "source.makefile meta.scope.conditional.makefile keyword.control.ifeq.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2775,12 +2775,12 @@ "c": "endif", "t": "source.makefile meta.scope.conditional.makefile keyword.control.endif.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3237,12 +3237,12 @@ "c": "ifeq", "t": "source.makefile meta.scope.conditional.makefile keyword.control.ifeq.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3419,12 +3419,12 @@ "c": "else ifeq", "t": "source.makefile meta.scope.conditional.makefile keyword.control.else.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3601,12 +3601,12 @@ "c": "else", "t": "source.makefile meta.scope.conditional.makefile keyword.control.else.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3755,12 +3755,12 @@ "c": "endif", "t": "source.makefile meta.scope.conditional.makefile keyword.control.endif.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4931,12 +4931,12 @@ "c": "export", "t": "source.makefile keyword.control.export.makefile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-173336_sh.json b/extensions/vscode-colorize-tests/test/colorize-results/test-173336_sh.json index 720a867ca74..c1875bfa986 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-173336_sh.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-173336_sh.json @@ -213,12 +213,12 @@ "c": "if", "t": "source.shell meta.scope.if-block.shell keyword.control.if.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -437,12 +437,12 @@ "c": "then", "t": "source.shell meta.scope.if-block.shell keyword.control.then.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -815,12 +815,12 @@ "c": "fi", "t": "source.shell meta.scope.if-block.shell keyword.control.fi.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-23630_cpp.json b/extensions/vscode-colorize-tests/test/colorize-results/test-23630_cpp.json index 222b60af2e0..79e4727a417 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-23630_cpp.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-23630_cpp.json @@ -3,12 +3,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.conditional.ifndef.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "ifndef", "t": "source.cpp keyword.control.directive.conditional.ifndef.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -73,12 +73,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -87,12 +87,12 @@ "c": "define", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -129,12 +129,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.endif.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -143,12 +143,12 @@ "c": "endif", "t": "source.cpp keyword.control.directive.endif.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-23850_cpp.json b/extensions/vscode-colorize-tests/test/colorize-results/test-23850_cpp.json index 61251a59c3c..a5e6addc3b1 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-23850_cpp.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-23850_cpp.json @@ -3,12 +3,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.conditional.ifndef.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "ifndef", "t": "source.cpp keyword.control.directive.conditional.ifndef.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -59,12 +59,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -73,12 +73,12 @@ "c": "define", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -115,12 +115,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.endif.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -129,12 +129,12 @@ "c": "endif", "t": "source.cpp keyword.control.directive.endif.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-241001_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-241001_ts.json index e2b376a059c..67b874115af 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-241001_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-241001_ts.json @@ -955,12 +955,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3027,12 +3027,12 @@ "c": "import", "t": "source.ts new.expr.ts keyword.control.import.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-6611_rs.json b/extensions/vscode-colorize-tests/test/colorize-results/test-6611_rs.json index a8dc0e0fd28..9897e09a654 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-6611_rs.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-6611_rs.json @@ -381,12 +381,12 @@ "c": "for", "t": "source.rust keyword.control.rust", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -689,12 +689,12 @@ "c": "for", "t": "source.rust keyword.control.rust", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-78769_cpp.json b/extensions/vscode-colorize-tests/test/colorize-results/test-78769_cpp.json index a1a55fd67db..16438692b78 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-78769_cpp.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-78769_cpp.json @@ -3,12 +3,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "define", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-freeze-56377_py.json b/extensions/vscode-colorize-tests/test/colorize-results/test-freeze-56377_py.json index 994f91b2ae1..432ecde8cce 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-freeze-56377_py.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-freeze-56377_py.json @@ -269,12 +269,12 @@ "c": "for", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -325,12 +325,12 @@ "c": "in", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -493,12 +493,12 @@ "c": "if", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-issue11_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-issue11_ts.json index 957fe515fb7..68717cc4939 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-issue11_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-issue11_ts.json @@ -115,12 +115,12 @@ "c": "if", "t": "source.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -465,12 +465,12 @@ "c": "for", "t": "source.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "for", "t": "source.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1025,12 +1025,12 @@ "c": "for", "t": "source.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1305,12 +1305,12 @@ "c": "for", "t": "source.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1473,12 +1473,12 @@ "c": "for", "t": "source.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3055,12 +3055,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-issue241715_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-issue241715_ts.json index 9489f1d5b91..da9e674e46c 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-issue241715_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-issue241715_ts.json @@ -633,12 +633,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1081,12 +1081,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1711,12 +1711,12 @@ "c": "export", "t": "source.ts meta.interface.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2159,12 +2159,12 @@ "c": "return", "t": "source.ts meta.arrow.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2257,12 +2257,12 @@ "c": "export", "t": "source.ts meta.function.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2523,12 +2523,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3475,12 +3475,12 @@ "c": "export", "t": "source.ts meta.function.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3853,12 +3853,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-issue5431_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-issue5431_ts.json index e093fe01582..c1988500c97 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-issue5431_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-issue5431_ts.json @@ -591,12 +591,12 @@ "c": "return", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-issue5465_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-issue5465_ts.json index b238ed5c61a..4282511c5e8 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-issue5465_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-issue5465_ts.json @@ -129,12 +129,12 @@ "c": "yield", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -227,12 +227,12 @@ "c": "yield", "t": "source.ts meta.function.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test-keywords_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test-keywords_ts.json index 091238d6e12..a365ac3d098 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test-keywords_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test-keywords_ts.json @@ -3,12 +3,12 @@ "c": "export", "t": "source.ts meta.var.expr.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test2_pl.json b/extensions/vscode-colorize-tests/test/colorize-results/test2_pl.json index dde3a9855c8..7d7b3bbe3e5 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test2_pl.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test2_pl.json @@ -3,12 +3,12 @@ "c": "die", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -129,12 +129,12 @@ "c": "unless", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -353,12 +353,12 @@ "c": "i", "t": "source.perl string.regexp.find.perl punctuation.definition.string.perl keyword.control.regexp-option.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -619,12 +619,12 @@ "c": "i", "t": "source.perl string.regexp.find.perl punctuation.definition.string.perl keyword.control.regexp-option.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "while", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1291,12 +1291,12 @@ "c": "next", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1319,12 +1319,12 @@ "c": "unless", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1529,12 +1529,12 @@ "c": "next", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1557,12 +1557,12 @@ "c": "unless", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1725,12 +1725,12 @@ "c": "$", "t": "source.perl string.regexp.find.perl keyword.control.anchor.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2131,12 +2131,12 @@ "c": "next", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2159,12 +2159,12 @@ "c": "unless", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2285,12 +2285,12 @@ "c": "$", "t": "source.perl string.regexp.find.perl keyword.control.anchor.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2439,12 +2439,12 @@ "c": "next", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2467,12 +2467,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2901,12 +2901,12 @@ "c": "for", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3419,12 +3419,12 @@ "c": "next", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3447,12 +3447,12 @@ "c": "unless", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3629,12 +3629,12 @@ "c": "for", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3965,12 +3965,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test6916_js.json b/extensions/vscode-colorize-tests/test/colorize-results/test6916_js.json index 5183b00921b..4fa10b042fa 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test6916_js.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test6916_js.json @@ -3,12 +3,12 @@ "c": "for", "t": "source.js keyword.control.loop.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -227,12 +227,12 @@ "c": "for", "t": "source.js meta.block.js keyword.control.loop.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -423,12 +423,12 @@ "c": "if", "t": "source.js meta.block.js meta.block.js keyword.control.conditional.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -535,12 +535,12 @@ "c": "return", "t": "source.js meta.block.js meta.block.js keyword.control.flow.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json b/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json index 4611be77db0..853018d8458 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json @@ -199,12 +199,12 @@ "c": "if", "t": "source.batchfile keyword.control.conditional.batchfile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -283,12 +283,12 @@ "c": "call", "t": "source.batchfile keyword.control.statement.batchfile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -381,12 +381,12 @@ "c": "if", "t": "source.batchfile keyword.control.conditional.batchfile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -563,12 +563,12 @@ "c": "call", "t": "source.batchfile keyword.control.statement.batchfile", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -685,4 +685,4 @@ "light_modern": "keyword: #0000FF" } } -] \ No newline at end of file +] diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_c.json b/extensions/vscode-colorize-tests/test/colorize-results/test_c.json index ecf56307bae..fbbf86a1c70 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_c.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_c.json @@ -87,12 +87,12 @@ "c": "#", "t": "source.c meta.preprocessor.include.c keyword.control.directive.include.c punctuation.definition.directive.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -101,12 +101,12 @@ "c": "include", "t": "source.c meta.preprocessor.include.c keyword.control.directive.include.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -171,12 +171,12 @@ "c": "#", "t": "source.c meta.preprocessor.include.c keyword.control.directive.include.c punctuation.definition.directive.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -185,12 +185,12 @@ "c": "include", "t": "source.c meta.preprocessor.include.c keyword.control.directive.include.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1179,12 +1179,12 @@ "c": "if", "t": "source.c meta.block.c keyword.control.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2089,12 +2089,12 @@ "c": "else", "t": "source.c meta.block.c keyword.control.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2117,12 +2117,12 @@ "c": "if", "t": "source.c meta.block.c keyword.control.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2691,12 +2691,12 @@ "c": "else", "t": "source.c meta.block.c keyword.control.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3489,12 +3489,12 @@ "c": "return", "t": "source.c meta.block.c keyword.control.c", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cc.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cc.json index 446f09c02c7..19e19cec621 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cc.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cc.json @@ -3,12 +3,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.conditional.if.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "if", "t": "source.cpp keyword.control.directive.conditional.if.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -269,12 +269,12 @@ "c": "for", "t": "source.cpp keyword.control.for.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -829,12 +829,12 @@ "c": "#", "t": "source.cpp keyword.control.directive.endif.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -843,12 +843,12 @@ "c": "endif", "t": "source.cpp keyword.control.directive.endif.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1655,12 +1655,12 @@ "c": "new", "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.operator.wordlike.cpp keyword.operator.new.cpp", "r": { - "dark_plus": "source.cpp keyword.operator.new: #CE92A4", + "dark_plus": "source.cpp keyword.operator.new: #C586C0", "light_plus": "source.cpp keyword.operator.new: #AF00DB", "dark_vs": "keyword.operator.new: #569CD6", "light_vs": "keyword.operator.new: #0000FF", "hc_black": "source.cpp keyword.operator.new: #C586C0", - "dark_modern": "source.cpp keyword.operator.new: #CE92A4", + "dark_modern": "source.cpp keyword.operator.new: #C586C0", "hc_light": "source.cpp keyword.operator.new: #B5200D", "light_modern": "source.cpp keyword.operator.new: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_clj.json b/extensions/vscode-colorize-tests/test/colorize-results/test_clj.json index 99786f9fec9..23597c44358 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_clj.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_clj.json @@ -45,12 +45,12 @@ "c": "require", "t": "source.clojure meta.expression.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -199,12 +199,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -885,12 +885,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2383,12 +2383,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2565,12 +2565,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3167,12 +3167,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3685,12 +3685,12 @@ "c": "def", "t": "source.clojure meta.expression.clojure meta.definition.global.clojure keyword.control.clojure", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_coffee.json b/extensions/vscode-colorize-tests/test/colorize-results/test_coffee.json index 7f79a5a6251..52efa92c373 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_coffee.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_coffee.json @@ -507,12 +507,12 @@ "c": "extends", "t": "source.coffee meta.class.coffee keyword.control.inheritance.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -941,12 +941,12 @@ "c": "while", "t": "source.coffee keyword.control.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1221,12 +1221,12 @@ "c": "for", "t": "source.coffee keyword.control.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1249,12 +1249,12 @@ "c": "in", "t": "source.coffee keyword.control.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1599,12 +1599,12 @@ "c": "for", "t": "source.coffee keyword.control.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1627,12 +1627,12 @@ "c": "in", "t": "source.coffee keyword.control.coffee", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cpp.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cpp.json index 7c95c4badca..652cc4824eb 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cpp.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cpp.json @@ -31,12 +31,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.include.cpp keyword.control.directive.include.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -45,12 +45,12 @@ "c": "include", "t": "source.cpp meta.preprocessor.include.cpp keyword.control.directive.include.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -115,12 +115,12 @@ "c": "using", "t": "source.cpp meta.using-namespace.cpp keyword.other.using.directive.cpp", "r": { - "dark_plus": "keyword.other.using: #CE92A4", + "dark_plus": "keyword.other.using: #C586C0", "light_plus": "keyword.other.using: #AF00DB", "dark_vs": "keyword: #569CD6", "light_vs": "keyword: #0000FF", "hc_black": "keyword.other.using: #C586C0", - "dark_modern": "keyword.other.using: #CE92A4", + "dark_modern": "keyword.other.using: #C586C0", "hc_light": "keyword.other.using: #B5200D", "light_modern": "keyword.other.using: #AF00DB" } @@ -199,12 +199,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -213,12 +213,12 @@ "c": "define", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -801,12 +801,12 @@ "c": "return", "t": "source.cpp meta.block.class.cpp meta.body.class.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.return.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1347,12 +1347,12 @@ "c": "operator", "t": "source.cpp meta.function.definition.special.operator-overload.cpp meta.head.function.definition.special.operator-overload.cpp keyword.other.operator.overload.cpp", "r": { - "dark_plus": "keyword.other.operator: #CE92A4", + "dark_plus": "keyword.other.operator: #C586C0", "light_plus": "keyword.other.operator: #AF00DB", "dark_vs": "keyword: #569CD6", "light_vs": "keyword: #0000FF", "hc_black": "keyword.other.operator: #C586C0", - "dark_modern": "keyword.other.operator: #CE92A4", + "dark_modern": "keyword.other.operator: #C586C0", "hc_light": "keyword.other.operator: #B5200D", "light_modern": "keyword.other.operator: #AF00DB" } @@ -1501,12 +1501,12 @@ "c": "#", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp punctuation.definition.directive.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1515,12 +1515,12 @@ "c": "define", "t": "source.cpp meta.preprocessor.macro.cpp keyword.control.directive.define.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2775,12 +2775,12 @@ "c": "if", "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.if.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3027,12 +3027,12 @@ "c": "return", "t": "source.cpp meta.function.definition.cpp meta.body.function.definition.cpp keyword.control.return.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json index 293dfcbe2e7..7f4bbb7758b 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cs.json @@ -3,12 +3,12 @@ "c": "using", "t": "source.cs keyword.other.directive.using.cs", "r": { - "dark_plus": "keyword.other.directive.using: #CE92A4", + "dark_plus": "keyword.other.directive.using: #C586C0", "light_plus": "keyword.other.directive.using: #AF00DB", "dark_vs": "keyword: #569CD6", "light_vs": "keyword: #0000FF", "hc_black": "keyword.other.directive.using: #C586C0", - "dark_modern": "keyword.other.directive.using: #CE92A4", + "dark_modern": "keyword.other.directive.using: #C586C0", "hc_light": "keyword.other.directive.using: #B5200D", "light_modern": "keyword.other.directive.using: #AF00DB" } @@ -423,12 +423,12 @@ "c": "if", "t": "source.cs keyword.control.conditional.if.cs", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1487,12 +1487,12 @@ "c": "foreach", "t": "source.cs keyword.control.loop.foreach.cs", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1585,12 +1585,12 @@ "c": "in", "t": "source.cs keyword.control.loop.in.cs", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json index fbfec42db62..4307f03ed1e 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cshtml.json @@ -3,12 +3,12 @@ "c": "@", "t": "text.html.cshtml meta.structure.razor.codeblock keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "{", "t": "text.html.cshtml meta.structure.razor.codeblock keyword.control.razor.directive.codeblock.open", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -311,12 +311,12 @@ "c": "@", "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.comment.razor keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -325,12 +325,12 @@ "c": "*", "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.comment.razor keyword.control.razor.comment.star", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -367,12 +367,12 @@ "c": "*", "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.comment.razor keyword.control.razor.comment.star", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -381,12 +381,12 @@ "c": "@", "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.comment.razor keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -409,12 +409,12 @@ "c": "if", "t": "text.html.cshtml meta.structure.razor.codeblock source.cs meta.statement.if.razor keyword.control.conditional.if.cs", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1473,12 +1473,12 @@ "c": "}", "t": "text.html.cshtml meta.structure.razor.codeblock keyword.control.razor.directive.codeblock.close", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3993,12 +3993,12 @@ "c": "@", "t": "text.html.cshtml meta.comment.razor keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4007,12 +4007,12 @@ "c": "*", "t": "text.html.cshtml meta.comment.razor keyword.control.razor.comment.star", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4049,12 +4049,12 @@ "c": "*", "t": "text.html.cshtml meta.comment.razor keyword.control.razor.comment.star", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4063,12 +4063,12 @@ "c": "@", "t": "text.html.cshtml meta.comment.razor keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4133,12 +4133,12 @@ "c": "@", "t": "text.html.cshtml meta.expression.implicit.cshtml keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4259,12 +4259,12 @@ "c": "@", "t": "text.html.cshtml meta.expression.explicit.cshtml keyword.control.cshtml.transition", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4273,12 +4273,12 @@ "c": "(", "t": "text.html.cshtml meta.expression.explicit.cshtml keyword.control.cshtml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4357,12 +4357,12 @@ "c": ")", "t": "text.html.cshtml meta.expression.explicit.cshtml keyword.control.cshtml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_css.json b/extensions/vscode-colorize-tests/test/colorize-results/test_css.json index 4bb1be19ba2..71722fd00db 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_css.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_css.json @@ -297,12 +297,12 @@ "c": "@", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css punctuation.definition.keyword.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -311,12 +311,12 @@ "c": "import", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -395,12 +395,12 @@ "c": "@", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css punctuation.definition.keyword.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -409,12 +409,12 @@ "c": "import", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -535,12 +535,12 @@ "c": "@", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css punctuation.definition.keyword.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -549,12 +549,12 @@ "c": "import", "t": "source.css meta.at-rule.import.css keyword.control.at-rule.import.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4917,12 +4917,12 @@ "c": "@", "t": "source.css meta.at-rule.header.css keyword.control.at-rule.css punctuation.definition.keyword.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4931,12 +4931,12 @@ "c": "property", "t": "source.css meta.at-rule.header.css keyword.control.at-rule.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_cu.json b/extensions/vscode-colorize-tests/test/colorize-results/test_cu.json index 075453241e2..e926933337e 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_cu.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_cu.json @@ -3,12 +3,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "include", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -87,12 +87,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -101,12 +101,12 @@ "c": "include", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -171,12 +171,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -185,12 +185,12 @@ "c": "include", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -255,12 +255,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -269,12 +269,12 @@ "c": "include", "t": "source.cuda-cpp meta.preprocessor.include.cuda-cpp keyword.control.directive.include.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -339,12 +339,12 @@ "c": "#", "t": "source.cuda-cpp keyword.control.directive.conditional.if.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -353,12 +353,12 @@ "c": "if", "t": "source.cuda-cpp keyword.control.directive.conditional.if.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -381,12 +381,12 @@ "c": "defined", "t": "source.cuda-cpp meta.preprocessor.conditional.cuda-cpp keyword.control.directive.conditional.defined.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -437,12 +437,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.undef.cuda-cpp keyword.control.directive.undef.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -451,12 +451,12 @@ "c": "undef", "t": "source.cuda-cpp meta.preprocessor.undef.cuda-cpp keyword.control.directive.undef.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -493,12 +493,12 @@ "c": "#", "t": "source.cuda-cpp keyword.control.directive.endif.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -507,12 +507,12 @@ "c": "endif", "t": "source.cuda-cpp keyword.control.directive.endif.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -521,12 +521,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -535,12 +535,12 @@ "c": "define", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -661,12 +661,12 @@ "c": "do", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.do.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "if", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp meta.block.cpp keyword.control.if.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1571,12 +1571,12 @@ "c": "while", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.while.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1627,12 +1627,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1641,12 +1641,12 @@ "c": "define", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1767,12 +1767,12 @@ "c": "do", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.do.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1963,12 +1963,12 @@ "c": "if", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp meta.block.cpp keyword.control.if.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2873,12 +2873,12 @@ "c": "while", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.while.cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2929,12 +2929,12 @@ "c": "#", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp punctuation.definition.directive.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2943,12 +2943,12 @@ "c": "define", "t": "source.cuda-cpp meta.preprocessor.macro.cuda-cpp keyword.control.directive.define.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5799,12 +5799,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6345,12 +6345,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8221,12 +8221,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8991,12 +8991,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp meta.block.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -9663,12 +9663,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp meta.block.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13891,12 +13891,12 @@ "c": "for", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp keyword.control.for.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -14157,12 +14157,12 @@ "c": "if", "t": "source.cuda-cpp meta.function.definition.cuda-cpp meta.body.function.definition.cuda-cpp meta.block.cuda-cpp keyword.control.if.cuda-cpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_dart.json b/extensions/vscode-colorize-tests/test/colorize-results/test_dart.json index 5f2fa73661c..dc43f74e3c8 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_dart.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_dart.json @@ -129,12 +129,12 @@ "c": "async", "t": "source.dart keyword.control.dart", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_env.json b/extensions/vscode-colorize-tests/test/colorize-results/test_env.json new file mode 100644 index 00000000000..a0eb219fea5 --- /dev/null +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_env.json @@ -0,0 +1,100 @@ +[ + { + "c": "# dev", + "t": "source.dotenv comment.line.dotenv", + "r": { + "dark_plus": "comment: #6A9955", + "light_plus": "comment: #008000", + "dark_vs": "comment: #6A9955", + "light_vs": "comment: #008000", + "hc_black": "comment: #7CA668", + "dark_modern": "comment: #6A9955", + "hc_light": "comment: #515151", + "light_modern": "comment: #008000" + } + }, + { + "c": "HELLO", + "t": "source.dotenv variable.key.dotenv", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE", + "dark_modern": "variable: #9CDCFE", + "hc_light": "variable: #001080", + "light_modern": "variable: #001080" + } + }, + { + "c": "=", + "t": "source.dotenv keyword.operator.assignment.dotenv", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4", + "dark_modern": "keyword.operator: #D4D4D4", + "hc_light": "keyword.operator: #000000", + "light_modern": "keyword.operator: #000000" + } + }, + { + "c": "123", + "t": "source.dotenv property.value.dotenv", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "dark_modern": "default: #CCCCCC", + "hc_light": "default: #292929", + "light_modern": "default: #3B3B3B" + } + }, + { + "c": "GOODBYE", + "t": "source.dotenv variable.key.dotenv", + "r": { + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "variable: #9CDCFE", + "dark_modern": "variable: #9CDCFE", + "hc_light": "variable: #001080", + "light_modern": "variable: #001080" + } + }, + { + "c": "=", + "t": "source.dotenv keyword.operator.assignment.dotenv", + "r": { + "dark_plus": "keyword.operator: #D4D4D4", + "light_plus": "keyword.operator: #000000", + "dark_vs": "keyword.operator: #D4D4D4", + "light_vs": "keyword.operator: #000000", + "hc_black": "keyword.operator: #D4D4D4", + "dark_modern": "keyword.operator: #D4D4D4", + "hc_light": "keyword.operator: #000000", + "light_modern": "keyword.operator: #000000" + } + }, + { + "c": "456", + "t": "source.dotenv property.value.dotenv", + "r": { + "dark_plus": "default: #D4D4D4", + "light_plus": "default: #000000", + "dark_vs": "default: #D4D4D4", + "light_vs": "default: #000000", + "hc_black": "default: #FFFFFF", + "dark_modern": "default: #CCCCCC", + "hc_light": "default: #292929", + "light_modern": "default: #3B3B3B" + } + } +] \ No newline at end of file diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_go.json b/extensions/vscode-colorize-tests/test/colorize-results/test_go.json index 7473403342c..d6b2ef38ebb 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_go.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_go.json @@ -45,12 +45,12 @@ "c": "import", "t": "source.go keyword.control.import.go", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -983,12 +983,12 @@ "c": "if", "t": "source.go keyword.control.go", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_groovy.json b/extensions/vscode-colorize-tests/test/colorize-results/test_groovy.json index 5bda16b6a10..2fb630ed130 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_groovy.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_groovy.json @@ -325,12 +325,12 @@ "c": "new", "t": "source.groovy keyword.control.new.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3153,12 +3153,12 @@ "c": "new", "t": "source.groovy meta.method-call.groovy keyword.control.new.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4665,12 +4665,12 @@ "c": "assert", "t": "source.groovy meta.declaration.assertion.groovy keyword.control.assert.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5827,12 +5827,12 @@ "c": "if", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5995,12 +5995,12 @@ "c": "else", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6023,12 +6023,12 @@ "c": "if", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6191,12 +6191,12 @@ "c": "else", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6737,12 +6737,12 @@ "c": "assert", "t": "source.groovy meta.declaration.assertion.groovy keyword.control.assert.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7409,12 +7409,12 @@ "c": "for", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7703,12 +7703,12 @@ "c": "for", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8207,12 +8207,12 @@ "c": "for", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8879,12 +8879,12 @@ "c": "for", "t": "source.groovy keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12617,12 +12617,12 @@ "c": "return", "t": "source.groovy meta.definition.method.groovy meta.method.body.java keyword.control.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13107,12 +13107,12 @@ "c": "assert", "t": "source.groovy meta.declaration.assertion.groovy keyword.control.assert.groovy", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_handlebars.json b/extensions/vscode-colorize-tests/test/colorize-results/test_handlebars.json index 82ca1b1508d..2ee4ccd1f3b 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_handlebars.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_handlebars.json @@ -297,12 +297,12 @@ "c": "#if", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -577,12 +577,12 @@ "c": "else", "t": "text.html.handlebars meta.function.inline.else.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "/if", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -885,12 +885,12 @@ "c": "#unless", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1151,12 +1151,12 @@ "c": "/unless", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1389,12 +1389,12 @@ "c": "#each", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1613,12 +1613,12 @@ "c": "/each", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1991,12 +1991,12 @@ "c": "#each", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2621,12 +2621,12 @@ "c": "/each", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_hbs.json b/extensions/vscode-colorize-tests/test/colorize-results/test_hbs.json index dd42bf5eb97..b79247facaa 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_hbs.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_hbs.json @@ -255,12 +255,12 @@ "c": "#each", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -885,12 +885,12 @@ "c": "/each", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1389,12 +1389,12 @@ "c": "#if", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1669,12 +1669,12 @@ "c": "/if", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2173,12 +2173,12 @@ "c": "#each", "t": "text.html.handlebars meta.function.block.start.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2425,12 +2425,12 @@ "c": "/each", "t": "text.html.handlebars meta.function.block.end.handlebars support.constant.handlebars keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_hlsl.json b/extensions/vscode-colorize-tests/test/colorize-results/test_hlsl.json index 481bb17d78a..5325987d5da 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_hlsl.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_hlsl.json @@ -311,12 +311,12 @@ "c": "return", "t": "source.hlsl keyword.control.hlsl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_jl.json b/extensions/vscode-colorize-tests/test/colorize-results/test_jl.json index 8d8bb3c3dc0..deb5a66740a 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_jl.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_jl.json @@ -143,12 +143,12 @@ "c": "end", "t": "source.julia keyword.control.end.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2103,12 +2103,12 @@ "c": "return", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2145,12 +2145,12 @@ "c": "for", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2257,12 +2257,12 @@ "c": "for", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2495,12 +2495,12 @@ "c": "if", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3083,12 +3083,12 @@ "c": "return", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3125,12 +3125,12 @@ "c": "end", "t": "source.julia keyword.control.end.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3153,12 +3153,12 @@ "c": "end", "t": "source.julia keyword.control.end.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3181,12 +3181,12 @@ "c": "end", "t": "source.julia keyword.control.end.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3209,12 +3209,12 @@ "c": "return", "t": "source.julia keyword.control.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3251,12 +3251,12 @@ "c": "end", "t": "source.julia keyword.control.end.julia", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_js.json b/extensions/vscode-colorize-tests/test/colorize-results/test_js.json index 5a3e62e3ac9..c4bb55a1e22 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_js.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_js.json @@ -1669,12 +1669,12 @@ "c": "return", "t": "source.js meta.function.expression.js meta.block.js keyword.control.flow.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2887,12 +2887,12 @@ "c": "return", "t": "source.js meta.function.expression.js meta.block.js keyword.control.flow.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4119,12 +4119,12 @@ "c": "for", "t": "source.js meta.function.js meta.block.js keyword.control.loop.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4847,12 +4847,12 @@ "c": "return", "t": "source.js meta.function.js meta.block.js keyword.control.flow.js", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_jsx.json b/extensions/vscode-colorize-tests/test/colorize-results/test_jsx.json index c1afc2165a9..ed8845d9816 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_jsx.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_jsx.json @@ -311,12 +311,12 @@ "c": "return", "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx keyword.control.flow.js.jsx", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1585,12 +1585,12 @@ "c": "if", "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx keyword.control.conditional.js.jsx", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1949,12 +1949,12 @@ "c": "return", "t": "source.js.jsx meta.var.expr.js.jsx meta.objectliteral.js.jsx meta.object.member.js.jsx meta.function.expression.js.jsx meta.block.js.jsx keyword.control.flow.js.jsx", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_less.json b/extensions/vscode-colorize-tests/test/colorize-results/test_less.json index 073c538de82..a66224dd9e6 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_less.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_less.json @@ -3,12 +3,12 @@ "c": "@", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less punctuation.definition.keyword.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "import", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -101,12 +101,12 @@ "c": "@", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less punctuation.definition.keyword.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -115,12 +115,12 @@ "c": "import", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -241,12 +241,12 @@ "c": "@", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less punctuation.definition.keyword.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -255,12 +255,12 @@ "c": "import", "t": "source.css.less meta.at-rule.import.less keyword.control.at-rule.import.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -703,12 +703,12 @@ "c": "when", "t": "source.css.less meta.selector.less meta.conditional.guarded-namespace.less keyword.control.conditional.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1221,12 +1221,12 @@ "c": "when", "t": "source.css.less meta.selector.less meta.conditional.guarded-namespace.less keyword.control.conditional.less", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_lua.json b/extensions/vscode-colorize-tests/test/colorize-results/test_lua.json index e56e3ebedc2..c7a93a0446f 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_lua.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_lua.json @@ -59,12 +59,12 @@ "c": "function", "t": "source.lua meta.function.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -171,12 +171,12 @@ "c": "if", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -283,12 +283,12 @@ "c": "then", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -311,12 +311,12 @@ "c": "return", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -367,12 +367,12 @@ "c": "else", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -395,12 +395,12 @@ "c": "return", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -577,12 +577,12 @@ "c": "end", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -605,12 +605,12 @@ "c": "end", "t": "source.lua keyword.control.lua", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_m.json b/extensions/vscode-colorize-tests/test/colorize-results/test_m.json index 0c0e4587fd6..c6c7e2d6278 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_m.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_m.json @@ -59,12 +59,12 @@ "c": "#", "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc punctuation.definition.directive.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -73,12 +73,12 @@ "c": "import", "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -143,12 +143,12 @@ "c": "#", "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc punctuation.definition.directive.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -157,12 +157,12 @@ "c": "import", "t": "source.objc meta.preprocessor.include.objc keyword.control.directive.import.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1809,12 +1809,12 @@ "c": "if", "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc meta.bracketed.objc meta.function-call.objc meta.block.objc keyword.control.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2159,12 +2159,12 @@ "c": "return", "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4021,12 +4021,12 @@ "c": "return", "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4077,12 +4077,12 @@ "c": "return", "t": "source.objc meta.implementation.objc meta.scope.implementation.objc meta.function-with-body.objc meta.block.objc keyword.control.objc", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_mm.json b/extensions/vscode-colorize-tests/test/colorize-results/test_mm.json index da24fb8688d..eeb16d5b737 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_mm.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_mm.json @@ -59,12 +59,12 @@ "c": "#", "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp punctuation.definition.directive.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -73,12 +73,12 @@ "c": "import", "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -143,12 +143,12 @@ "c": "#", "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp punctuation.definition.directive.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -157,12 +157,12 @@ "c": "import", "t": "source.objcpp meta.preprocessor.include.objcpp keyword.control.directive.import.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1697,12 +1697,12 @@ "c": "if", "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp meta.bracket.square.access.objcpp keyword.control.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2075,12 +2075,12 @@ "c": "return", "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3811,12 +3811,12 @@ "c": "return", "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3867,12 +3867,12 @@ "c": "return", "t": "source.objcpp meta.implementation.objcpp meta.scope.implementation.objcpp meta.function-with-body.objcpp meta.block.objcpp keyword.control.objcpp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_php.json b/extensions/vscode-colorize-tests/test/colorize-results/test_php.json index 200544164a5..ea79b0e2006 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_php.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_php.json @@ -1347,12 +1347,12 @@ "c": "for", "t": "text.html.php meta.embedded.block.php source.php keyword.control.for.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2075,12 +2075,12 @@ "c": "if", "t": "text.html.php meta.embedded.block.php source.php keyword.control.if.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2411,12 +2411,12 @@ "c": "else", "t": "text.html.php meta.embedded.block.php source.php keyword.control.else.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3419,12 +3419,12 @@ "c": "for", "t": "text.html.php meta.embedded.block.php source.php keyword.control.for.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3783,12 +3783,12 @@ "c": "if", "t": "text.html.php meta.embedded.block.php source.php keyword.control.if.php", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_pl.json b/extensions/vscode-colorize-tests/test/colorize-results/test_pl.json index b10e49c8246..1a80edc135c 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_pl.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_pl.json @@ -3,12 +3,12 @@ "c": "use", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -395,12 +395,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -689,12 +689,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1613,12 +1613,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1907,12 +1907,12 @@ "c": "return", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2061,12 +2061,12 @@ "c": "while", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2523,12 +2523,12 @@ "c": "while", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2775,12 +2775,12 @@ "c": "if", "t": "source.perl keyword.control.perl", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_ps1.json b/extensions/vscode-colorize-tests/test/colorize-results/test_ps1.json index b919dfdabda..7fee15950e9 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_ps1.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_ps1.json @@ -143,12 +143,12 @@ "c": "try", "t": "source.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -535,12 +535,12 @@ "c": "return", "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "catch", "t": "source.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -801,12 +801,12 @@ "c": "throw", "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1081,12 +1081,12 @@ "c": "param", "t": "source.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1361,12 +1361,12 @@ "c": "foreach", "t": "source.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1431,12 +1431,12 @@ "c": "in", "t": "source.powershell meta.scriptblock.powershell meta.group.simple.subexpression.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1613,12 +1613,12 @@ "c": "if", "t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2285,12 +2285,12 @@ "c": "if", "t": "source.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2817,12 +2817,12 @@ "c": "if", "t": "source.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3167,12 +3167,12 @@ "c": "else", "t": "source.powershell keyword.control.powershell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_py.json b/extensions/vscode-colorize-tests/test/colorize-results/test_py.json index 28d7010a42b..e8d718cad72 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_py.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_py.json @@ -3,12 +3,12 @@ "c": "from", "t": "source.python keyword.control.import.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -31,12 +31,12 @@ "c": "import", "t": "source.python keyword.control.import.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -759,12 +759,12 @@ "c": "return", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1109,12 +1109,12 @@ "c": "for", "t": "source.python meta.function.python meta.function.parameters.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1165,12 +1165,12 @@ "c": "in", "t": "source.python meta.function.python meta.function.parameters.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1221,12 +1221,12 @@ "c": "if", "t": "source.python meta.function.python meta.function.parameters.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1333,12 +1333,12 @@ "c": "else", "t": "source.python meta.function.python meta.function.parameters.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1501,12 +1501,12 @@ "c": "pass", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1515,12 +1515,12 @@ "c": "pass", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1683,12 +1683,12 @@ "c": "for", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1711,12 +1711,12 @@ "c": "in", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1823,12 +1823,12 @@ "c": "yield", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3237,12 +3237,12 @@ "c": "if", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3335,12 +3335,12 @@ "c": "return", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3391,12 +3391,12 @@ "c": "elif", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3629,12 +3629,12 @@ "c": "return", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3825,12 +3825,12 @@ "c": "else", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3867,12 +3867,12 @@ "c": "return", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5127,12 +5127,12 @@ "c": "if", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5519,12 +5519,12 @@ "c": "return", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6093,12 +6093,12 @@ "c": "while", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6163,12 +6163,12 @@ "c": "try", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6429,12 +6429,12 @@ "c": "break", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6457,12 +6457,12 @@ "c": "except", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6611,12 +6611,12 @@ "c": "async", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6639,12 +6639,12 @@ "c": "with", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6695,12 +6695,12 @@ "c": "as", "t": "source.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7479,12 +7479,12 @@ "c": ">>> ", "t": "source.python string.quoted.docstring.raw.multi.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7521,12 +7521,12 @@ "c": "... ", "t": "source.python string.quoted.docstring.raw.multi.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7563,12 +7563,12 @@ "c": "... ", "t": "source.python string.quoted.docstring.raw.multi.python keyword.control.flow.python", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_r.json b/extensions/vscode-colorize-tests/test/colorize-results/test_r.json index 17fbf383edd..4d56b651660 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_r.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_r.json @@ -451,12 +451,12 @@ "c": "function", "t": "source.r meta.function.r keyword.control.r", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_rb.json b/extensions/vscode-colorize-tests/test/colorize-results/test_rb.json index b93bf251b67..032617573e4 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_rb.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_rb.json @@ -115,12 +115,12 @@ "c": "module", "t": "source.ruby meta.module.ruby keyword.control.module.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -297,12 +297,12 @@ "c": "class", "t": "source.ruby meta.class.ruby keyword.control.class.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1375,12 +1375,12 @@ "c": "def", "t": "source.ruby meta.function.method.with-arguments.ruby keyword.control.def.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1669,12 +1669,12 @@ "c": "super", "t": "source.ruby keyword.control.pseudo-method.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2047,12 +2047,12 @@ "c": "if", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2243,12 +2243,12 @@ "c": "unless", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3125,12 +3125,12 @@ "c": "if", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3433,12 +3433,12 @@ "c": "else", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3573,12 +3573,12 @@ "c": "end", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4091,12 +4091,12 @@ "c": "end", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4119,12 +4119,12 @@ "c": "end", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4133,12 +4133,12 @@ "c": "end", "t": "source.ruby keyword.control.ruby", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json b/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json index 825becadb30..aa8468c4d8a 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_rst.json @@ -87,12 +87,12 @@ "c": "1. ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -115,12 +115,12 @@ "c": "2. ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -143,12 +143,12 @@ "c": " - ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -171,12 +171,12 @@ "c": " - ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -199,12 +199,12 @@ "c": "3. ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -269,12 +269,12 @@ "c": "::", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -479,12 +479,12 @@ "c": "| ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -507,12 +507,12 @@ "c": "| ", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -535,12 +535,12 @@ "c": "+-------------+--------------+", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -549,12 +549,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -577,12 +577,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -605,12 +605,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -619,12 +619,12 @@ "c": "+=============+==============+", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -633,12 +633,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -661,12 +661,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -689,12 +689,12 @@ "c": "|", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -703,12 +703,12 @@ "c": "+-------------+--------------+", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -717,12 +717,12 @@ "c": "============ ============", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -745,12 +745,12 @@ "c": "============ ============", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -773,12 +773,12 @@ "c": "============ ============", "t": "source.rst keyword.control.table", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -829,12 +829,12 @@ "c": ">>>", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1221,12 +1221,12 @@ "c": ".. image::", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1277,12 +1277,12 @@ "c": ":sub:", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1305,12 +1305,12 @@ "c": ":sup:", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1431,12 +1431,12 @@ "c": "..", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1487,12 +1487,12 @@ "c": "replace::", "t": "source.rst keyword.control", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_scss.json b/extensions/vscode-colorize-tests/test/colorize-results/test_scss.json index dfae042fd1b..933ebf2ba5c 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_scss.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_scss.json @@ -115,12 +115,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.charset.scss keyword.control.at-rule.charset.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -129,12 +129,12 @@ "c": "charset", "t": "source.css.scss meta.at-rule.charset.scss keyword.control.at-rule.charset.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7059,12 +7059,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.function.scss keyword.control.at-rule.function.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7073,12 +7073,12 @@ "c": "function", "t": "source.css.scss meta.at-rule.function.scss keyword.control.at-rule.function.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7199,12 +7199,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7213,12 +7213,12 @@ "c": "return", "t": "source.css.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7787,12 +7787,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7801,12 +7801,12 @@ "c": "import", "t": "source.css.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8025,12 +8025,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8039,12 +8039,12 @@ "c": "import", "t": "source.css.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8333,12 +8333,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8347,12 +8347,12 @@ "c": "import", "t": "source.css.scss meta.property-list.scss meta.at-rule.import.scss keyword.control.at-rule.import.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8655,12 +8655,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.media.scss keyword.control.at-rule.media.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8669,12 +8669,12 @@ "c": "media", "t": "source.css.scss meta.property-list.scss meta.at-rule.media.scss keyword.control.at-rule.media.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -9425,12 +9425,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -9439,12 +9439,12 @@ "c": "extend", "t": "source.css.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10069,12 +10069,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10083,12 +10083,12 @@ "c": "extend", "t": "source.css.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10237,12 +10237,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.warn.scss keyword.control.warn.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10251,12 +10251,12 @@ "c": "debug", "t": "source.css.scss meta.at-rule.warn.scss keyword.control.warn.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10293,12 +10293,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10307,12 +10307,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10461,12 +10461,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10475,12 +10475,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10601,12 +10601,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.property-list.scss meta.at-rule.warn.scss keyword.control.warn.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10615,12 +10615,12 @@ "c": "warn", "t": "source.css.scss meta.property-list.scss meta.property-list.scss meta.at-rule.warn.scss keyword.control.warn.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10951,12 +10951,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10965,12 +10965,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -11091,12 +11091,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.property-list.scss meta.at-rule.warn.scss keyword.control.warn.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -11105,12 +11105,12 @@ "c": "warn", "t": "source.css.scss meta.property-list.scss meta.property-list.scss meta.at-rule.warn.scss keyword.control.warn.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -11833,12 +11833,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -11847,12 +11847,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12197,12 +12197,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12211,12 +12211,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12505,12 +12505,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12519,12 +12519,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12883,12 +12883,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12897,12 +12897,12 @@ "c": "if", "t": "source.css.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13121,12 +13121,12 @@ "c": "@", "t": "source.css.scss meta.property-list.scss meta.at-rule.else.scss keyword.control.else.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13135,12 +13135,12 @@ "c": "else ", "t": "source.css.scss meta.property-list.scss meta.at-rule.else.scss keyword.control.else.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13331,12 +13331,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.for.scss keyword.control.for.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13345,12 +13345,12 @@ "c": "for", "t": "source.css.scss meta.at-rule.for.scss keyword.control.for.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13401,12 +13401,12 @@ "c": "from", "t": "source.css.scss meta.at-rule.for.scss keyword.control.operator", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13457,12 +13457,12 @@ "c": "through", "t": "source.css.scss meta.at-rule.for.scss keyword.control.operator", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13877,12 +13877,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss keyword.control.each.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13891,12 +13891,12 @@ "c": "each", "t": "source.css.scss meta.at-rule.each.scss keyword.control.each.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -13947,12 +13947,12 @@ "c": "in", "t": "source.css.scss meta.at-rule.each.scss keyword.control.operator", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -14479,12 +14479,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss keyword.control.while.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -14493,12 +14493,12 @@ "c": "while", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss keyword.control.while.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15109,12 +15109,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.function.scss keyword.control.at-rule.function.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15123,12 +15123,12 @@ "c": "function", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.function.scss keyword.control.at-rule.function.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15291,12 +15291,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.for.scss keyword.control.for.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15305,12 +15305,12 @@ "c": "for", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.for.scss keyword.control.for.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15361,12 +15361,12 @@ "c": "from", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.for.scss keyword.control.operator", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15417,12 +15417,12 @@ "c": "to", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.for.scss keyword.control.operator", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15501,12 +15501,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -15515,12 +15515,12 @@ "c": "if", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16005,12 +16005,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16019,12 +16019,12 @@ "c": "return", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16173,12 +16173,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16187,12 +16187,12 @@ "c": "return", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.return.scss keyword.control.return.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16299,12 +16299,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16313,12 +16313,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16915,12 +16915,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -16929,12 +16929,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17139,12 +17139,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17153,12 +17153,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17755,12 +17755,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17769,12 +17769,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17937,12 +17937,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17951,12 +17951,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -18413,12 +18413,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -18427,12 +18427,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -18889,12 +18889,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -18903,12 +18903,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19561,12 +19561,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19575,12 +19575,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19743,12 +19743,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19757,12 +19757,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19925,12 +19925,12 @@ "c": "@content", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.content.scss keyword.control.content.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -19995,12 +19995,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20009,12 +20009,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20331,12 +20331,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.if.scss keyword.control.if.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20345,12 +20345,12 @@ "c": "if", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.if.scss keyword.control.if.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20429,12 +20429,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20443,12 +20443,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20919,12 +20919,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.page.scss keyword.control.at-rule.page.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -20933,12 +20933,12 @@ "c": "page", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.at-rule.page.scss keyword.control.at-rule.page.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -21787,12 +21787,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -21801,12 +21801,12 @@ "c": "extend", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22473,12 +22473,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22487,12 +22487,12 @@ "c": "mixin", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.mixin.scss keyword.control.at-rule.mixin.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22641,12 +22641,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22655,12 +22655,12 @@ "c": "extend", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22767,12 +22767,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -22781,12 +22781,12 @@ "c": "extend", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.extend.scss keyword.control.at-rule.extend.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -23243,12 +23243,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -23257,12 +23257,12 @@ "c": "include", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.property-list.scss meta.at-rule.include.scss keyword.control.at-rule.include.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -23439,12 +23439,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.fontface.scss keyword.control.at-rule.fontface.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -23453,12 +23453,12 @@ "c": "font-face", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.fontface.scss keyword.control.at-rule.fontface.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -24531,12 +24531,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -24545,12 +24545,12 @@ "c": "-webkit-keyframes", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -24937,12 +24937,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -24951,12 +24951,12 @@ "c": "-moz-keyframes", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -25721,12 +25721,12 @@ "c": "@", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss punctuation.definition.keyword.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -25735,12 +25735,12 @@ "c": "keyframes", "t": "source.css.scss meta.at-rule.each.scss meta.at-rule.while.scss meta.property-list.scss meta.at-rule.keyframes.scss keyword.control.at-rule.keyframes.scss", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_sh.json b/extensions/vscode-colorize-tests/test/colorize-results/test_sh.json index fc06d9f4d9a..0dde2e0748e 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_sh.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_sh.json @@ -31,12 +31,12 @@ "c": "if", "t": "source.shell meta.scope.if-block.shell keyword.control.if.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -297,12 +297,12 @@ "c": "then", "t": "source.shell meta.scope.if-block.shell keyword.control.then.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1235,12 +1235,12 @@ "c": "else", "t": "source.shell meta.scope.if-block.shell keyword.control.else.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1529,12 +1529,12 @@ "c": "fi", "t": "source.shell meta.scope.if-block.shell keyword.control.fi.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2607,12 +2607,12 @@ "c": "if", "t": "source.shell meta.function.shell meta.function.body.shell meta.scope.if-block.shell keyword.control.if.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2873,12 +2873,12 @@ "c": "then", "t": "source.shell meta.function.shell meta.function.body.shell meta.scope.if-block.shell keyword.control.then.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3055,12 +3055,12 @@ "c": "else", "t": "source.shell meta.function.shell meta.function.body.shell meta.scope.if-block.shell keyword.control.else.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3237,12 +3237,12 @@ "c": "fi", "t": "source.shell meta.function.shell meta.function.body.shell meta.scope.if-block.shell keyword.control.fi.shell", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3345,4 +3345,4 @@ "light_modern": "string: #A31515" } } -] \ No newline at end of file +] diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_swift.json b/extensions/vscode-colorize-tests/test/colorize-results/test_swift.json index c84a0185f31..8b1b64f71f5 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_swift.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_swift.json @@ -647,12 +647,12 @@ "c": "for", "t": "source.swift meta.definition.function.swift meta.definition.function.body.swift keyword.control.loop.swift", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -675,12 +675,12 @@ "c": "in", "t": "source.swift meta.definition.function.swift meta.definition.function.body.swift keyword.control.loop.swift", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -731,12 +731,12 @@ "c": "if", "t": "source.swift meta.definition.function.swift meta.definition.function.body.swift keyword.control.branch.swift", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -857,12 +857,12 @@ "c": "return", "t": "source.swift meta.definition.function.swift meta.definition.function.body.swift keyword.control.transfer.swift", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -969,12 +969,12 @@ "c": "return", "t": "source.swift meta.definition.function.swift meta.definition.function.body.swift keyword.control.transfer.swift", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_tex.json b/extensions/vscode-colorize-tests/test/colorize-results/test_tex.json index f2b21f30a78..7cc786089fd 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_tex.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_tex.json @@ -3,12 +3,12 @@ "c": "\\", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex punctuation.definition.function.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -17,12 +17,12 @@ "c": "documentclass", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -115,12 +115,12 @@ "c": "\\", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex punctuation.definition.function.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -129,12 +129,12 @@ "c": "usepackage", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -185,12 +185,12 @@ "c": "\\", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex punctuation.definition.function.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -199,12 +199,12 @@ "c": "usepackage", "t": "text.tex.latex meta.preamble.latex keyword.control.preamble.latex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -507,12 +507,12 @@ "c": "\\\\", "t": "text.tex.latex keyword.control.newline.tex", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_ts.json b/extensions/vscode-colorize-tests/test/colorize-results/test_ts.json index c87cf0f039c..68504d08d8e 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_ts.json @@ -171,12 +171,12 @@ "c": "export", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1347,12 +1347,12 @@ "c": "export", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts keyword.control.export.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4021,12 +4021,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4539,12 +4539,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.arrow.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5533,12 +5533,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.arrow.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6807,12 +6807,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7171,12 +7171,12 @@ "c": "else", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7199,12 +7199,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7451,12 +7451,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7857,12 +7857,12 @@ "c": "for", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8193,12 +8193,12 @@ "c": "for", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.block.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8543,12 +8543,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.block.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8781,12 +8781,12 @@ "c": "continue", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.block.ts meta.block.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8823,12 +8823,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.block.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -9327,12 +9327,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -9705,12 +9705,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10223,12 +10223,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10293,12 +10293,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -10769,12 +10769,12 @@ "c": "for", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -11259,12 +11259,12 @@ "c": "for", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts meta.block.ts keyword.control.loop.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12085,12 +12085,12 @@ "c": "return", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.flow.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -12365,12 +12365,12 @@ "c": "if", "t": "source.ts meta.namespace.declaration.ts meta.block.ts meta.class.ts meta.method.declaration.ts meta.block.ts keyword.control.conditional.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_vb.json b/extensions/vscode-colorize-tests/test/colorize-results/test_vb.json index 6706deb203d..2d8b7a5fbf2 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_vb.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_vb.json @@ -1137,12 +1137,12 @@ "c": "Do", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1165,12 +1165,12 @@ "c": "While", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1585,12 +1585,12 @@ "c": "If", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1795,12 +1795,12 @@ "c": "Then", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2369,12 +2369,12 @@ "c": "If", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2397,12 +2397,12 @@ "c": "Then", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2425,12 +2425,12 @@ "c": "Exit Sub", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2691,12 +2691,12 @@ "c": "End If", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2747,12 +2747,12 @@ "c": "Loop", "t": "source.asp.vb.net keyword.control.asp", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_yaml.json b/extensions/vscode-colorize-tests/test/colorize-results/test_yaml.json index 6ca362c7a18..0908e19e3ea 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_yaml.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_yaml.json @@ -115,12 +115,12 @@ "c": "&", "t": "source.yaml meta.stream.yaml meta.document.yaml meta.block.sequence.yaml meta.mapping.yaml meta.map.value.yaml keyword.control.flow.anchor.yaml punctuation.definition.anchor.yaml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -507,12 +507,12 @@ "c": "*", "t": "source.yaml meta.stream.yaml meta.document.yaml meta.block.sequence.yaml meta.mapping.yaml meta.map.value.yaml keyword.control.flow.alias.yaml punctuation.definition.alias.yaml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -647,12 +647,12 @@ "c": "*", "t": "source.yaml meta.stream.yaml meta.document.yaml meta.block.sequence.yaml meta.mapping.yaml meta.map.value.yaml keyword.control.flow.alias.yaml punctuation.definition.alias.yaml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -829,12 +829,12 @@ "c": "*", "t": "source.yaml meta.stream.yaml meta.document.yaml meta.block.sequence.yaml meta.mapping.yaml meta.map.value.yaml keyword.control.flow.alias.yaml punctuation.definition.alias.yaml", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-241001_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-241001_ts.json index 2c4294c18a9..a5a8c33bf22 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-241001_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-241001_ts.json @@ -577,12 +577,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2047,12 +2047,12 @@ "c": "import", "t": "new.expr.ts keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue11_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue11_ts.json index fef5b2f06f4..5e8481b6289 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue11_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue11_ts.json @@ -73,12 +73,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -367,12 +367,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -591,12 +591,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -815,12 +815,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1039,12 +1039,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1179,12 +1179,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2299,12 +2299,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue241715_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue241715_ts.json index 879e9e26c2c..c7c13ff004c 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue241715_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue241715_ts.json @@ -409,12 +409,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -703,12 +703,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1137,12 +1137,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1459,12 +1459,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1529,12 +1529,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -1711,12 +1711,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2313,12 +2313,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2579,12 +2579,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5431_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5431_ts.json index 067fee14bc1..2a122f89471 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5431_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5431_ts.json @@ -409,12 +409,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5465_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5465_ts.json index 1cfeec33c2e..100bf5c3d07 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5465_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-issue5465_ts.json @@ -87,12 +87,12 @@ "c": "yield", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -157,12 +157,12 @@ "c": "yield", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-keywords_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-keywords_ts.json index c6617c9f426..6753ae3fa4c 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-keywords_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test-keywords_ts.json @@ -3,12 +3,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json index e7bf6aacd02..73b86795d8a 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_css.json @@ -101,12 +101,12 @@ "c": "@import", "t": "keyword.control.at-rule.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -157,12 +157,12 @@ "c": "@import", "t": "keyword.control.at-rule.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -255,12 +255,12 @@ "c": "@import", "t": "keyword.control.at-rule.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3307,12 +3307,12 @@ "c": "@property", "t": "keyword.control.at-rule.css", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_env.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_env.json new file mode 100644 index 00000000000..0637a088a01 --- /dev/null +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_env.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_ts.json b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_ts.json index d4c0361052c..b31e6daa154 100644 --- a/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_ts.json +++ b/extensions/vscode-colorize-tests/test/colorize-tree-sitter-results/test_ts.json @@ -59,12 +59,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -801,12 +801,12 @@ "c": "export", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2579,12 +2579,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -2943,12 +2943,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -3671,12 +3671,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4609,12 +4609,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4833,12 +4833,12 @@ "c": "else", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -4847,12 +4847,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5015,12 +5015,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5253,12 +5253,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5477,12 +5477,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5701,12 +5701,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5841,12 +5841,12 @@ "c": "continue", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -5869,12 +5869,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6233,12 +6233,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6457,12 +6457,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6765,12 +6765,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -6807,12 +6807,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7171,12 +7171,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -7493,12 +7493,12 @@ "c": "for", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8109,12 +8109,12 @@ "c": "return", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } @@ -8277,12 +8277,12 @@ "c": "if", "t": "keyword.control.ts", "r": { - "dark_plus": "keyword.control: #CE92A4", + "dark_plus": "keyword.control: #C586C0", "light_plus": "keyword.control: #AF00DB", "dark_vs": "keyword.control: #569CD6", "light_vs": "keyword.control: #0000FF", "hc_black": "keyword.control: #C586C0", - "dark_modern": "keyword.control: #CE92A4", + "dark_modern": "keyword.control: #C586C0", "hc_light": "keyword.control: #B5200D", "light_modern": "keyword.control: #AF00DB" } diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index c96c1d5894f..0990d7c5036 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -18,7 +18,7 @@ ], "scripts": { "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", - "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-test-resolver" + "vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.mjs compile-extension:vscode-test-resolver" }, "activationEvents": [ "onResolveRemoteAuthority:test", diff --git a/extensions/microsoft-authentication/src/browser/fetch.ts b/gulpfile.mjs similarity index 91% rename from extensions/microsoft-authentication/src/browser/fetch.ts rename to gulpfile.mjs index c61281ca8f8..21d7757da7d 100644 --- a/extensions/microsoft-authentication/src/browser/fetch.ts +++ b/gulpfile.mjs @@ -2,5 +2,4 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ - -export default fetch; +import './build/gulpfile.mjs'; diff --git a/package-lock.json b/package-lock.json index f26fb7c358c..ff7180b2fe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "code-oss-dev", - "version": "1.106.0", + "version": "1.107.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "code-oss-dev", - "version": "1.106.0", + "version": "1.107.0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -15,28 +15,28 @@ "@parcel/watcher": "parcel-bundler/watcher#1ca032aa8339260a8a3bcf825c3a1a71e3e43542", "@types/semver": "^7.5.8", "@vscode/deviceid": "^0.1.1", - "@vscode/iconv-lite-umd": "0.7.0", + "@vscode/iconv-lite-umd": "0.7.1", "@vscode/policy-watcher": "^1.3.2", - "@vscode/proxy-agent": "^0.35.0", + "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", "@vscode/sqlite3": "5.1.8-vscode", "@vscode/sudo-prompt": "9.3.1", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.5.0", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/headless": "^5.6.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/headless": "^5.6.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "jschardet": "3.1.4", @@ -48,7 +48,7 @@ "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta35", "open": "^10.1.2", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "undici": "^7.9.0", "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", @@ -58,7 +58,7 @@ "yazl": "^2.4.3" }, "devDependencies": { - "@playwright/test": "^1.55.1", + "@playwright/test": "^1.56.1", "@stylistic/eslint-plugin-ts": "^2.8.0", "@types/cookie": "^0.3.3", "@types/debug": "^4.1.5", @@ -68,7 +68,7 @@ "@types/kerberos": "^1.1.2", "@types/minimist": "^1.2.1", "@types/mocha": "^10.0.10", - "@types/node": "22.x", + "@types/node": "^22.18.10", "@types/sinon": "^10.0.2", "@types/sinon-test": "^2.4.2", "@types/trusted-types": "^2.0.7", @@ -80,7 +80,7 @@ "@types/yauzl": "^2.10.0", "@types/yazl": "^2.4.2", "@typescript-eslint/utils": "^8.45.0", - "@typescript/native-preview": "^7.0.0-dev.20250812.1", + "@typescript/native-preview": "^7.0.0-dev.20251117", "@vscode/gulp-electron": "^1.38.2", "@vscode/l10n-dev": "0.0.35", "@vscode/telemetry-extractor": "^1.10.2", @@ -89,7 +89,7 @@ "@vscode/test-web": "^0.0.62", "@vscode/v8-heap-parser": "^0.1.0", "@vscode/vscode-perf": "^0.0.19", - "@webgpu/types": "^0.1.44", + "@webgpu/types": "^0.1.66", "ansi-colors": "^3.2.3", "asar": "^3.0.3", "chromium-pickle-js": "^0.2.0", @@ -98,7 +98,7 @@ "css-loader": "^6.9.1", "debounce": "^1.0.0", "deemon": "^1.13.6", - "electron": "37.6.0", + "electron": "39.2.0", "eslint": "^9.36.0", "eslint-formatter-compact": "^8.40.0", "eslint-plugin-header": "3.1.1", @@ -152,7 +152,7 @@ "ts-node": "^10.9.1", "tsec": "0.2.7", "tslib": "^2.6.3", - "typescript": "^6.0.0-dev.20250922", + "typescript": "^6.0.0-dev.20251117", "typescript-eslint": "^8.45.0", "util": "^0.12.4", "webpack": "^5.94.0", @@ -1721,13 +1721,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.55.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.1.tgz", - "integrity": "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.55.1" + "playwright": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -2083,13 +2083,13 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", + "version": "22.18.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.13.tgz", + "integrity": "sha512-Bo45YKIjnmFtv6I1TuC8AaHBbqXtIo+Om5fE4QiU1Tj8QR/qt+8O3BAtOimG5IFmwaWiPmB3Mv3jtYzBA4Us2A==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/node-fetch": { @@ -2103,14 +2103,17 @@ } }, "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz", + "integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -2506,28 +2509,28 @@ } }, "node_modules/@typescript/native-preview": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-B7svR7Fm4cLLL8ARBVc9Xx2KFcZuCkNsdR7LBZjSqaDM6am11XizhPORrI7x8rlVQ71CBoQVgOp/2/Bn3x+OgA==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview/-/native-preview-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-JgKY4Q6jRCszCJ46c8tVrGVnmdiRPSKTW0UQvcyxdI7LG9NYMchJ/W7iUyFZVjG8BV1iUTl3DYml1xErPHLKeg==", "dev": true, "license": "Apache-2.0", "bin": { "tsgo": "bin/tsgo.js" }, "optionalDependencies": { - "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20250922.1", - "@typescript/native-preview-darwin-x64": "7.0.0-dev.20250922.1", - "@typescript/native-preview-linux-arm": "7.0.0-dev.20250922.1", - "@typescript/native-preview-linux-arm64": "7.0.0-dev.20250922.1", - "@typescript/native-preview-linux-x64": "7.0.0-dev.20250922.1", - "@typescript/native-preview-win32-arm64": "7.0.0-dev.20250922.1", - "@typescript/native-preview-win32-x64": "7.0.0-dev.20250922.1" + "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20251117.1", + "@typescript/native-preview-darwin-x64": "7.0.0-dev.20251117.1", + "@typescript/native-preview-linux-arm": "7.0.0-dev.20251117.1", + "@typescript/native-preview-linux-arm64": "7.0.0-dev.20251117.1", + "@typescript/native-preview-linux-x64": "7.0.0-dev.20251117.1", + "@typescript/native-preview-win32-arm64": "7.0.0-dev.20251117.1", + "@typescript/native-preview-win32-x64": "7.0.0-dev.20251117.1" } }, "node_modules/@typescript/native-preview-darwin-arm64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-R4sKE/cQYMGrmaz8OBnnseABdB6W0ZCQ9muHQnoxuyukf7m0wLLqvGNorQZSWVl9xQ7qNniXcZJlCKp4JmRr6w==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-arm64/-/native-preview-darwin-arm64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-O7Hhb9m8AZJCAUSBbGmZs7Vm890Kh5Z3xAAASs+L4thtPM0oRckeaoXLvHeE9Qy1p8qG//EmZ3+uSdtUTV4wqg==", "cpu": [ "arm64" ], @@ -2539,9 +2542,9 @@ ] }, "node_modules/@typescript/native-preview-darwin-x64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-Hhh+9e/75ZQxdatdA8TFKOKjPwqjXWNI2a8vswvMU6zOmiVYZoYaUGEGFhk0W1WPGnt/kZSM1Mb4a9nVaEwhZQ==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-darwin-x64/-/native-preview-darwin-x64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-/I/iWWvUvuy8BK0bXn5Kz6z2QwknwD2kl2estQxgsz9VgHHyLSyjAg7c18pX/re0Z9ISPz7wutEKabzdtRW8Uw==", "cpu": [ "x64" ], @@ -2553,9 +2556,9 @@ ] }, "node_modules/@typescript/native-preview-linux-arm": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-4JbSk4B0SUo2c+S9YKGLAaMQXA16Pd9Cd7GLhMiABRtOLEHFDAaFmFbVoGYX5Dyicix711oziX/WAhD6nuC73A==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm/-/native-preview-linux-arm-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-Mfnc8CytGICsYJCMbu3FwE/KDcVg4/QTFix6O31oUkj9ERp3zbSePVMQulkJTH2vuhDvJnVISHzIYawtq5QPTQ==", "cpu": [ "arm" ], @@ -2567,9 +2570,9 @@ ] }, "node_modules/@typescript/native-preview-linux-arm64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-Rw74z0tf0NEujnl0W58fQ5pbh8P1fr2ujQTMkQYz9WpH+hYuysQgcOiDEoht62CxtLHflexu3dUWJI8/LUPyHA==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-arm64/-/native-preview-linux-arm64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-YSkmJb4/WrS6ZMEJSDbv5o2Garms3+3yKsH+Y3JLUab0namf1Br7T53ydW7ijV2rE7j9DgJs9P+GNu8753St3Q==", "cpu": [ "arm64" ], @@ -2581,9 +2584,9 @@ ] }, "node_modules/@typescript/native-preview-linux-x64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-lY6JAZgzeJxLwciC8Wc9l7OlDYwVbuo3JK+qHfLlyxu8h1Q3cGF5VMpgSlAj9CKLDQ0h4kDAecLLiEEOod78aw==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-linux-x64/-/native-preview-linux-x64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-R5KvnKuGsbozjHbmA+zPa4xVkQSutvtU9/PQJ7vjJL0xsvSsRUgOE2V2jlT+KnfjAhYVoIg2njtHdf0uv5k9Ow==", "cpu": [ "x64" ], @@ -2595,9 +2598,9 @@ ] }, "node_modules/@typescript/native-preview-win32-arm64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-pGzWqNx7x6Sqs20Ea5Xn/JC9eZ9Do6bu6K+dmfpewYYhwUv8jiOhh+fr9TJFZ8MlaZDTp9FclQIGpW+2MZ8UOw==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-arm64/-/native-preview-win32-arm64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-xfEwDD9BwCm2gFf0AePfvXxjgQ/EDBDLRbSejtShTSFwrgdnRJ7iW63/ns/i31qLesTzGZaLxeAV8zgh6C2Ibg==", "cpu": [ "arm64" ], @@ -2609,9 +2612,9 @@ ] }, "node_modules/@typescript/native-preview-win32-x64": { - "version": "7.0.0-dev.20250922.1", - "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20250922.1.tgz", - "integrity": "sha512-RoNm3P69p5F/ZJ7O7nIoUJB0OVG5nGIEVzP/VF2lm8jBbDN8aCRNT+DkZrQvdXJEBg2fM0WrTzcik9KVXAyEag==", + "version": "7.0.0-dev.20251117.1", + "resolved": "https://registry.npmjs.org/@typescript/native-preview-win32-x64/-/native-preview-win32-x64-7.0.0-dev.20251117.1.tgz", + "integrity": "sha512-GhJ4GIygHSU86gZw6NkOnJKi/XW0Yw+1quanZ6BaOAZ+HY6aftuESy+NlbC6nUSGE2xmbvxqJgqchCIlC6YPoA==", "cpu": [ "x64" ], @@ -2922,9 +2925,10 @@ } }, "node_modules/@vscode/iconv-lite-umd": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz", - "integrity": "sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.1.tgz", + "integrity": "sha512-tK6k0DXFHW7q5+GGuGZO+phpAqpxO4WXl+BLc/8/uOk3RsM2ssAL3CQUQDb1TGfwltjsauhN6S4ghYZzs4sPFw==", + "license": "MIT" }, "node_modules/@vscode/l10n-dev": { "version": "0.0.35", @@ -3015,9 +3019,9 @@ } }, "node_modules/@vscode/proxy-agent": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@vscode/proxy-agent/-/proxy-agent-0.35.0.tgz", - "integrity": "sha512-25BxUVwWkRVdVKHIekIz5pshmPprkLmtyPteRIhZIKJF++5u1nLETeHO+a+E957UXnH+YiD2Hh9g9DxVnuBRxA==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/@vscode/proxy-agent/-/proxy-agent-0.36.0.tgz", + "integrity": "sha512-W4mls/+zErqTYcKC41utdmoYnBWZRH1dRF9U4cBAyKU5EhcnWfVsPBvUnXXw1CffI3djmMWnu9JrF/Ynw7lkcg==", "license": "MIT", "dependencies": { "@tootallnate/once": "^3.0.0", @@ -3028,6 +3032,9 @@ "socks-proxy-agent": "^8.0.1", "undici": "^7.2.0" }, + "engines": { + "node": ">=22.15.0" + }, "optionalDependencies": { "@vscode/windows-ca-certs": "^0.3.1" } @@ -3318,9 +3325,9 @@ } }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.1.4.tgz", - "integrity": "sha512-kQVVg/CamCYDM+/XYCZuNTQyixjZd8ts/Gf84UzjEY0eRnbg6kiy5I9z2/2i3XdqwhI87iG07rkMR2KwhqcSbA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", + "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", "license": "MIT" }, "node_modules/@vscode/v8-heap-parser": { @@ -3568,10 +3575,11 @@ } }, "node_modules/@webgpu/types": { - "version": "0.1.44", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.44.tgz", - "integrity": "sha512-JDpYJN5E/asw84LTYhKyvPpxGnD+bAKPtpW9Ilurf7cZpxaTbxkQcGwOd7jgB9BPBrTYQ+32ufo4HiuomTjHNQ==", - "dev": true + "version": "0.1.66", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.66.tgz", + "integrity": "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@webpack-cli/configtest": { "version": "2.1.1", @@ -3618,30 +3626,30 @@ } }, "node_modules/@xterm/addon-clipboard": { - "version": "0.2.0-beta.102", - "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.102.tgz", - "integrity": "sha512-HDI5T7k7UXEIWKMOmKZAArhZcpmz/J2tpF8DNpTVNkhOpIKWwGbhaFuhPQBuNtnfxtoR5sqVkr/tMIji4jfC+A==", + "version": "0.2.0-beta.119", + "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.119.tgz", + "integrity": "sha512-yWmCpGuTvSaIeEfdSijdf8K8qRAYuEGnKkaJZ6er+cOzdmGHBNzyBDKKeyins0aV2j4CGKPDiWHQF5+qGzZDGw==", "license": "MIT", "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-image": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.119.tgz", - "integrity": "sha512-mFBAU8SysOqkBt4KYetwY5OEzIziRG4ECImtYgbx8Z6AIZ8NSqSE8/f12TOZ+vWkGwHrx12odsM94Wllpjz2dQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.136.tgz", + "integrity": "sha512-syWhqpFMAcQ1+US0JjFzj0ORokj8hkz2VgXcCCbTfO0cDtpSYYxMNLaY2fpL459rnOFB4olI9Nf9PZdonmBPDw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-ligatures": { - "version": "0.10.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.119.tgz", - "integrity": "sha512-CjKsvXzRwDSDaTGz1jCX2tMS3X6BtBiN/nWx4xOYVi7QAQ516tUOup/oUhK4x7lKIYv5CrPKWfX9JzQ/Bzou5w==", + "version": "0.10.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.136.tgz", + "integrity": "sha512-WkvL7BVdoqpNf8QsH4n37Pu7jEZTiJ+OD4FmLMVavw0euhgG18zzJKNKIYRuKcddR52dT/Q8TrspVJofpL98GQ==", "license": "MIT", "dependencies": { "font-finder": "^1.1.0", @@ -3651,64 +3659,64 @@ "node": ">8.0.0" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-progress": { - "version": "0.2.0-beta.25", - "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.25.tgz", - "integrity": "sha512-snRn6MFbX2GhzVf0+yFpVJ0qe/A94VQ7swBmFEa6JwV8kEuzkmjeU5dPhztKSXp5KFnJV9kgj0kTs3J6Y5GlnQ==", + "version": "0.2.0-beta.42", + "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.42.tgz", + "integrity": "sha512-C5w7y6rwSUdRcEiJHFnB2qJI/6DBOi/fJAvTmIpmNZE60cVnrLUuyLmXh6aKbSQ44J6W3PrD5xthb8re3UVUOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-search": { - "version": "0.16.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.119.tgz", - "integrity": "sha512-RiWmnW1b1jvPebN/FtmXyKaXwcNPp34WJT52jE2QP101Mx7wIsTwketoqHkRAqX7fqV9YZ/4ZoJKjtW9IdroEg==", + "version": "0.16.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.136.tgz", + "integrity": "sha512-Y2T/ShQBelmOGy7lup3VEfFF/yXeNkkMXqhGftmjzmwSA+eylFW+92vczMSrckTW++EFvVLR/L5jMXiSw0qOWQ==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-serialize": { - "version": "0.14.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.119.tgz", - "integrity": "sha512-dLFW+wKImCoLIAGLMgm6ReiaY1oxSEsIaT0WoOIiA30I3vTwi2gM7SbqIv7W8WsD4GIDHETUTPEtrEP2t4i7ZQ==", + "version": "0.14.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.136.tgz", + "integrity": "sha512-ursvqITzhZrBQT8XsbOyAQJJKohv33NEm6ToLtMZUmPurBG6KXlVZ9LAPs2YpCBqkifLktSE1GdsofJCpADWuA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-unicode11": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.119.tgz", - "integrity": "sha512-R7UNkxnjPIcYIQK6EHyG+SBP/I0tbqobwAYLbeahvf7E6okcQzirFYgTUi4vY3f9wRJTDx/cS7Vh4XJG55e4nQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.136.tgz", + "integrity": "sha512-RwtNbON1uNndrtPCM6qMMElTTpxs7ZLRQVbSm4/BMW6GAt6AbW1RAqwoxMRhbz7VVTux/c3HcKfj3SI1MhqSOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-webgl": { - "version": "0.19.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.119.tgz", - "integrity": "sha512-j8usRuPfHIbjPoPTGbeUehuEslYIVDwfJb+2clM79j0hal8rvXVvX1/GOpqVK7LJtWbg+EaFZZo8EvUsJMiQpg==", + "version": "0.19.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.136.tgz", + "integrity": "sha512-MzVlFKrlgJjKQ6T4/TuamvlvR2FFDvxAPY90lo9u4899k7NNif+M8bBdNea3+bsPMU3fKLhGHoTp0+8MjskaeA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/headless": { - "version": "5.6.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-5.6.0-beta.119.tgz", - "integrity": "sha512-kZW0Nuu0Rhm/lov6rp+LTbf0rWur/cM2zAUiU/IxpgR+tCJlPT5stSFXBvc+AzaNNHuvpHG8ko2YUJTmqdWp2A==", + "version": "5.6.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-5.6.0-beta.136.tgz", + "integrity": "sha512-3irueWS6Ei+XlTMCuh6ZWj1tBnVvjitDtD4PN+v81RKjaCNO/QN9abGTHQx+651GP291ESwY8ocKThSoQ9yklw==", "license": "MIT" }, "node_modules/@xterm/xterm": { - "version": "5.6.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.119.tgz", - "integrity": "sha512-DGuLxADtzHBSuD1YK7URgkUglPsayWlE722QMVknvfm72PdbzSqu6TPzsN7KeFsFHN7ajYjuEz9B/RaIQoLC8Q==", + "version": "5.6.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.136.tgz", + "integrity": "sha512-cOWfdbPUYjV8qJY0yg/HdJBiq/hl8J2NRma563crQbSveDpuiiKV+T+ZVeGKQ2YZztLCz6h+kox6J7LQcPtpiQ==", "license": "MIT" }, "node_modules/@xtuc/ieee754": { @@ -6331,9 +6339,9 @@ "dev": true }, "node_modules/electron": { - "version": "37.6.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-37.6.0.tgz", - "integrity": "sha512-8AANcn6irYQ7cTAJRY7r0CovWckcGCHUniQecyGhw/jJ25vWwitVhF97skF+EyDztiEI6YBoF0G6tx1s37bO3g==", + "version": "39.2.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-39.2.0.tgz", + "integrity": "sha512-iISf3nmZYOBb2WZXETNr46Ot7Ny5nq7aTAWxkPnpaFvdVnDTk9ixK4JgC9NNctKR+VS/pXP1Ryp86mudny3sDQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6520,6 +6528,22 @@ "node": ">= 0.4" } }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -7714,13 +7738,16 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -10007,12 +10034,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -11191,10 +11219,11 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -11412,9 +11441,9 @@ } }, "node_modules/koa": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/koa/-/koa-2.16.1.tgz", - "integrity": "sha512-umfX9d3iuSxTQP4pnzLOz0HKnPg0FaUUIKcye2lOiz3KPu1Y3M3xlz76dISdFPQs37P9eJz1wUpcTS6KDPn9fA==", + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.16.3.tgz", + "integrity": "sha512-zPPuIt+ku1iCpFBRwseMcPYQ1cJL8l60rSmKeOuGfOXyE6YnTBmf2aEFNL2HQGrD0cPcLO/t+v9RTgC+fwEh/g==", "dev": true, "license": "MIT", "dependencies": { @@ -12293,21 +12322,23 @@ } }, "node_modules/mime-db": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", - "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.28", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", - "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, + "license": "MIT", "dependencies": { - "mime-db": "1.45.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -14096,13 +14127,13 @@ } }, "node_modules/playwright": { - "version": "1.55.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz", - "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.55.1" + "playwright-core": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -14128,9 +14159,9 @@ } }, "node_modules/playwright/node_modules/playwright-core": { - "version": "1.55.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz", - "integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -16654,10 +16685,14 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/tas-client-umd": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/tas-client-umd/-/tas-client-umd-0.2.0.tgz", - "integrity": "sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q==" + "node_modules/tas-client": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.3.1.tgz", + "integrity": "sha512-Mn4+4t/KXEf8aIENeI1TkzpKIImzmG+FjPZ2dlaoGNFgxJqBE/pp3MT7nc2032EG4aS73E4OEcr2WiNaWW8mdA==", + "license": "MIT", + "engines": { + "node": ">=22" + } }, "node_modules/teex": { "version": "1.0.1", @@ -17273,9 +17308,9 @@ "dev": true }, "node_modules/typescript": { - "version": "6.0.0-dev.20250922", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.0-dev.20250922.tgz", - "integrity": "sha512-4jTznRR2W8ak4kgHlxhNEauwCS/O2O2AfS3yC+Y4VxkRDFIruwdcW4+UQflBJrLCFa42lhdAAMGl1td/99KTKg==", + "version": "6.0.0-dev.20251117", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.0-dev.20251117.tgz", + "integrity": "sha512-BJkVdQDGWE8KxtuSLvWLQ/ju+n6FdSM8rq/2B9myrmKXeKa9HRG36MOTMgfZQUWDmPd2f5+U8fhU7xO2+WNa3g==", "dev": true, "license": "Apache-2.0", "bin": { @@ -17380,9 +17415,9 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, diff --git a/package.json b/package.json index ebd3fa44f35..7fb7d71297e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", - "version": "1.106.0", - "distro": "cf7a6d44d8299723d955936df569ea424e6b68fd", + "version": "1.107.0", + "distro": "3ee33b7862b5e018538b730ae631f35747f57a2c", "author": { "name": "Microsoft Corporation" }, @@ -15,6 +15,7 @@ "test-browser-no-install": "node test/unit/browser/index.js", "test-node": "mocha test/unit/node/index.js --delay --ui=tdd --timeout=5000 --exit", "test-extension": "vscode-test", + "test-build-scripts": "cd build && npm run test", "preinstall": "node build/npm/preinstall.js", "postinstall": "node build/npm/postinstall.js", "compile": "node ./node_modules/gulp/bin/gulp.js compile", @@ -32,7 +33,7 @@ "watch-extensions": "node --max-old-space-size=8192 ./node_modules/gulp/bin/gulp.js watch-extensions watch-extension-media", "watch-extensionsd": "deemon npm run watch-extensions", "kill-watch-extensionsd": "deemon --kill npm run watch-extensions", - "precommit": "node build/hygiene.js", + "precommit": "node build/hygiene.mjs", "gulp": "node --max-old-space-size=8192 ./node_modules/gulp/bin/gulp.js", "electron": "node build/lib/electron", "7z": "7z", @@ -54,8 +55,8 @@ "compile-web": "node ./node_modules/gulp/bin/gulp.js compile-web", "watch-web": "node ./node_modules/gulp/bin/gulp.js watch-web", "watch-cli": "node ./node_modules/gulp/bin/gulp.js watch-cli", - "eslint": "node build/eslint", - "stylelint": "node build/stylelint", + "eslint": "node build/eslint.mjs", + "stylelint": "node build/stylelint.mjs", "playwright-install": "npm exec playwright install", "compile-build": "node ./node_modules/gulp/bin/gulp.js compile-build-with-mangling", "compile-extensions-build": "node ./node_modules/gulp/bin/gulp.js compile-extensions-build", @@ -68,7 +69,7 @@ "extensions-ci": "node ./node_modules/gulp/bin/gulp.js extensions-ci", "extensions-ci-pr": "node ./node_modules/gulp/bin/gulp.js extensions-ci-pr", "perf": "node scripts/code-perf.js", - "update-build-ts-version": "npm install -D typescript@next && npm install -D @typescript/native-preview && (cd build && npm run compile)" + "update-build-ts-version": "npm install -D typescript@next @typescript/native-preview && (cd build && npm run compile)" }, "dependencies": { "@microsoft/1ds-core-js": "^3.2.13", @@ -76,28 +77,28 @@ "@parcel/watcher": "parcel-bundler/watcher#1ca032aa8339260a8a3bcf825c3a1a71e3e43542", "@types/semver": "^7.5.8", "@vscode/deviceid": "^0.1.1", - "@vscode/iconv-lite-umd": "0.7.0", + "@vscode/iconv-lite-umd": "0.7.1", "@vscode/policy-watcher": "^1.3.2", - "@vscode/proxy-agent": "^0.35.0", + "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", "@vscode/sqlite3": "5.1.8-vscode", "@vscode/sudo-prompt": "9.3.1", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-mutex": "^0.5.0", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/headless": "^5.6.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/headless": "^5.6.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", "jschardet": "3.1.4", @@ -109,7 +110,7 @@ "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta35", "open": "^10.1.2", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "undici": "^7.9.0", "v8-inspect-profiler": "^0.1.1", "vscode-oniguruma": "1.7.0", @@ -119,7 +120,7 @@ "yazl": "^2.4.3" }, "devDependencies": { - "@playwright/test": "^1.55.1", + "@playwright/test": "^1.56.1", "@stylistic/eslint-plugin-ts": "^2.8.0", "@types/cookie": "^0.3.3", "@types/debug": "^4.1.5", @@ -129,7 +130,7 @@ "@types/kerberos": "^1.1.2", "@types/minimist": "^1.2.1", "@types/mocha": "^10.0.10", - "@types/node": "22.x", + "@types/node": "^22.18.10", "@types/sinon": "^10.0.2", "@types/sinon-test": "^2.4.2", "@types/trusted-types": "^2.0.7", @@ -141,7 +142,7 @@ "@types/yauzl": "^2.10.0", "@types/yazl": "^2.4.2", "@typescript-eslint/utils": "^8.45.0", - "@typescript/native-preview": "^7.0.0-dev.20250812.1", + "@typescript/native-preview": "^7.0.0-dev.20251117", "@vscode/gulp-electron": "^1.38.2", "@vscode/l10n-dev": "0.0.35", "@vscode/telemetry-extractor": "^1.10.2", @@ -150,7 +151,7 @@ "@vscode/test-web": "^0.0.62", "@vscode/v8-heap-parser": "^0.1.0", "@vscode/vscode-perf": "^0.0.19", - "@webgpu/types": "^0.1.44", + "@webgpu/types": "^0.1.66", "ansi-colors": "^3.2.3", "asar": "^3.0.3", "chromium-pickle-js": "^0.2.0", @@ -159,7 +160,7 @@ "css-loader": "^6.9.1", "debounce": "^1.0.0", "deemon": "^1.13.6", - "electron": "37.6.0", + "electron": "39.2.0", "eslint": "^9.36.0", "eslint-formatter-compact": "^8.40.0", "eslint-plugin-header": "3.1.1", @@ -213,7 +214,7 @@ "ts-node": "^10.9.1", "tsec": "0.2.7", "tslib": "^2.6.3", - "typescript": "^6.0.0-dev.20250922", + "typescript": "^6.0.0-dev.20251117", "typescript-eslint": "^8.45.0", "util": "^0.12.4", "webpack": "^5.94.0", diff --git a/product.json b/product.json index a23473a4663..f088e15a772 100644 --- a/product.json +++ b/product.json @@ -82,5 +82,65 @@ "publisherDisplayName": "Microsoft" } } - ] + ], + "defaultChatAgent": { + "extensionId": "GitHub.copilot", + "chatExtensionId": "GitHub.copilot-chat", + "documentationUrl": "https://aka.ms/github-copilot-overview", + "termsStatementUrl": "https://aka.ms/github-copilot-terms-statement", + "privacyStatementUrl": "https://aka.ms/github-copilot-privacy-statement", + "skusDocumentationUrl": "https://aka.ms/github-copilot-plans", + "publicCodeMatchesUrl": "https://aka.ms/github-copilot-match-public-code", + "manageSettingsUrl": "https://aka.ms/github-copilot-settings", + "managePlanUrl": "https://aka.ms/github-copilot-manage-plan", + "manageOverageUrl": "https://aka.ms/github-copilot-manage-overage", + "upgradePlanUrl": "https://aka.ms/github-copilot-upgrade-plan", + "signUpUrl": "https://aka.ms/github-sign-up", + "provider": { + "default": { + "id": "github", + "name": "GitHub" + }, + "enterprise": { + "id": "github-enterprise", + "name": "GHE.com" + }, + "google": { + "id": "google", + "name": "Google" + }, + "apple": { + "id": "apple", + "name": "Apple" + } + }, + "providerUriSetting": "github-enterprise.uri", + "providerScopes": [ + [ + "user:email" + ], + [ + "read:user" + ], + [ + "read:user", + "user:email", + "repo", + "workflow" + ] + ], + "entitlementUrl": "https://api.github.com/copilot_internal/user", + "entitlementSignupLimitedUrl": "https://api.github.com/copilot_internal/subscribe_limited_user", + "chatQuotaExceededContext": "github.copilot.chat.quotaExceeded", + "completionsQuotaExceededContext": "github.copilot.completions.quotaExceeded", + "walkthroughCommand": "github.copilot.open.walkthrough", + "completionsMenuCommand": "github.copilot.toggleStatusMenu", + "completionsRefreshTokenCommand": "github.copilot.signIn", + "chatRefreshTokenCommand": "github.copilot.refreshToken", + "generateCommitMessageCommand": "github.copilot.git.generateCommitMessage", + "resolveMergeConflictsCommand": "github.copilot.git.resolveMergeConflicts", + "completionsAdvancedSetting": "github.copilot.advanced", + "completionsEnablementSetting": "github.copilot.enable", + "nextEditSuggestionsSetting": "github.copilot.nextEditSuggestions.enabled" + } } diff --git a/remote/.npmrc b/remote/.npmrc index c1ef6fcca6e..326fb9fd0f6 100644 --- a/remote/.npmrc +++ b/remote/.npmrc @@ -1,6 +1,6 @@ disturl="https://nodejs.org/dist" -target="22.19.0" -ms_build_id="360633" +target="22.21.1" +ms_build_id="374314" runtime="node" build_from_source="true" legacy-peer-deps="true" diff --git a/remote/package-lock.json b/remote/package-lock.json index a6a9e253204..7d123d102d5 100644 --- a/remote/package-lock.json +++ b/remote/package-lock.json @@ -12,24 +12,24 @@ "@microsoft/1ds-post-js": "^3.2.13", "@parcel/watcher": "parcel-bundler/watcher#1ca032aa8339260a8a3bcf825c3a1a71e3e43542", "@vscode/deviceid": "^0.1.1", - "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/proxy-agent": "^0.35.0", + "@vscode/iconv-lite-umd": "0.7.1", + "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/headless": "^5.6.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/headless": "^5.6.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "cookie": "^0.7.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", @@ -39,7 +39,7 @@ "minimist": "^1.2.8", "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta35", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "^9.2.1", @@ -128,14 +128,15 @@ } }, "node_modules/@vscode/iconv-lite-umd": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz", - "integrity": "sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.1.tgz", + "integrity": "sha512-tK6k0DXFHW7q5+GGuGZO+phpAqpxO4WXl+BLc/8/uOk3RsM2ssAL3CQUQDb1TGfwltjsauhN6S4ghYZzs4sPFw==", + "license": "MIT" }, "node_modules/@vscode/proxy-agent": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/@vscode/proxy-agent/-/proxy-agent-0.35.0.tgz", - "integrity": "sha512-25BxUVwWkRVdVKHIekIz5pshmPprkLmtyPteRIhZIKJF++5u1nLETeHO+a+E957UXnH+YiD2Hh9g9DxVnuBRxA==", + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/@vscode/proxy-agent/-/proxy-agent-0.36.0.tgz", + "integrity": "sha512-W4mls/+zErqTYcKC41utdmoYnBWZRH1dRF9U4cBAyKU5EhcnWfVsPBvUnXXw1CffI3djmMWnu9JrF/Ynw7lkcg==", "license": "MIT", "dependencies": { "@tootallnate/once": "^3.0.0", @@ -146,6 +147,9 @@ "socks-proxy-agent": "^8.0.1", "undici": "^7.2.0" }, + "engines": { + "node": ">=22.15.0" + }, "optionalDependencies": { "@vscode/windows-ca-certs": "^0.3.1" } @@ -184,9 +188,9 @@ } }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.1.4.tgz", - "integrity": "sha512-kQVVg/CamCYDM+/XYCZuNTQyixjZd8ts/Gf84UzjEY0eRnbg6kiy5I9z2/2i3XdqwhI87iG07rkMR2KwhqcSbA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", + "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", "license": "MIT" }, "node_modules/@vscode/vscode-languagedetection": { @@ -237,30 +241,30 @@ "hasInstallScript": true }, "node_modules/@xterm/addon-clipboard": { - "version": "0.2.0-beta.102", - "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.102.tgz", - "integrity": "sha512-HDI5T7k7UXEIWKMOmKZAArhZcpmz/J2tpF8DNpTVNkhOpIKWwGbhaFuhPQBuNtnfxtoR5sqVkr/tMIji4jfC+A==", + "version": "0.2.0-beta.119", + "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.119.tgz", + "integrity": "sha512-yWmCpGuTvSaIeEfdSijdf8K8qRAYuEGnKkaJZ6er+cOzdmGHBNzyBDKKeyins0aV2j4CGKPDiWHQF5+qGzZDGw==", "license": "MIT", "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-image": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.119.tgz", - "integrity": "sha512-mFBAU8SysOqkBt4KYetwY5OEzIziRG4ECImtYgbx8Z6AIZ8NSqSE8/f12TOZ+vWkGwHrx12odsM94Wllpjz2dQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.136.tgz", + "integrity": "sha512-syWhqpFMAcQ1+US0JjFzj0ORokj8hkz2VgXcCCbTfO0cDtpSYYxMNLaY2fpL459rnOFB4olI9Nf9PZdonmBPDw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-ligatures": { - "version": "0.10.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.119.tgz", - "integrity": "sha512-CjKsvXzRwDSDaTGz1jCX2tMS3X6BtBiN/nWx4xOYVi7QAQ516tUOup/oUhK4x7lKIYv5CrPKWfX9JzQ/Bzou5w==", + "version": "0.10.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.136.tgz", + "integrity": "sha512-WkvL7BVdoqpNf8QsH4n37Pu7jEZTiJ+OD4FmLMVavw0euhgG18zzJKNKIYRuKcddR52dT/Q8TrspVJofpL98GQ==", "license": "MIT", "dependencies": { "font-finder": "^1.1.0", @@ -270,64 +274,64 @@ "node": ">8.0.0" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-progress": { - "version": "0.2.0-beta.25", - "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.25.tgz", - "integrity": "sha512-snRn6MFbX2GhzVf0+yFpVJ0qe/A94VQ7swBmFEa6JwV8kEuzkmjeU5dPhztKSXp5KFnJV9kgj0kTs3J6Y5GlnQ==", + "version": "0.2.0-beta.42", + "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.42.tgz", + "integrity": "sha512-C5w7y6rwSUdRcEiJHFnB2qJI/6DBOi/fJAvTmIpmNZE60cVnrLUuyLmXh6aKbSQ44J6W3PrD5xthb8re3UVUOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-search": { - "version": "0.16.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.119.tgz", - "integrity": "sha512-RiWmnW1b1jvPebN/FtmXyKaXwcNPp34WJT52jE2QP101Mx7wIsTwketoqHkRAqX7fqV9YZ/4ZoJKjtW9IdroEg==", + "version": "0.16.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.136.tgz", + "integrity": "sha512-Y2T/ShQBelmOGy7lup3VEfFF/yXeNkkMXqhGftmjzmwSA+eylFW+92vczMSrckTW++EFvVLR/L5jMXiSw0qOWQ==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-serialize": { - "version": "0.14.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.119.tgz", - "integrity": "sha512-dLFW+wKImCoLIAGLMgm6ReiaY1oxSEsIaT0WoOIiA30I3vTwi2gM7SbqIv7W8WsD4GIDHETUTPEtrEP2t4i7ZQ==", + "version": "0.14.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.136.tgz", + "integrity": "sha512-ursvqITzhZrBQT8XsbOyAQJJKohv33NEm6ToLtMZUmPurBG6KXlVZ9LAPs2YpCBqkifLktSE1GdsofJCpADWuA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-unicode11": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.119.tgz", - "integrity": "sha512-R7UNkxnjPIcYIQK6EHyG+SBP/I0tbqobwAYLbeahvf7E6okcQzirFYgTUi4vY3f9wRJTDx/cS7Vh4XJG55e4nQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.136.tgz", + "integrity": "sha512-RwtNbON1uNndrtPCM6qMMElTTpxs7ZLRQVbSm4/BMW6GAt6AbW1RAqwoxMRhbz7VVTux/c3HcKfj3SI1MhqSOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-webgl": { - "version": "0.19.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.119.tgz", - "integrity": "sha512-j8usRuPfHIbjPoPTGbeUehuEslYIVDwfJb+2clM79j0hal8rvXVvX1/GOpqVK7LJtWbg+EaFZZo8EvUsJMiQpg==", + "version": "0.19.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.136.tgz", + "integrity": "sha512-MzVlFKrlgJjKQ6T4/TuamvlvR2FFDvxAPY90lo9u4899k7NNif+M8bBdNea3+bsPMU3fKLhGHoTp0+8MjskaeA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/headless": { - "version": "5.6.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-5.6.0-beta.119.tgz", - "integrity": "sha512-kZW0Nuu0Rhm/lov6rp+LTbf0rWur/cM2zAUiU/IxpgR+tCJlPT5stSFXBvc+AzaNNHuvpHG8ko2YUJTmqdWp2A==", + "version": "5.6.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/headless/-/headless-5.6.0-beta.136.tgz", + "integrity": "sha512-3irueWS6Ei+XlTMCuh6ZWj1tBnVvjitDtD4PN+v81RKjaCNO/QN9abGTHQx+651GP291ESwY8ocKThSoQ9yklw==", "license": "MIT" }, "node_modules/@xterm/xterm": { - "version": "5.6.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.119.tgz", - "integrity": "sha512-DGuLxADtzHBSuD1YK7URgkUglPsayWlE722QMVknvfm72PdbzSqu6TPzsN7KeFsFHN7ajYjuEz9B/RaIQoLC8Q==", + "version": "5.6.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.136.tgz", + "integrity": "sha512-cOWfdbPUYjV8qJY0yg/HdJBiq/hl8J2NRma563crQbSveDpuiiKV+T+ZVeGKQ2YZztLCz6h+kox6J7LQcPtpiQ==", "license": "MIT" }, "node_modules/agent-base": { @@ -1121,10 +1125,14 @@ "node": ">=6" } }, - "node_modules/tas-client-umd": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/tas-client-umd/-/tas-client-umd-0.2.0.tgz", - "integrity": "sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q==" + "node_modules/tas-client": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.3.1.tgz", + "integrity": "sha512-Mn4+4t/KXEf8aIENeI1TkzpKIImzmG+FjPZ2dlaoGNFgxJqBE/pp3MT7nc2032EG4aS73E4OEcr2WiNaWW8mdA==", + "license": "MIT", + "engines": { + "node": ">=22" + } }, "node_modules/tiny-inflate": { "version": "1.0.3", diff --git a/remote/package.json b/remote/package.json index 38e9037c747..905eae3d92e 100644 --- a/remote/package.json +++ b/remote/package.json @@ -7,24 +7,24 @@ "@microsoft/1ds-post-js": "^3.2.13", "@parcel/watcher": "parcel-bundler/watcher#1ca032aa8339260a8a3bcf825c3a1a71e3e43542", "@vscode/deviceid": "^0.1.1", - "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/proxy-agent": "^0.35.0", + "@vscode/iconv-lite-umd": "0.7.1", + "@vscode/proxy-agent": "^0.36.0", "@vscode/ripgrep": "^1.15.13", "@vscode/spdlog": "^0.15.2", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", "@vscode/windows-process-tree": "^0.6.0", "@vscode/windows-registry": "^1.1.0", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/headless": "^5.6.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/headless": "^5.6.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "cookie": "^0.7.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.2", @@ -34,7 +34,7 @@ "minimist": "^1.2.8", "native-watchdog": "^1.4.1", "node-pty": "1.1.0-beta35", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "vscode-oniguruma": "1.7.0", "vscode-regexpp": "^3.1.0", "vscode-textmate": "^9.2.1", diff --git a/remote/web/package-lock.json b/remote/web/package-lock.json index 80f4f0c7dc7..ac1a0d4234d 100644 --- a/remote/web/package-lock.json +++ b/remote/web/package-lock.json @@ -10,21 +10,21 @@ "dependencies": { "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", - "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/iconv-lite-umd": "0.7.1", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "jschardet": "3.1.4", "katex": "^0.16.22", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "vscode-oniguruma": "1.7.0", "vscode-textmate": "^9.2.1" } @@ -72,14 +72,15 @@ "integrity": "sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ==" }, "node_modules/@vscode/iconv-lite-umd": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.0.tgz", - "integrity": "sha512-bRRFxLfg5dtAyl5XyiVWz/ZBPahpOpPrNYnnHpOpUZvam4tKH35wdhP4Kj6PbM0+KdliOsPzbGWpkxcdpNB/sg==" + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@vscode/iconv-lite-umd/-/iconv-lite-umd-0.7.1.tgz", + "integrity": "sha512-tK6k0DXFHW7q5+GGuGZO+phpAqpxO4WXl+BLc/8/uOk3RsM2ssAL3CQUQDb1TGfwltjsauhN6S4ghYZzs4sPFw==", + "license": "MIT" }, "node_modules/@vscode/tree-sitter-wasm": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.1.4.tgz", - "integrity": "sha512-kQVVg/CamCYDM+/XYCZuNTQyixjZd8ts/Gf84UzjEY0eRnbg6kiy5I9z2/2i3XdqwhI87iG07rkMR2KwhqcSbA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@vscode/tree-sitter-wasm/-/tree-sitter-wasm-0.2.0.tgz", + "integrity": "sha512-abvLfKwmriqgdS4WrIzFK7mzdPUVqIIW1UWarp2lA8lpOZ1EDPL1snRBKe7g+5R5ri173mNJEuPLnG/NlpMp4w==", "license": "MIT" }, "node_modules/@vscode/vscode-languagedetection": { @@ -91,30 +92,30 @@ } }, "node_modules/@xterm/addon-clipboard": { - "version": "0.2.0-beta.102", - "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.102.tgz", - "integrity": "sha512-HDI5T7k7UXEIWKMOmKZAArhZcpmz/J2tpF8DNpTVNkhOpIKWwGbhaFuhPQBuNtnfxtoR5sqVkr/tMIji4jfC+A==", + "version": "0.2.0-beta.119", + "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.2.0-beta.119.tgz", + "integrity": "sha512-yWmCpGuTvSaIeEfdSijdf8K8qRAYuEGnKkaJZ6er+cOzdmGHBNzyBDKKeyins0aV2j4CGKPDiWHQF5+qGzZDGw==", "license": "MIT", "dependencies": { "js-base64": "^3.7.5" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-image": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.119.tgz", - "integrity": "sha512-mFBAU8SysOqkBt4KYetwY5OEzIziRG4ECImtYgbx8Z6AIZ8NSqSE8/f12TOZ+vWkGwHrx12odsM94Wllpjz2dQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-image/-/addon-image-0.9.0-beta.136.tgz", + "integrity": "sha512-syWhqpFMAcQ1+US0JjFzj0ORokj8hkz2VgXcCCbTfO0cDtpSYYxMNLaY2fpL459rnOFB4olI9Nf9PZdonmBPDw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-ligatures": { - "version": "0.10.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.119.tgz", - "integrity": "sha512-CjKsvXzRwDSDaTGz1jCX2tMS3X6BtBiN/nWx4xOYVi7QAQ516tUOup/oUhK4x7lKIYv5CrPKWfX9JzQ/Bzou5w==", + "version": "0.10.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-ligatures/-/addon-ligatures-0.10.0-beta.136.tgz", + "integrity": "sha512-WkvL7BVdoqpNf8QsH4n37Pu7jEZTiJ+OD4FmLMVavw0euhgG18zzJKNKIYRuKcddR52dT/Q8TrspVJofpL98GQ==", "license": "MIT", "dependencies": { "font-finder": "^1.1.0", @@ -124,58 +125,58 @@ "node": ">8.0.0" }, "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-progress": { - "version": "0.2.0-beta.25", - "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.25.tgz", - "integrity": "sha512-snRn6MFbX2GhzVf0+yFpVJ0qe/A94VQ7swBmFEa6JwV8kEuzkmjeU5dPhztKSXp5KFnJV9kgj0kTs3J6Y5GlnQ==", + "version": "0.2.0-beta.42", + "resolved": "https://registry.npmjs.org/@xterm/addon-progress/-/addon-progress-0.2.0-beta.42.tgz", + "integrity": "sha512-C5w7y6rwSUdRcEiJHFnB2qJI/6DBOi/fJAvTmIpmNZE60cVnrLUuyLmXh6aKbSQ44J6W3PrD5xthb8re3UVUOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-search": { - "version": "0.16.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.119.tgz", - "integrity": "sha512-RiWmnW1b1jvPebN/FtmXyKaXwcNPp34WJT52jE2QP101Mx7wIsTwketoqHkRAqX7fqV9YZ/4ZoJKjtW9IdroEg==", + "version": "0.16.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-search/-/addon-search-0.16.0-beta.136.tgz", + "integrity": "sha512-Y2T/ShQBelmOGy7lup3VEfFF/yXeNkkMXqhGftmjzmwSA+eylFW+92vczMSrckTW++EFvVLR/L5jMXiSw0qOWQ==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-serialize": { - "version": "0.14.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.119.tgz", - "integrity": "sha512-dLFW+wKImCoLIAGLMgm6ReiaY1oxSEsIaT0WoOIiA30I3vTwi2gM7SbqIv7W8WsD4GIDHETUTPEtrEP2t4i7ZQ==", + "version": "0.14.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-serialize/-/addon-serialize-0.14.0-beta.136.tgz", + "integrity": "sha512-ursvqITzhZrBQT8XsbOyAQJJKohv33NEm6ToLtMZUmPurBG6KXlVZ9LAPs2YpCBqkifLktSE1GdsofJCpADWuA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-unicode11": { - "version": "0.9.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.119.tgz", - "integrity": "sha512-R7UNkxnjPIcYIQK6EHyG+SBP/I0tbqobwAYLbeahvf7E6okcQzirFYgTUi4vY3f9wRJTDx/cS7Vh4XJG55e4nQ==", + "version": "0.9.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.9.0-beta.136.tgz", + "integrity": "sha512-RwtNbON1uNndrtPCM6qMMElTTpxs7ZLRQVbSm4/BMW6GAt6AbW1RAqwoxMRhbz7VVTux/c3HcKfj3SI1MhqSOw==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/addon-webgl": { - "version": "0.19.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.119.tgz", - "integrity": "sha512-j8usRuPfHIbjPoPTGbeUehuEslYIVDwfJb+2clM79j0hal8rvXVvX1/GOpqVK7LJtWbg+EaFZZo8EvUsJMiQpg==", + "version": "0.19.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/addon-webgl/-/addon-webgl-0.19.0-beta.136.tgz", + "integrity": "sha512-MzVlFKrlgJjKQ6T4/TuamvlvR2FFDvxAPY90lo9u4899k7NNif+M8bBdNea3+bsPMU3fKLhGHoTp0+8MjskaeA==", "license": "MIT", "peerDependencies": { - "@xterm/xterm": "^5.6.0-beta.119" + "@xterm/xterm": "^5.6.0-beta.136" } }, "node_modules/@xterm/xterm": { - "version": "5.6.0-beta.119", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.119.tgz", - "integrity": "sha512-DGuLxADtzHBSuD1YK7URgkUglPsayWlE722QMVknvfm72PdbzSqu6TPzsN7KeFsFHN7ajYjuEz9B/RaIQoLC8Q==", + "version": "5.6.0-beta.136", + "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.136.tgz", + "integrity": "sha512-cOWfdbPUYjV8qJY0yg/HdJBiq/hl8J2NRma563crQbSveDpuiiKV+T+ZVeGKQ2YZztLCz6h+kox6J7LQcPtpiQ==", "license": "MIT" }, "node_modules/commander": { @@ -286,10 +287,14 @@ "node": ">8.0.0" } }, - "node_modules/tas-client-umd": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/tas-client-umd/-/tas-client-umd-0.2.0.tgz", - "integrity": "sha512-oezN7mJVm5qZDVEby7OzxCLKUpUN5of0rY4dvOWaDF2JZBlGpd3BXceFN8B53qlTaIkVSzP65aAMT0Vc+/N25Q==" + "node_modules/tas-client": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.3.1.tgz", + "integrity": "sha512-Mn4+4t/KXEf8aIENeI1TkzpKIImzmG+FjPZ2dlaoGNFgxJqBE/pp3MT7nc2032EG4aS73E4OEcr2WiNaWW8mdA==", + "license": "MIT", + "engines": { + "node": ">=22" + } }, "node_modules/tiny-inflate": { "version": "1.0.3", diff --git a/remote/web/package.json b/remote/web/package.json index 5e6c923b3b7..26584bf22a5 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -5,21 +5,21 @@ "dependencies": { "@microsoft/1ds-core-js": "^3.2.13", "@microsoft/1ds-post-js": "^3.2.13", - "@vscode/iconv-lite-umd": "0.7.0", - "@vscode/tree-sitter-wasm": "^0.1.4", + "@vscode/iconv-lite-umd": "0.7.1", + "@vscode/tree-sitter-wasm": "^0.2.0", "@vscode/vscode-languagedetection": "1.0.21", - "@xterm/addon-clipboard": "^0.2.0-beta.102", - "@xterm/addon-image": "^0.9.0-beta.119", - "@xterm/addon-ligatures": "^0.10.0-beta.119", - "@xterm/addon-progress": "^0.2.0-beta.25", - "@xterm/addon-search": "^0.16.0-beta.119", - "@xterm/addon-serialize": "^0.14.0-beta.119", - "@xterm/addon-unicode11": "^0.9.0-beta.119", - "@xterm/addon-webgl": "^0.19.0-beta.119", - "@xterm/xterm": "^5.6.0-beta.119", + "@xterm/addon-clipboard": "^0.2.0-beta.119", + "@xterm/addon-image": "^0.9.0-beta.136", + "@xterm/addon-ligatures": "^0.10.0-beta.136", + "@xterm/addon-progress": "^0.2.0-beta.42", + "@xterm/addon-search": "^0.16.0-beta.136", + "@xterm/addon-serialize": "^0.14.0-beta.136", + "@xterm/addon-unicode11": "^0.9.0-beta.136", + "@xterm/addon-webgl": "^0.19.0-beta.136", + "@xterm/xterm": "^5.6.0-beta.136", "jschardet": "3.1.4", "katex": "^0.16.22", - "tas-client-umd": "0.2.0", + "tas-client": "0.3.1", "vscode-oniguruma": "1.7.0", "vscode-textmate": "^9.2.1" } diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 50c14ff8d3f..2be5bfef0a0 100644 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -80,6 +80,11 @@ mkdir %GITWORKSPACE% call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test %API_TESTS_EXTRA_ARGS% if %errorlevel% neq 0 exit /b %errorlevel% +echo. +echo ### Git Base tests +call npm run test-extension -- -l git-base +if %errorlevel% neq 0 exit /b %errorlevel% + echo. echo ### Ipynb tests call npm run test-extension -- -l ipynb diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index 3e26bb17a17..e3c391004f8 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -97,6 +97,12 @@ echo "$INTEGRATION_TEST_ELECTRON_PATH" $(mktemp -d 2>/dev/null) --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test $API_TESTS_EXTRA_ARGS kill_app +echo +echo "### Git Base tests" +echo +npm run test-extension -- -l git-base +kill_app + echo echo "### Ipynb tests" echo diff --git a/src/bootstrap-fork.ts b/src/bootstrap-fork.ts index ba08fb3c47d..b87e855ba85 100644 --- a/src/bootstrap-fork.ts +++ b/src/bootstrap-fork.ts @@ -123,7 +123,7 @@ function pipeLoggingToParent(): void { Object.defineProperty(stream, 'write', { set: () => { }, - get: () => (chunk: string | Buffer | Uint8Array, encoding: BufferEncoding | undefined, callback: ((err?: Error | undefined) => void) | undefined) => { + get: () => (chunk: string | Buffer | Uint8Array, encoding: BufferEncoding | undefined, callback: ((err?: Error | null) => void) | undefined) => { buf += chunk.toString(encoding); const eol = buf.length > MAX_STREAM_BUFFER_LENGTH ? buf.length : buf.lastIndexOf('\n'); if (eol !== -1) { diff --git a/src/main.ts b/src/main.ts index 7b7e1da509e..e19dde49541 100644 --- a/src/main.ts +++ b/src/main.ts @@ -330,9 +330,8 @@ function configureCommandlineSwitchesSync(cliArgs: NativeParsedArgs) { // Following features are disabled from the runtime: // `CalculateNativeWinOcclusion` - Disable native window occlusion tracker (https://groups.google.com/a/chromium.org/g/embedder-dev/c/ZF3uHHyWLKw/m/VDN2hDXMAAAJ) - // `FontationsLinuxSystemFonts` - Revert to FreeType for system fonts on Linux Refs https://github.com/microsoft/vscode/issues/260391 const featuresToDisable = - `CalculateNativeWinOcclusion,FontationsLinuxSystemFonts,${app.commandLine.getSwitchValue('disable-features')}`; + `CalculateNativeWinOcclusion,${app.commandLine.getSwitchValue('disable-features')}`; app.commandLine.appendSwitch('disable-features', featuresToDisable); // Blink features to configure. diff --git a/src/tsconfig.base.json b/src/tsconfig.base.json index 732da287a10..b1c66907abf 100644 --- a/src/tsconfig.base.json +++ b/src/tsconfig.base.json @@ -20,7 +20,6 @@ "DOM", "DOM.Iterable", "WebWorker.ImportScripts" - ], - "allowSyntheticDefaultImports": true + ] } } diff --git a/src/tsconfig.monaco.json b/src/tsconfig.monaco.json index cd3d0d860b9..6293f59ba2b 100644 --- a/src/tsconfig.monaco.json +++ b/src/tsconfig.monaco.json @@ -13,7 +13,8 @@ "preserveConstEnums": true, "target": "ES2022", "sourceMap": false, - "declaration": true + "declaration": true, + "skipLibCheck": true }, "include": [ "typings/css.d.ts", diff --git a/src/tsec.exemptions.json b/src/tsec.exemptions.json index f913df5e7da..83691e2de5a 100644 --- a/src/tsec.exemptions.json +++ b/src/tsec.exemptions.json @@ -18,7 +18,7 @@ "vs/workbench/contrib/notebook/browser/view/renderers/webviewPreloads.ts" ], "ban-worker-calls": [ - "vs/base/browser/webWorkerFactory.ts", + "vs/platform/webWorker/browser/webWorkerServiceImpl.ts", "vs/workbench/services/extensions/browser/webWorkerExtensionHost.ts" ], "ban-worker-importscripts": [ diff --git a/src/vs/base/browser/browser.ts b/src/vs/base/browser/browser.ts index 13b937daf32..b6e9ec09fff 100644 --- a/src/vs/base/browser/browser.ts +++ b/src/vs/base/browser/browser.ts @@ -131,13 +131,32 @@ export function isStandalone(): boolean { // e.g. visible is true even in fullscreen mode where the controls are hidden // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/visible export function isWCOEnabled(): boolean { - // eslint-disable-next-line local/code-no-any-casts - return (navigator as any)?.windowControlsOverlay?.visible; + return !!(navigator as Navigator & { windowControlsOverlay?: { visible: boolean } })?.windowControlsOverlay?.visible; } // Returns the bounding rect of the titlebar area if it is supported and defined // See docs at https://developer.mozilla.org/en-US/docs/Web/API/WindowControlsOverlay/getTitlebarAreaRect export function getWCOTitlebarAreaRect(targetWindow: Window): DOMRect | undefined { - // eslint-disable-next-line local/code-no-any-casts - return (targetWindow.navigator as any)?.windowControlsOverlay?.getTitlebarAreaRect(); + return (targetWindow.navigator as Navigator & { windowControlsOverlay?: { getTitlebarAreaRect: () => DOMRect } })?.windowControlsOverlay?.getTitlebarAreaRect(); +} + +export interface IMonacoEnvironment { + + createTrustedTypesPolicy?( + policyName: string, + policyOptions?: Options, + ): undefined | Pick>; + + getWorker?(moduleId: string, label: string): Worker | Promise; + + getWorkerUrl?(moduleId: string, label: string): string; + + globalAPI?: boolean; + +} +interface IGlobalWithMonacoEnvironment { + MonacoEnvironment?: IMonacoEnvironment; +} +export function getMonacoEnvironment(): IMonacoEnvironment | undefined { + return (globalThis as IGlobalWithMonacoEnvironment).MonacoEnvironment; } diff --git a/src/vs/base/browser/canIUse.ts b/src/vs/base/browser/canIUse.ts index 39fe06ce9d8..d7c129abb27 100644 --- a/src/vs/base/browser/canIUse.ts +++ b/src/vs/base/browser/canIUse.ts @@ -33,8 +33,7 @@ export const BrowserFeatures = { return KeyboardSupport.Always; } - // eslint-disable-next-line local/code-no-any-casts - if ((navigator).keyboard || browser.isSafari) { + if ((navigator as Navigator & { keyboard?: unknown }).keyboard || browser.isSafari) { return KeyboardSupport.FullScreen; } diff --git a/src/vs/base/browser/deviceAccess.ts b/src/vs/base/browser/deviceAccess.ts index 9114a5c3d8d..793825e98fe 100644 --- a/src/vs/base/browser/deviceAccess.ts +++ b/src/vs/base/browser/deviceAccess.ts @@ -5,6 +5,27 @@ // https://wicg.github.io/webusb/ +interface UsbDevice { + readonly deviceClass: number; + readonly deviceProtocol: number; + readonly deviceSubclass: number; + readonly deviceVersionMajor: number; + readonly deviceVersionMinor: number; + readonly deviceVersionSubminor: number; + readonly manufacturerName?: string; + readonly productId: number; + readonly productName?: string; + readonly serialNumber?: string; + readonly usbVersionMajor: number; + readonly usbVersionMinor: number; + readonly usbVersionSubminor: number; + readonly vendorId: number; +} + +interface USB { + requestDevice(options: { filters: unknown[] }): Promise; +} + export interface UsbDeviceData { readonly deviceClass: number; readonly deviceProtocol: number; @@ -23,8 +44,7 @@ export interface UsbDeviceData { } export async function requestUsbDevice(options?: { filters?: unknown[] }): Promise { - // eslint-disable-next-line local/code-no-any-casts - const usb = (navigator as any).usb; + const usb = (navigator as Navigator & { usb?: USB }).usb; if (!usb) { return undefined; } @@ -54,14 +74,26 @@ export async function requestUsbDevice(options?: { filters?: unknown[] }): Promi // https://wicg.github.io/serial/ +interface SerialPortInfo { + readonly usbVendorId?: number | undefined; + readonly usbProductId?: number | undefined; +} + +interface SerialPort { + getInfo(): SerialPortInfo; +} + +interface Serial { + requestPort(options: { filters: unknown[] }): Promise; +} + export interface SerialPortData { readonly usbVendorId?: number | undefined; readonly usbProductId?: number | undefined; } export async function requestSerialPort(options?: { filters?: unknown[] }): Promise { - // eslint-disable-next-line local/code-no-any-casts - const serial = (navigator as any).serial; + const serial = (navigator as Navigator & { serial?: Serial }).serial; if (!serial) { return undefined; } @@ -80,6 +112,18 @@ export async function requestSerialPort(options?: { filters?: unknown[] }): Prom // https://wicg.github.io/webhid/ +interface HidDevice { + readonly opened: boolean; + readonly vendorId: number; + readonly productId: number; + readonly productName: string; + readonly collections: []; +} + +interface HID { + requestDevice(options: { filters: unknown[] }): Promise; +} + export interface HidDeviceData { readonly opened: boolean; readonly vendorId: number; @@ -89,8 +133,7 @@ export interface HidDeviceData { } export async function requestHidDevice(options?: { filters?: unknown[] }): Promise { - // eslint-disable-next-line local/code-no-any-casts - const hid = (navigator as any).hid; + const hid = (navigator as Navigator & { hid?: HID }).hid; if (!hid) { return undefined; } diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index 3abc4f9484a..bb8522180c3 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -5,7 +5,7 @@ import * as browser from './browser.js'; import { BrowserFeatures } from './canIUse.js'; -import { IKeyboardEvent, StandardKeyboardEvent } from './keyboardEvent.js'; +import { hasModifierKeys, IKeyboardEvent, StandardKeyboardEvent } from './keyboardEvent.js'; import { IMouseEvent, StandardMouseEvent } from './mouseEvent.js'; import { AbstractIdleValue, IntervalTimer, TimeoutTimer, _runWhenIdle, IdleDeadline } from '../common/async.js'; import { BugIndicatingError, onUnexpectedError } from '../common/errors.js'; @@ -799,6 +799,7 @@ export function setParentFlowTo(fromChildElement: HTMLElement, toParentElement: function getParentFlowToElement(node: HTMLElement): HTMLElement | null { const flowToParentId = node.dataset[parentFlowToDataKey]; if (typeof flowToParentId === 'string') { + // eslint-disable-next-line no-restricted-syntax return node.ownerDocument.getElementById(flowToParentId); } return null; @@ -995,14 +996,14 @@ export const sharedMutationObserver = new class { }; export function createMetaElement(container: HTMLElement = mainWindow.document.head): HTMLMetaElement { - return createHeadElement('meta', container) as HTMLMetaElement; + return createHeadElement('meta', container); } export function createLinkElement(container: HTMLElement = mainWindow.document.head): HTMLLinkElement { - return createHeadElement('link', container) as HTMLLinkElement; + return createHeadElement('link', container); } -function createHeadElement(tagName: string, container: HTMLElement = mainWindow.document.head): HTMLElement { +function createHeadElement(tagName: K, container: HTMLElement = mainWindow.document.head): HTMLElementTagNameMap[K] { const element = document.createElement(tagName); container.appendChild(element); return element; @@ -1267,7 +1268,7 @@ export function append(parent: HTMLElement, ...children: (T | st export function append(parent: HTMLElement, ...children: (T | string)[]): T | void { parent.append(...children); if (children.length === 1 && typeof children[0] !== 'string') { - return children[0]; + return children[0]; } } @@ -1336,7 +1337,7 @@ function _$(namespace: Namespace, description: string, attrs? result.append(...children); - return result as T; + return result; } export function $(description: string, attrs?: { [key: string]: any }, ...children: Array): T { @@ -1813,7 +1814,7 @@ export class ModifierKeyEmitter extends event.Emitter { } get isModifierPressed(): boolean { - return this._keyStatus.altKey || this._keyStatus.ctrlKey || this._keyStatus.metaKey || this._keyStatus.shiftKey; + return hasModifierKeys(this._keyStatus); } /** @@ -2506,7 +2507,43 @@ export abstract class ObserverNode | undefined = undefined; + + get isHovered(): IObservable { + if (!this._isHovered) { + const hovered = observableValue('hovered', false); + this._element.addEventListener('mouseenter', (_e) => hovered.set(true, undefined)); + this._element.addEventListener('mouseleave', (_e) => hovered.set(false, undefined)); + this._isHovered = hovered; + } + return this._isHovered; + } + + private _didMouseMoveDuringHover: IObservable | undefined = undefined; + + get didMouseMoveDuringHover(): IObservable { + if (!this._didMouseMoveDuringHover) { + let _hovering = false; + const hovered = observableValue('didMouseMoveDuringHover', false); + this._element.addEventListener('mouseenter', (_e) => { + _hovering = true; + }); + this._element.addEventListener('mousemove', (_e) => { + if (_hovering) { + hovered.set(true, undefined); + } + }); + this._element.addEventListener('mouseleave', (_e) => { + _hovering = false; + hovered.set(false, undefined); + }); + this._didMouseMoveDuringHover = hovered; + } + return this._didMouseMoveDuringHover; + } } + function setClassName(domNode: HTMLOrSVGElement, className: string) { if (isSVGElement(domNode)) { domNode.setAttribute('class', className); @@ -2514,6 +2551,7 @@ function setClassName(domNode: HTMLOrSVGElement, className: string) { domNode.className = className; } } + function resolve(value: ValueOrList, reader: IReader | undefined, cb: (val: T) => void): void { if (isObservable(value)) { cb(value.read(reader)); @@ -2581,41 +2619,6 @@ export class ObserverNodeWithElement | undefined = undefined; - - get isHovered(): IObservable { - if (!this._isHovered) { - const hovered = observableValue('hovered', false); - this._element.addEventListener('mouseenter', (_e) => hovered.set(true, undefined)); - this._element.addEventListener('mouseleave', (_e) => hovered.set(false, undefined)); - this._isHovered = hovered; - } - return this._isHovered; - } - - private _didMouseMoveDuringHover: IObservable | undefined = undefined; - - get didMouseMoveDuringHover(): IObservable { - if (!this._didMouseMoveDuringHover) { - let _hovering = false; - const hovered = observableValue('didMouseMoveDuringHover', false); - this._element.addEventListener('mouseenter', (_e) => { - _hovering = true; - }); - this._element.addEventListener('mousemove', (_e) => { - if (_hovering) { - hovered.set(true, undefined); - } - }); - this._element.addEventListener('mouseleave', (_e) => { - _hovering = false; - hovered.set(false, undefined); - }); - this._didMouseMoveDuringHover = hovered; - } - return this._didMouseMoveDuringHover; - } } function setOrRemoveAttribute(element: HTMLOrSVGElement, key: string, value: unknown) { if (value === null || value === undefined) { diff --git a/src/vs/base/browser/keyboardEvent.ts b/src/vs/base/browser/keyboardEvent.ts index 4e98a3b12d8..6b675d06535 100644 --- a/src/vs/base/browser/keyboardEvent.ts +++ b/src/vs/base/browser/keyboardEvent.ts @@ -4,12 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as browser from './browser.js'; -import { EVENT_KEY_CODE_MAP, KeyCode, KeyCodeUtils, KeyMod } from '../common/keyCodes.js'; +import { EVENT_KEY_CODE_MAP, isModifierKey, KeyCode, KeyCodeUtils, KeyMod } from '../common/keyCodes.js'; import { KeyCodeChord } from '../common/keybindings.js'; import * as platform from '../common/platform.js'; - - function extractKeyCode(e: KeyboardEvent): KeyCode { if (e.charCode) { // "keypress" events mostly @@ -114,6 +112,15 @@ export function printStandardKeyboardEvent(e: StandardKeyboardEvent): string { return `modifiers: [${modifiers.join(',')}], code: ${e.code}, keyCode: ${e.keyCode} ('${KeyCodeUtils.toString(e.keyCode)}')`; } +export function hasModifierKeys(keyStatus: { + readonly ctrlKey: boolean; + readonly shiftKey: boolean; + readonly altKey: boolean; + readonly metaKey: boolean; +}): boolean { + return keyStatus.ctrlKey || keyStatus.shiftKey || keyStatus.altKey || keyStatus.metaKey; +} + export class StandardKeyboardEvent implements IKeyboardEvent { readonly _standardKeyboardEventBrand = true; @@ -181,7 +188,7 @@ export class StandardKeyboardEvent implements IKeyboardEvent { private _computeKeybinding(): number { let key = KeyCode.Unknown; - if (this.keyCode !== KeyCode.Ctrl && this.keyCode !== KeyCode.Shift && this.keyCode !== KeyCode.Alt && this.keyCode !== KeyCode.Meta) { + if (!isModifierKey(this.keyCode)) { key = this.keyCode; } @@ -205,7 +212,7 @@ export class StandardKeyboardEvent implements IKeyboardEvent { private _computeKeyCodeChord(): KeyCodeChord { let key = KeyCode.Unknown; - if (this.keyCode !== KeyCode.Ctrl && this.keyCode !== KeyCode.Shift && this.keyCode !== KeyCode.Alt && this.keyCode !== KeyCode.Meta) { + if (!isModifierKey(this.keyCode)) { key = this.keyCode; } return new KeyCodeChord(this.ctrlKey, this.shiftKey, this.altKey, this.metaKey, key); diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index 90a597ff5b7..7ae7db5461a 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -22,7 +22,7 @@ import * as domSanitize from './domSanitize.js'; import { convertTagToPlaintext } from './domSanitize.js'; import { StandardKeyboardEvent } from './keyboardEvent.js'; import { StandardMouseEvent } from './mouseEvent.js'; -import { renderLabelWithIcons } from './ui/iconLabel/iconLabels.js'; +import { renderIcon, renderLabelWithIcons } from './ui/iconLabel/iconLabels.js'; export type MarkdownActionHandler = (linkContent: string, mdStr: IMarkdownString) => void; @@ -115,6 +115,62 @@ const defaultMarkedRenderers = Object.freeze({ }, }); +/** + * Blockquote renderer that processes GitHub-style alert syntax. + * Transforms blockquotes like "> [!NOTE]" into structured alert markup with icons. + * + * Based on GitHub's alert syntax: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts + */ +function createAlertBlockquoteRenderer(fallbackRenderer: (this: marked.Renderer, token: marked.Tokens.Blockquote) => string) { + return function (this: marked.Renderer, token: marked.Tokens.Blockquote): string { + const { tokens } = token; + // Check if this blockquote starts with alert syntax [!TYPE] + const firstToken = tokens[0]; + if (firstToken?.type !== 'paragraph') { + return fallbackRenderer.call(this, token); + } + + const paragraphTokens = firstToken.tokens; + if (!paragraphTokens || paragraphTokens.length === 0) { + return fallbackRenderer.call(this, token); + } + + const firstTextToken = paragraphTokens[0]; + if (firstTextToken?.type !== 'text') { + return fallbackRenderer.call(this, token); + } + + const pattern = /^\s*\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\s*?\n*/i; + const match = firstTextToken.raw.match(pattern); + if (!match) { + return fallbackRenderer.call(this, token); + } + + // Remove the alert marker from the token + firstTextToken.raw = firstTextToken.raw.replace(pattern, ''); + firstTextToken.text = firstTextToken.text.replace(pattern, ''); + + const alertIcons: Record = { + 'note': 'info', + 'tip': 'light-bulb', + 'important': 'comment', + 'warning': 'alert', + 'caution': 'stop' + }; + + const type = match[1]; + const typeCapitalized = type.charAt(0).toUpperCase() + type.slice(1).toLowerCase(); + const severity = type.toLowerCase(); + const iconHtml = renderIcon({ id: alertIcons[severity] }).outerHTML; + + // Render the remaining content + const content = this.parser.parse(tokens); + + // Return alert markup with icon and severity (skipping the first 3 characters: `

`) + return `

${iconHtml}${typeCapitalized}${content.substring(3)}

\n`; + }; +} + export interface IRenderedMarkdown extends IDisposable { readonly element: HTMLElement; } @@ -164,7 +220,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende let outElement: HTMLElement; if (target) { outElement = target; - DOM.reset(target, ...renderedContent.children); + DOM.reset(target, ...renderedContent.childNodes); } else { outElement = renderedContent; } @@ -175,6 +231,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende return; } const renderedElements = new Map(tuples); + // eslint-disable-next-line no-restricted-syntax const placeholderElements = outElement.querySelectorAll(`div[data-code]`); for (const placeholderElement of placeholderElements) { const renderedElement = renderedElements.get(placeholderElement.dataset['code'] ?? ''); @@ -186,6 +243,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende }); } else if (syncCodeBlocks.length > 0) { const renderedElements = new Map(syncCodeBlocks); + // eslint-disable-next-line no-restricted-syntax const placeholderElements = outElement.querySelectorAll(`div[data-code]`); for (const placeholderElement of placeholderElements) { const renderedElement = renderedElements.get(placeholderElement.dataset['code'] ?? ''); @@ -197,6 +255,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende // Signal size changes for image tags if (options.asyncRenderCallback) { + // eslint-disable-next-line no-restricted-syntax for (const img of outElement.getElementsByTagName('img')) { const listener = disposables.add(DOM.addDisposableListener(img, 'load', () => { listener.dispose(); @@ -227,6 +286,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende } // Remove/disable inputs + // eslint-disable-next-line no-restricted-syntax for (const input of [...outElement.getElementsByTagName('input')]) { if (input.attributes.getNamedItem('type')?.value === 'checkbox') { input.setAttribute('disabled', ''); @@ -254,6 +314,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende } function rewriteRenderedLinks(markdown: IMarkdownString, options: MarkdownRenderOptions, root: HTMLElement) { + // eslint-disable-next-line no-restricted-syntax for (const el of root.querySelectorAll('img, audio, video, source')) { const src = el.getAttribute('src'); // Get the raw 'src' attribute value as text, not the resolved 'src' if (src) { @@ -275,6 +336,7 @@ function rewriteRenderedLinks(markdown: IMarkdownString, options: MarkdownRender } } + // eslint-disable-next-line no-restricted-syntax for (const el of root.querySelectorAll('a')) { const href = el.getAttribute('href'); // Get the raw 'href' attribute value as text, not the resolved 'href' el.setAttribute('href', ''); // Clear out href. We use the `data-href` for handling clicks instead @@ -300,6 +362,10 @@ function createMarkdownRenderer(marked: marked.Marked, options: MarkdownRenderOp renderer.link = defaultMarkedRenderers.link; renderer.paragraph = defaultMarkedRenderers.paragraph; + if (markdown.supportAlertSyntax) { + renderer.blockquote = createAlertBlockquoteRenderer(renderer.blockquote); + } + // Will collect [id, renderedElement] tuples const codeBlocks: Promise<[string, HTMLElement]>[] = []; const syncCodeBlocks: [string, HTMLElement][] = []; @@ -369,6 +435,7 @@ function activateLink(mdStr: IMarkdownString, options: MarkdownRenderOptions, ev onUnexpectedError(err); } finally { event.preventDefault(); + event.stopPropagation(); } } @@ -493,6 +560,7 @@ export const allowedMarkdownHtmlAttributes = Object.freeze> { - interface IMonacoEnvironment { - createTrustedTypesPolicy( - policyName: string, - policyOptions?: Options, - ): undefined | Pick>; - } - // eslint-disable-next-line local/code-no-any-casts - const monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment; + const monacoEnvironment = getMonacoEnvironment(); if (monacoEnvironment?.createTrustedTypesPolicy) { try { @@ -30,7 +24,7 @@ export function createTrustedTypesPolicy` + // eslint-disable-next-line no-restricted-syntax const root = rendered.element.querySelector('p')?.innerHTML; if (root) { safeSetInnerHtml(labelElement, root, buttonSanitizerConfig); @@ -371,7 +372,7 @@ export interface IButtonWithDropdownOptions extends IButtonOptions { export class ButtonWithDropdown extends Disposable implements IButton { readonly primaryButton: Button; - private readonly action: Action; + private readonly action: IAction; readonly dropdownButton: Button; private readonly separatorContainer: HTMLDivElement; private readonly separator: HTMLDivElement; @@ -393,7 +394,7 @@ export class ButtonWithDropdown extends Disposable implements IButton { this.primaryButton = this._register(new Button(this.element, options)); this._register(this.primaryButton.onDidClick(e => this._onDidClick.fire(e))); - this.action = this._register(new Action('primaryAction', renderAsPlaintext(this.primaryButton.label), undefined, true, async () => this._onDidClick.fire(undefined))); + this.action = toAction({ id: 'primaryAction', label: renderAsPlaintext(this.primaryButton.label), run: async () => this._onDidClick.fire(undefined) }); this.separatorContainer = document.createElement('div'); this.separatorContainer.classList.add('monaco-button-dropdown-separator'); @@ -652,6 +653,7 @@ export class ButtonWithIcon extends Button { const rendered = renderMarkdown(value, undefined, document.createElement('span')); rendered.dispose(); + // eslint-disable-next-line no-restricted-syntax const root = rendered.element.querySelector('p')?.innerHTML; if (root) { safeSetInnerHtml(this._mdlabelElement, root, buttonSanitizerConfig); diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 2d5fc3a2eeb..28f3db1cc81 100644 Binary files a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf and b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf differ diff --git a/src/vs/base/browser/ui/dialog/dialog.ts b/src/vs/base/browser/ui/dialog/dialog.ts index b569359a06c..6c972e7866b 100644 --- a/src/vs/base/browser/ui/dialog/dialog.ts +++ b/src/vs/base/browser/ui/dialog/dialog.ts @@ -136,6 +136,7 @@ export class Dialog extends Disposable { const customFooter = this.footerContainer.appendChild($('#monaco-dialog-footer.dialog-footer')); this.options.renderFooter(customFooter); + // eslint-disable-next-line no-restricted-syntax for (const el of this.footerContainer.querySelectorAll('a')) { el.tabIndex = 0; } @@ -177,6 +178,7 @@ export class Dialog extends Disposable { const customBody = this.messageContainer.appendChild($('#monaco-dialog-message-body.dialog-message-body')); this.options.renderBody(customBody); + // eslint-disable-next-line no-restricted-syntax for (const el of this.messageContainer.querySelectorAll('a')) { el.tabIndex = 0; } @@ -378,6 +380,7 @@ export class Dialog extends Disposable { let focusedIndex = -1; if (this.messageContainer) { + // eslint-disable-next-line no-restricted-syntax const links = this.messageContainer.querySelectorAll('a'); for (const link of links) { focusableElements.push(link); @@ -422,6 +425,7 @@ export class Dialog extends Disposable { } if (this.footerContainer) { + // eslint-disable-next-line no-restricted-syntax const links = this.footerContainer.querySelectorAll('a'); for (const link of links) { focusableElements.push(link); @@ -562,6 +566,7 @@ export class Dialog extends Disposable { this.element.style.border = border; if (linkFgColor) { + // eslint-disable-next-line no-restricted-syntax for (const el of [...this.messageContainer.getElementsByTagName('a'), ...this.footerContainer?.getElementsByTagName('a') ?? []]) { el.style.color = linkFgColor; } diff --git a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts index 1842d6444d4..6b3610b67c1 100644 --- a/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts +++ b/src/vs/base/browser/ui/dropdown/dropdownActionViewItem.ts @@ -73,6 +73,7 @@ export class DropdownMenuActionViewItem extends BaseActionViewItem { const labelRenderer: ILabelRenderer = (el: HTMLElement): IDisposable | null => { this.element = append(el, $('a.action-label')); + this.setAriaLabelAttributes(this.element); return this.renderLabel(this.element); }; diff --git a/src/vs/base/browser/ui/findinput/findInput.ts b/src/vs/base/browser/ui/findinput/findInput.ts index 2182b0bd2cb..2c9c47f4d5e 100644 --- a/src/vs/base/browser/ui/findinput/findInput.ts +++ b/src/vs/base/browser/ui/findinput/findInput.ts @@ -16,8 +16,8 @@ import { KeyCode } from '../../../common/keyCodes.js'; import './findInput.css'; import * as nls from '../../../../nls.js'; import { DisposableStore, MutableDisposable } from '../../../common/lifecycle.js'; -import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js'; import { IHistory } from '../../../common/history.js'; +import type { IHoverLifecycleOptions } from '../hover/hover.js'; export interface IFindInputOptions { @@ -38,6 +38,7 @@ export interface IFindInputOptions { readonly toggleStyles: IToggleStyles; readonly inputBoxStyles: IInputBoxStyles; readonly history?: IHistory; + readonly hoverLifecycleOptions?: IHoverLifecycleOptions; } const NLS_DEFAULT_LABEL = nls.localize('defaultLabel', "input"); @@ -114,13 +115,12 @@ export class FindInput extends Widget { history: options.history })); - const hoverDelegate = this._register(createInstantHoverDelegate()); - if (this.showCommonFindToggles) { + const hoverLifecycleOptions: IHoverLifecycleOptions = options?.hoverLifecycleOptions || { groupId: 'find-input' }; this.regex = this._register(new RegexToggle({ appendTitle: appendRegexLabel, isChecked: false, - hoverDelegate, + hoverLifecycleOptions, ...options.toggleStyles })); this._register(this.regex.onChange(viaKeyboard => { @@ -137,7 +137,7 @@ export class FindInput extends Widget { this.wholeWords = this._register(new WholeWordsToggle({ appendTitle: appendWholeWordsLabel, isChecked: false, - hoverDelegate, + hoverLifecycleOptions, ...options.toggleStyles })); this._register(this.wholeWords.onChange(viaKeyboard => { @@ -151,7 +151,7 @@ export class FindInput extends Widget { this.caseSensitive = this._register(new CaseSensitiveToggle({ appendTitle: appendCaseSensitiveLabel, isChecked: false, - hoverDelegate, + hoverLifecycleOptions, ...options.toggleStyles })); this._register(this.caseSensitive.onChange(viaKeyboard => { diff --git a/src/vs/base/browser/ui/findinput/findInputToggles.ts b/src/vs/base/browser/ui/findinput/findInputToggles.ts index c13fcafe5f8..b2eec09e331 100644 --- a/src/vs/base/browser/ui/findinput/findInputToggles.ts +++ b/src/vs/base/browser/ui/findinput/findInputToggles.ts @@ -3,11 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js'; -import { IHoverDelegate } from '../hover/hoverDelegate.js'; import { Toggle } from '../toggle/toggle.js'; import { Codicon } from '../../../common/codicons.js'; import * as nls from '../../../../nls.js'; +import { type IHoverLifecycleOptions } from '../hover/hover.js'; export interface IFindInputToggleOpts { readonly appendTitle: string; @@ -15,7 +14,7 @@ export interface IFindInputToggleOpts { readonly inputActiveOptionBorder: string | undefined; readonly inputActiveOptionForeground: string | undefined; readonly inputActiveOptionBackground: string | undefined; - readonly hoverDelegate?: IHoverDelegate; + readonly hoverLifecycleOptions?: IHoverLifecycleOptions; } const NLS_CASE_SENSITIVE_TOGGLE_LABEL = nls.localize('caseDescription', "Match Case"); @@ -28,7 +27,7 @@ export class CaseSensitiveToggle extends Toggle { icon: Codicon.caseSensitive, title: NLS_CASE_SENSITIVE_TOGGLE_LABEL + opts.appendTitle, isChecked: opts.isChecked, - hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'), + hoverLifecycleOptions: opts.hoverLifecycleOptions, inputActiveOptionBorder: opts.inputActiveOptionBorder, inputActiveOptionForeground: opts.inputActiveOptionForeground, inputActiveOptionBackground: opts.inputActiveOptionBackground @@ -42,7 +41,7 @@ export class WholeWordsToggle extends Toggle { icon: Codicon.wholeWord, title: NLS_WHOLE_WORD_TOGGLE_LABEL + opts.appendTitle, isChecked: opts.isChecked, - hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'), + hoverLifecycleOptions: opts.hoverLifecycleOptions, inputActiveOptionBorder: opts.inputActiveOptionBorder, inputActiveOptionForeground: opts.inputActiveOptionForeground, inputActiveOptionBackground: opts.inputActiveOptionBackground @@ -56,7 +55,7 @@ export class RegexToggle extends Toggle { icon: Codicon.regex, title: NLS_REGEX_TOGGLE_LABEL + opts.appendTitle, isChecked: opts.isChecked, - hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'), + hoverLifecycleOptions: opts.hoverLifecycleOptions, inputActiveOptionBorder: opts.inputActiveOptionBorder, inputActiveOptionForeground: opts.inputActiveOptionForeground, inputActiveOptionBackground: opts.inputActiveOptionBackground diff --git a/src/vs/base/browser/ui/findinput/replaceInput.ts b/src/vs/base/browser/ui/findinput/replaceInput.ts index 018a26fc1bd..10c5b47b653 100644 --- a/src/vs/base/browser/ui/findinput/replaceInput.ts +++ b/src/vs/base/browser/ui/findinput/replaceInput.ts @@ -16,8 +16,8 @@ import { Emitter, Event } from '../../../common/event.js'; import { KeyCode } from '../../../common/keyCodes.js'; import './findInput.css'; import * as nls from '../../../../nls.js'; -import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js'; import { IHistory } from '../../../common/history.js'; +import { type IHoverLifecycleOptions } from '../hover/hover.js'; export interface IReplaceInputOptions { @@ -28,6 +28,7 @@ export interface IReplaceInputOptions { readonly flexibleHeight?: boolean; readonly flexibleWidth?: boolean; readonly flexibleMaxHeight?: number; + readonly hoverLifecycleOptions?: IHoverLifecycleOptions; readonly appendPreserveCaseLabel?: string; readonly history?: IHistory; @@ -46,7 +47,7 @@ class PreserveCaseToggle extends Toggle { icon: Codicon.preserveCase, title: NLS_PRESERVE_CASE_LABEL + opts.appendTitle, isChecked: opts.isChecked, - hoverDelegate: opts.hoverDelegate ?? getDefaultHoverDelegate('element'), + hoverLifecycleOptions: opts.hoverLifecycleOptions, inputActiveOptionBorder: opts.inputActiveOptionBorder, inputActiveOptionForeground: opts.inputActiveOptionForeground, inputActiveOptionBackground: opts.inputActiveOptionBackground, @@ -120,6 +121,7 @@ export class ReplaceInput extends Widget { this.preserveCase = this._register(new PreserveCaseToggle({ appendTitle: appendPreserveCaseLabel, isChecked: false, + hoverLifecycleOptions: options.hoverLifecycleOptions, ...options.toggleStyles })); this._register(this.preserveCase.onChange(viaKeyboard => { diff --git a/src/vs/base/browser/ui/grid/gridview.ts b/src/vs/base/browser/ui/grid/gridview.ts index efa08927c1c..46821d6fcb8 100644 --- a/src/vs/base/browser/ui/grid/gridview.ts +++ b/src/vs/base/browser/ui/grid/gridview.ts @@ -1717,7 +1717,7 @@ export class GridView implements IDisposable { const height = json.height; const result = new GridView(options); - result._deserialize(json.root as ISerializedBranchNode, orientation, deserializer, height); + result._deserialize(json.root, orientation, deserializer, height); return result; } @@ -1729,7 +1729,7 @@ export class GridView implements IDisposable { private _deserializeNode(node: ISerializedNode, orientation: Orientation, deserializer: IViewDeserializer, orthogonalSize: number): Node { let result: Node; if (node.type === 'branch') { - const serializedChildren = node.data as ISerializedNode[]; + const serializedChildren = node.data; const children = serializedChildren.map(serializedChild => { return { node: this._deserializeNode(serializedChild, orthogonal(orientation), deserializer, node.size), diff --git a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts index 0c6cb1f1fa7..006a832f11e 100644 --- a/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts +++ b/src/vs/base/browser/ui/highlightedlabel/highlightedLabel.ts @@ -22,12 +22,6 @@ export interface IHighlight { } export interface IHighlightedLabelOptions { - - /** - * Whether the label supports rendering icons. - */ - readonly supportIcons?: boolean; - readonly hoverDelegate?: IHoverDelegate; } @@ -41,7 +35,6 @@ export class HighlightedLabel extends Disposable { private text: string = ''; private title: string = ''; private highlights: readonly IHighlight[] = []; - private supportIcons: boolean; private didEverRender: boolean = false; private customHover: IManagedHover | undefined; @@ -53,7 +46,6 @@ export class HighlightedLabel extends Disposable { constructor(container: HTMLElement, private readonly options?: IHighlightedLabelOptions) { super(); - this.supportIcons = options?.supportIcons ?? false; this.domNode = dom.append(container, dom.$('span.monaco-highlighted-label')); } @@ -73,7 +65,7 @@ export class HighlightedLabel extends Disposable { * @param escapeNewLines Whether to escape new lines. * @returns */ - set(text: string | undefined, highlights: readonly IHighlight[] = [], title: string = '', escapeNewLines?: boolean) { + set(text: string | undefined, highlights: readonly IHighlight[] = [], title: string = '', escapeNewLines?: boolean, supportIcons?: boolean) { if (!text) { text = ''; } @@ -90,10 +82,10 @@ export class HighlightedLabel extends Disposable { this.text = text; this.title = title; this.highlights = highlights; - this.render(); + this.render(supportIcons); } - private render(): void { + private render(supportIcons?: boolean): void { const children: Array = []; let pos = 0; @@ -105,7 +97,7 @@ export class HighlightedLabel extends Disposable { if (pos < highlight.start) { const substring = this.text.substring(pos, highlight.start); - if (this.supportIcons) { + if (supportIcons) { children.push(...renderLabelWithIcons(substring)); } else { children.push(substring); @@ -114,7 +106,7 @@ export class HighlightedLabel extends Disposable { } const substring = this.text.substring(pos, highlight.end); - const element = dom.$('span.highlight', undefined, ...this.supportIcons ? renderLabelWithIcons(substring) : [substring]); + const element = dom.$('span.highlight', undefined, ...supportIcons ? renderLabelWithIcons(substring) : [substring]); if (highlight.extraClasses) { element.classList.add(...highlight.extraClasses); @@ -126,7 +118,7 @@ export class HighlightedLabel extends Disposable { if (pos < this.text.length) { const substring = this.text.substring(pos,); - if (this.supportIcons) { + if (supportIcons) { children.push(...renderLabelWithIcons(substring)); } else { children.push(substring); diff --git a/src/vs/base/browser/ui/hover/hover.ts b/src/vs/base/browser/ui/hover/hover.ts index 6c682c3c083..50510f6e9a6 100644 --- a/src/vs/base/browser/ui/hover/hover.ts +++ b/src/vs/base/browser/ui/hover/hover.ts @@ -148,6 +148,17 @@ export interface IHoverWidget extends IDisposable { readonly isDisposed: boolean; } +export const enum HoverStyle { + /** + * The hover is anchored below the element with a pointer above it pointing at the target. + */ + Pointer = 1, + /** + * The hover is anchored to the bottom right of the cursor's location. + */ + Mouse = 2, +} + export interface IHoverOptions { /** * The content to display in the primary section of the hover. The type of text determines the @@ -205,6 +216,11 @@ export interface IHoverOptions { */ trapFocus?: boolean; + /** + * The style of the hover, this sets default values of {@link position} and {@link appearance}: + */ + style?: HoverStyle; + /** * Options that defines where the hover is positioned. */ diff --git a/src/vs/base/browser/ui/hover/hoverWidget.css b/src/vs/base/browser/ui/hover/hoverWidget.css index 11f1fdccc7c..85379221cf2 100644 --- a/src/vs/base/browser/ui/hover/hoverWidget.css +++ b/src/vs/base/browser/ui/hover/hoverWidget.css @@ -181,19 +181,6 @@ color: var(--vscode-textLink-activeForeground); } -/** - * Spans in markdown hovers need a margin-bottom to avoid looking cramped: - * https://github.com/microsoft/vscode/issues/101496 - - * This was later refined to only apply when the last child of a rendered markdown block (before the - * border or a `hr`) uses background color: - * https://github.com/microsoft/vscode/issues/228136 - */ -.monaco-hover .markdown-hover .hover-contents:not(.code-hover-contents):not(.html-hover-contents) p:last-child [style*="background-color"] { - margin-bottom: 4px; - display: inline-block; -} - /** * Add a slight margin to try vertically align codicons with any text * https://github.com/microsoft/vscode/issues/221359 diff --git a/src/vs/base/browser/ui/iconLabel/iconLabel.ts b/src/vs/base/browser/ui/iconLabel/iconLabel.ts index b3eedce65c8..468667aabc0 100644 --- a/src/vs/base/browser/ui/iconLabel/iconLabel.ts +++ b/src/vs/base/browser/ui/iconLabel/iconLabel.ts @@ -16,6 +16,7 @@ import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js'; import type { IManagedHoverTooltipMarkdownString } from '../hover/hover.js'; import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js'; import { URI } from '../../../common/uri.js'; +import { ThemeIcon } from '../../../common/themables.js'; export interface IIconLabelCreationOptions { readonly supportHighlights?: boolean; @@ -31,6 +32,7 @@ export interface IIconLabelValueOptions { suffix?: string; hideIcon?: boolean; extraClasses?: readonly string[]; + bold?: boolean; italic?: boolean; strikethrough?: boolean; matches?: readonly IMatch[]; @@ -39,7 +41,8 @@ export interface IIconLabelValueOptions { disabledCommand?: boolean; readonly separator?: string; readonly domId?: string; - iconPath?: URI; + iconPath?: URI | ThemeIcon; + supportIcons?: boolean; } class FastLabelNode { @@ -136,6 +139,10 @@ export class IconLabel extends Disposable { labelClasses.push(...options.extraClasses); } + if (options.bold) { + labelClasses.push('bold'); + } + if (options.italic) { labelClasses.push('italic'); } @@ -156,6 +163,7 @@ export class IconLabel extends Disposable { } } + // eslint-disable-next-line no-restricted-syntax const existingIconNode = this.domNode.element.querySelector('.monaco-icon-label-iconpath'); if (options?.iconPath) { let iconNode; @@ -165,7 +173,13 @@ export class IconLabel extends Disposable { } else { iconNode = existingIconNode; } - iconNode.style.backgroundImage = css.asCSSUrl(options?.iconPath); + if (ThemeIcon.isThemeIcon(options.iconPath)) { + const iconClass = ThemeIcon.asClassName(options.iconPath); + iconNode.className = `monaco-icon-label-iconpath ${iconClass}`; + iconNode.style.backgroundImage = ''; + } else { + iconNode.style.backgroundImage = css.asCSSUrl(options?.iconPath); + } iconNode.style.backgroundRepeat = 'no-repeat'; iconNode.style.backgroundPosition = 'center'; iconNode.style.backgroundSize = 'contain'; @@ -185,7 +199,8 @@ export class IconLabel extends Disposable { if (description || this.descriptionNode) { const descriptionNode = this.getOrCreateDescriptionNode(); if (descriptionNode instanceof HighlightedLabel) { - descriptionNode.set(description || '', options ? options.descriptionMatches : undefined, undefined, options?.labelEscapeNewLines); + const supportIcons = options?.supportIcons ?? this.creationOptions?.supportIcons; + descriptionNode.set(description || '', options ? options.descriptionMatches : undefined, undefined, options?.labelEscapeNewLines, supportIcons); this.setupHover(descriptionNode.element, options?.descriptionTitle); } else { descriptionNode.textContent = description && options?.labelEscapeNewLines ? HighlightedLabel.escapeNewLines(description, []) : (description || ''); @@ -247,7 +262,7 @@ export class IconLabel extends Disposable { if (!this.descriptionNode) { const descriptionContainer = this._register(new FastLabelNode(dom.append(this.labelContainer, dom.$('span.monaco-icon-description-container')))); if (this.creationOptions?.supportDescriptionHighlights) { - this.descriptionNode = this._register(new HighlightedLabel(dom.append(descriptionContainer.element, dom.$('span.label-description')), { supportIcons: !!this.creationOptions.supportIcons })); + this.descriptionNode = this._register(new HighlightedLabel(dom.append(descriptionContainer.element, dom.$('span.label-description')))); } else { this.descriptionNode = this._register(new FastLabelNode(dom.append(descriptionContainer.element, dom.$('span.label-description')))); } @@ -338,14 +353,17 @@ class LabelWithHighlights extends Disposable { this.label = label; this.options = options; + // Determine supportIcons: use option if provided, otherwise use constructor value + const supportIcons = options?.supportIcons ?? this.supportIcons; + if (typeof label === 'string') { if (!this.singleLabel) { this.container.textContent = ''; this.container.classList.remove('multiple'); - this.singleLabel = this._register(new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), { supportIcons: this.supportIcons })); + this.singleLabel = this._register(new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })))); } - this.singleLabel.set(label, options?.matches, undefined, options?.labelEscapeNewLines); + this.singleLabel.set(label, options?.matches, undefined, options?.labelEscapeNewLines, supportIcons); } else { this.container.textContent = ''; this.container.classList.add('multiple'); @@ -360,8 +378,8 @@ class LabelWithHighlights extends Disposable { const id = options?.domId && `${options?.domId}_${i}`; const name = dom.$('a.label-name', { id, 'data-icon-label-count': label.length, 'data-icon-label-index': i, 'role': 'treeitem' }); - const highlightedLabel = this._register(new HighlightedLabel(dom.append(this.container, name), { supportIcons: this.supportIcons })); - highlightedLabel.set(l, m, undefined, options?.labelEscapeNewLines); + const highlightedLabel = this._register(new HighlightedLabel(dom.append(this.container, name))); + highlightedLabel.set(l, m, undefined, options?.labelEscapeNewLines, supportIcons); if (i < label.length - 1) { dom.append(name, dom.$('span.label-separator', undefined, separator)); diff --git a/src/vs/base/browser/ui/iconLabel/iconlabel.css b/src/vs/base/browser/ui/iconLabel/iconlabel.css index ed9278d7087..d3dfd9a586b 100644 --- a/src/vs/base/browser/ui/iconLabel/iconlabel.css +++ b/src/vs/base/browser/ui/iconLabel/iconlabel.css @@ -33,9 +33,8 @@ .monaco-icon-label-iconpath { width: 16px; - height: 16px; - padding-left: 2px; - margin-top: 2px; + height: 22px; + margin-right: 6px; display: flex; } @@ -79,6 +78,11 @@ opacity: .95; } +.monaco-icon-label.bold > .monaco-icon-label-container > .monaco-icon-name-container > .label-name, +.monaco-icon-label.bold > .monaco-icon-label-container > .monaco-icon-description-container > .label-description { + font-weight: bold; +} + .monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-name-container > .label-name, .monaco-icon-label.italic > .monaco-icon-label-container > .monaco-icon-description-container > .label-description { font-style: italic; diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index 44af8e92aee..df93d742649 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -536,6 +536,12 @@ export class InputBox extends Widget { this.state = 'idle'; } + private layoutMessage(): void { + if (this.state === 'open' && this.contextViewProvider) { + this.contextViewProvider.layout(); + } + } + private onValueChange(): void { this._onDidChange.fire(this.value); @@ -586,6 +592,7 @@ export class InputBox extends Widget { public layout(): void { if (!this.mirror) { + this.layoutMessage(); return; } @@ -597,6 +604,8 @@ export class InputBox extends Widget { this.input.style.height = this.cachedHeight + 'px'; this._onDidHeightChange.fire(this.cachedContentHeight); } + + this.layoutMessage(); } public insertAtCursor(text: string): void { diff --git a/src/vs/base/browser/ui/list/listPaging.ts b/src/vs/base/browser/ui/list/listPaging.ts index cb486cfaaba..04c2b8de2ef 100644 --- a/src/vs/base/browser/ui/list/listPaging.ts +++ b/src/vs/base/browser/ui/list/listPaging.ts @@ -6,7 +6,7 @@ import { range } from '../../../common/arrays.js'; import { CancellationTokenSource } from '../../../common/cancellation.js'; import { Event } from '../../../common/event.js'; -import { Disposable, IDisposable } from '../../../common/lifecycle.js'; +import { Disposable, DisposableStore, IDisposable } from '../../../common/lifecycle.js'; import { IPagedModel } from '../../../common/paging.js'; import { ScrollbarVisibility } from '../../../common/scrollable.js'; import './list.css'; @@ -122,8 +122,9 @@ function fromPagedListOptions(modelProvider: () => IPagedModel, options: I export class PagedList implements IDisposable { - private list: List; + private readonly list: List; private _model!: IPagedModel; + private readonly modelDisposables = new DisposableStore(); constructor( user: string, @@ -202,8 +203,10 @@ export class PagedList implements IDisposable { } set model(model: IPagedModel) { + this.modelDisposables.clear(); this._model = model; this.list.splice(0, this.list.length, range(model.length)); + this.modelDisposables.add(model.onDidIncrementLength(newLength => this.list.splice(this.list.length, 0, range(this.list.length, newLength)))); } get length(): number { @@ -296,5 +299,6 @@ export class PagedList implements IDisposable { dispose(): void { this.list.dispose(); + this.modelDisposables.dispose(); } } diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 7fc6ea246b6..6f2a2349d5b 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -58,11 +58,13 @@ export const enum ListViewTargetSector { BOTTOM = 3 // [75%-100%) } +export type CheckBoxAccessibleState = boolean | 'mixed'; + export interface IListViewAccessibilityProvider { getSetSize?(element: T, index: number, listLength: number): number; getPosInSet?(element: T, index: number): number; getRole?(element: T): AriaRole | undefined; - isChecked?(element: T): boolean | IValueWithChangeEvent | undefined; + isChecked?(element: T): CheckBoxAccessibleState | IValueWithChangeEvent | undefined; } export interface IListViewOptionsUpdate { @@ -197,7 +199,7 @@ class ListViewAccessibilityProvider implements Required number; readonly getPosInSet: (element: T, index: number) => number; readonly getRole: (element: T) => AriaRole | undefined; - readonly isChecked: (element: T) => boolean | IValueWithChangeEvent | undefined; + readonly isChecked: (element: T) => CheckBoxAccessibleState | IValueWithChangeEvent | undefined; constructor(accessibilityProvider?: IListViewAccessibilityProvider) { if (accessibilityProvider?.getSetSize) { @@ -959,11 +961,12 @@ export class ListView implements IListView { item.row.domNode.setAttribute('role', role); const checked = this.accessibilityProvider.isChecked(item.element); + const toAriaState = (value: CheckBoxAccessibleState) => value === 'mixed' ? 'mixed' : String(!!value); - if (typeof checked === 'boolean') { - item.row.domNode.setAttribute('aria-checked', String(!!checked)); + if (typeof checked === 'boolean' || checked === 'mixed') { + item.row.domNode.setAttribute('aria-checked', toAriaState(checked)); } else if (checked) { - const update = (checked: boolean) => item.row!.domNode.setAttribute('aria-checked', String(!!checked)); + const update = (value: CheckBoxAccessibleState) => item.row!.domNode.setAttribute('aria-checked', toAriaState(value)); update(checked.value); item.checkedDisposable = checked.onDidChange(() => update(checked.value)); } @@ -1115,9 +1118,9 @@ export class ListView implements IListView { @memoize get onMouseOver(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseover')).event, e => this.toMouseEvent(e), this.disposables); } @memoize get onMouseMove(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mousemove')).event, e => this.toMouseEvent(e), this.disposables); } @memoize get onMouseOut(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'mouseout')).event, e => this.toMouseEvent(e), this.disposables); } - @memoize get onContextMenu(): Event | IListGestureEvent> { return Event.any | IListGestureEvent>(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'contextmenu')).event, e => this.toMouseEvent(e), this.disposables), Event.map(this.disposables.add(new DomEmitter(this.domNode, TouchEventType.Contextmenu)).event as Event, e => this.toGestureEvent(e), this.disposables)); } + @memoize get onContextMenu(): Event | IListGestureEvent> { return Event.any | IListGestureEvent>(Event.map(this.disposables.add(new DomEmitter(this.domNode, 'contextmenu')).event, e => this.toMouseEvent(e), this.disposables), Event.map(this.disposables.add(new DomEmitter(this.domNode, TouchEventType.Contextmenu)).event, e => this.toGestureEvent(e), this.disposables)); } @memoize get onTouchStart(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.domNode, 'touchstart')).event, e => this.toTouchEvent(e), this.disposables); } - @memoize get onTap(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.rowsContainer, TouchEventType.Tap)).event, e => this.toGestureEvent(e as GestureEvent), this.disposables); } + @memoize get onTap(): Event> { return Event.map(this.disposables.add(new DomEmitter(this.rowsContainer, TouchEventType.Tap)).event, e => this.toGestureEvent(e), this.disposables); } private toMouseEvent(browserEvent: MouseEvent): IListMouseEvent { const index = this.getItemIndexFromEventTarget(browserEvent.target || null); @@ -1363,7 +1366,7 @@ export class ListView implements IListView { } for (const index of feedback) { - const item = this.items[index]!; + const item = this.items[index]; item.dropTarget = true; item.row?.domNode.classList.add(dragOverEffectPosition); @@ -1371,7 +1374,7 @@ export class ListView implements IListView { this.currentDragFeedbackDisposable = toDisposable(() => { for (const index of feedback) { - const item = this.items[index]!; + const item = this.items[index]; item.dropTarget = false; item.row?.domNode.classList.remove(dragOverEffectPosition); @@ -1633,8 +1636,12 @@ export class ListView implements IListView { if (item.row) { item.row.domNode.style.height = ''; item.size = item.row.domNode.offsetHeight; - if (item.size === 0 && !isAncestor(item.row.domNode, getWindow(item.row.domNode).document.body)) { - console.warn('Measuring item node that is not in DOM! Add ListView to the DOM before measuring row height!', new Error().stack); + if (item.size === 0) { + if (!isAncestor(item.row.domNode, getWindow(item.row.domNode).document.body)) { + console.warn('Measuring item node that is not in DOM! Add ListView to the DOM before measuring row height!', new Error().stack); + } else { + console.warn('Measured item node at 0px- ensure that ListView is not display:none before measuring row height!', new Error().stack); + } } item.lastDynamicHeightWidth = this.renderWidth; return item.size - size; diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index f4e96e204e2..c637ba43c88 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -631,6 +631,7 @@ class DOMFocusController implements IDisposable { return; } + // eslint-disable-next-line no-restricted-syntax const tabIndexElement = focusedDomElement.querySelector('[tabIndex]'); if (!tabIndexElement || !(isHTMLElement(tabIndexElement)) || tabIndexElement.tabIndex === -1) { diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index 607dc187a74..29240b5c9a4 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -118,7 +118,7 @@ export class MenuBar extends Disposable { this._register(DOM.ModifierKeyEmitter.getInstance().event(this.onModifierKeyToggled, this)); this._register(DOM.addDisposableListener(this.container, DOM.EventType.KEY_DOWN, (e) => { - const event = new StandardKeyboardEvent(e as KeyboardEvent); + const event = new StandardKeyboardEvent(e); let eventHandled = true; const key = !!e.key ? e.key.toLocaleLowerCase() : ''; @@ -157,7 +157,7 @@ export class MenuBar extends Disposable { })); this._register(DOM.addDisposableListener(this.container, DOM.EventType.FOCUS_IN, (e) => { - const event = e as FocusEvent; + const event = e; if (event.relatedTarget) { if (!this.container.contains(event.relatedTarget as HTMLElement)) { @@ -167,7 +167,7 @@ export class MenuBar extends Disposable { })); this._register(DOM.addDisposableListener(this.container, DOM.EventType.FOCUS_OUT, (e) => { - const event = e as FocusEvent; + const event = e; // We are losing focus and there is no related target, e.g. webview case if (!event.relatedTarget) { @@ -228,7 +228,7 @@ export class MenuBar extends Disposable { this.updateLabels(titleElement, buttonElement, menuBarMenu.label); this._register(DOM.addDisposableListener(buttonElement, DOM.EventType.KEY_UP, (e) => { - const event = new StandardKeyboardEvent(e as KeyboardEvent); + const event = new StandardKeyboardEvent(e); let eventHandled = true; if ((event.equals(KeyCode.DownArrow) || event.equals(KeyCode.Enter)) && !this.isOpen) { @@ -324,7 +324,7 @@ export class MenuBar extends Disposable { buttonElement.style.visibility = 'hidden'; this._register(DOM.addDisposableListener(buttonElement, DOM.EventType.KEY_UP, (e) => { - const event = new StandardKeyboardEvent(e as KeyboardEvent); + const event = new StandardKeyboardEvent(e); let eventHandled = true; const triggerKeys = [KeyCode.Enter]; diff --git a/src/vs/base/browser/ui/progressbar/progressAccessibilitySignal.ts b/src/vs/base/browser/ui/progressbar/progressAccessibilitySignal.ts index db5d0b0cee3..5419c8819c6 100644 --- a/src/vs/base/browser/ui/progressbar/progressAccessibilitySignal.ts +++ b/src/vs/base/browser/ui/progressbar/progressAccessibilitySignal.ts @@ -14,10 +14,10 @@ const nullScopedAccessibilityProgressSignalFactory = () => ({ }); let progressAccessibilitySignalSchedulerFactory: (msDelayTime: number, msLoopTime?: number) => IScopedAccessibilityProgressSignalDelegate = nullScopedAccessibilityProgressSignalFactory; -export function setProgressAcccessibilitySignalScheduler(progressAccessibilitySignalScheduler: (msDelayTime: number, msLoopTime?: number) => IScopedAccessibilityProgressSignalDelegate) { +export function setProgressAccessibilitySignalScheduler(progressAccessibilitySignalScheduler: (msDelayTime: number, msLoopTime?: number) => IScopedAccessibilityProgressSignalDelegate) { progressAccessibilitySignalSchedulerFactory = progressAccessibilitySignalScheduler; } -export function getProgressAcccessibilitySignalScheduler(msDelayTime: number, msLoopTime?: number): IScopedAccessibilityProgressSignalDelegate { +export function getProgressAccessibilitySignalScheduler(msDelayTime: number, msLoopTime?: number): IScopedAccessibilityProgressSignalDelegate { return progressAccessibilitySignalSchedulerFactory(msDelayTime, msLoopTime); } diff --git a/src/vs/base/browser/ui/progressbar/progressbar.ts b/src/vs/base/browser/ui/progressbar/progressbar.ts index 3b0a5e2f5e0..a369fb81871 100644 --- a/src/vs/base/browser/ui/progressbar/progressbar.ts +++ b/src/vs/base/browser/ui/progressbar/progressbar.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { hide, show } from '../../dom.js'; -import { getProgressAcccessibilitySignalScheduler } from './progressAccessibilitySignal.js'; +import { getProgressAccessibilitySignalScheduler } from './progressAccessibilitySignal.js'; import { RunOnceScheduler } from '../../../common/async.js'; import { Disposable, IDisposable, MutableDisposable } from '../../../common/lifecycle.js'; import { isNumber } from '../../../common/types.js'; @@ -206,7 +206,7 @@ export class ProgressBar extends Disposable { show(delay?: number): void { this.showDelayedScheduler.cancel(); - this.progressSignal.value = getProgressAcccessibilitySignalScheduler(ProgressBar.PROGRESS_SIGNAL_DEFAULT_DELAY); + this.progressSignal.value = getProgressAccessibilitySignalScheduler(ProgressBar.PROGRESS_SIGNAL_DEFAULT_DELAY); if (typeof delay === 'number') { this.showDelayedScheduler.schedule(delay); diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts index cc899c1c4f3..6f2fcb52276 100644 --- a/src/vs/base/browser/ui/sash/sash.ts +++ b/src/vs/base/browser/ui/sash/sash.ts @@ -511,6 +511,7 @@ export class Sash extends Disposable { return; } + // eslint-disable-next-line no-restricted-syntax const iframes = this.el.ownerDocument.getElementsByTagName('iframe'); for (const iframe of iframes) { iframe.classList.add(PointerEventsDisabledCssClass); // disable mouse events on iframes as long as we drag the sash diff --git a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css index 84c17370894..be500bc2e56 100644 --- a/src/vs/base/browser/ui/scrollbar/media/scrollbars.css +++ b/src/vs/base/browser/ui/scrollbar/media/scrollbars.css @@ -59,6 +59,10 @@ box-shadow: var(--vscode-scrollbar-shadow) 6px 0 6px -6px inset; } +.monaco-scrollable-element > .scrollbar { + background: var(--vscode-scrollbar-background); +} + .monaco-scrollable-element > .scrollbar > .slider { background: var(--vscode-scrollbarSlider-background); } diff --git a/src/vs/base/browser/ui/selectBox/selectBox.ts b/src/vs/base/browser/ui/selectBox/selectBox.ts index 1e023ae4e4e..335c2c9c09b 100644 --- a/src/vs/base/browser/ui/selectBox/selectBox.ts +++ b/src/vs/base/browser/ui/selectBox/selectBox.ts @@ -53,6 +53,11 @@ export interface ISelectOptionItem { isDisabled?: boolean; } +export const SeparatorSelectOption: Readonly = Object.freeze({ + text: '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500', + isDisabled: true, +}); + export interface ISelectBoxStyles extends IListStyles { readonly selectBackground: string | undefined; readonly selectListBackground: string | undefined; diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css index 292cd2dd1e1..dcb66d31c5a 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.css +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.css @@ -3,21 +3,11 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -/* Use custom CSS vars to expose padding into parent select for padding calculation */ -.monaco-select-box-dropdown-padding { - --dropdown-padding-top: 1px; - --dropdown-padding-bottom: 1px; -} - -.hc-black .monaco-select-box-dropdown-padding, -.hc-light .monaco-select-box-dropdown-padding { - --dropdown-padding-top: 3px; - --dropdown-padding-bottom: 4px; -} - .monaco-select-box-dropdown-container { display: none; - box-sizing: border-box; + box-sizing: border-box; + border-radius: 5px; + box-shadow: 0 2px 8px var(--vscode-widget-shadow); } .monaco-select-box-dropdown-container > .select-box-details-pane > .select-box-description-markdown * { @@ -41,35 +31,34 @@ text-align: left; width: 1px; overflow: hidden; - border-bottom-left-radius: 3px; - border-bottom-right-radius: 3px; } .monaco-select-box-dropdown-container > .select-box-dropdown-list-container { flex: 0 0 auto; align-self: flex-start; - padding-top: var(--dropdown-padding-top); - padding-bottom: var(--dropdown-padding-bottom); - padding-left: 1px; - padding-right: 1px; width: 100%; overflow: hidden; - box-sizing: border-box; + box-sizing: border-box; } .monaco-select-box-dropdown-container > .select-box-details-pane { padding: 5px; } -.hc-black .monaco-select-box-dropdown-container > .select-box-dropdown-list-container { - padding-top: var(--dropdown-padding-top); - padding-bottom: var(--dropdown-padding-bottom); -} - .monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row { cursor: pointer; } +.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:first-child { + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row:last-child { + border-bottom-left-radius: 5px; + border-bottom-right-radius: 5px; +} + .monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .option-text { text-overflow: ellipsis; overflow: hidden; @@ -100,12 +89,12 @@ /* https://webaim.org/techniques/css/invisiblecontent/ */ .monaco-select-box-dropdown-container > .select-box-dropdown-list-container .monaco-list .monaco-list-row > .visually-hidden { - position: absolute; - left: -10000px; - top: auto; - width: 1px; - height: 1px; - overflow: hidden; + position: absolute; + left: -10000px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; } .monaco-select-box-dropdown-container > .select-box-dropdown-container-width-control { diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts index c6a1c8a3dbe..f6c2ff1cb4f 100644 --- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts +++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts @@ -7,7 +7,7 @@ import { localize } from '../../../../nls.js'; import * as arrays from '../../../common/arrays.js'; import { Emitter, Event } from '../../../common/event.js'; import { KeyCode, KeyCodeUtils } from '../../../common/keyCodes.js'; -import { Disposable, IDisposable } from '../../../common/lifecycle.js'; +import { Disposable, DisposableStore, IDisposable } from '../../../common/lifecycle.js'; import { isMacintosh } from '../../../common/platform.js'; import { ScrollbarVisibility } from '../../../common/scrollable.js'; import * as cssJs from '../../cssValue.js'; @@ -15,7 +15,7 @@ import * as dom from '../../dom.js'; import * as domStylesheetsJs from '../../domStylesheets.js'; import { DomEmitter } from '../../event.js'; import { StandardKeyboardEvent } from '../../keyboardEvent.js'; -import { MarkdownActionHandler, renderMarkdown } from '../../markdownRenderer.js'; +import { IRenderedMarkdown, MarkdownActionHandler, renderMarkdown } from '../../markdownRenderer.js'; import { AnchorPosition, IContextViewProvider } from '../contextview/contextview.js'; import type { IManagedHover } from '../hover/hover.js'; import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js'; @@ -103,6 +103,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi private _dropDownPosition!: AnchorPosition; private _hasDetails: boolean = false; private selectionDetailsPane!: HTMLElement; + private readonly _selectionDetailsDisposables = this._register(new DisposableStore()); private _skipLayout: boolean = false; private _cachedMaxDetailsHeight?: number; private _hover?: IManagedHover; @@ -124,9 +125,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi } this.selectElement = document.createElement('select'); - - // Use custom CSS vars for padding calculation - this.selectElement.className = 'monaco-select-box monaco-select-box-dropdown-padding'; + this.selectElement.className = 'monaco-select-box'; if (typeof this.selectBoxOptions.ariaLabel === 'string') { this.selectElement.setAttribute('aria-label', this.selectBoxOptions.ariaLabel); @@ -175,8 +174,6 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi // SetUp ContextView container to hold select Dropdown this.contextViewProvider = contextViewProvider; this.selectDropDownContainer = dom.$('.monaco-select-box-dropdown-container'); - // Use custom CSS vars for padding calculation (shared with parent select) - this.selectDropDownContainer.classList.add('monaco-select-box-dropdown-padding'); // Setup container for select option details this.selectionDetailsPane = dom.append(this.selectDropDownContainer, $('.select-box-details-pane')); @@ -471,7 +468,6 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi }, onHide: () => { this.selectDropDownContainer.classList.remove('visible'); - this.selectElement.classList.remove('synthetic-focus'); }, anchorPosition: this._dropDownPosition }, this.selectBoxOptions.optionsAsChildren ? this.container : undefined); @@ -486,7 +482,6 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi layout: () => this.layoutSelectDropDown(), onHide: () => { this.selectDropDownContainer.classList.remove('visible'); - this.selectElement.classList.remove('synthetic-focus'); }, anchorPosition: this._dropDownPosition }, this.selectBoxOptions.optionsAsChildren ? this.container : undefined); @@ -558,15 +553,13 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi const window = dom.getWindow(this.selectElement); const selectPosition = dom.getDomNodePagePosition(this.selectElement); - const styles = dom.getWindow(this.selectElement).getComputedStyle(this.selectElement); - const verticalPadding = parseFloat(styles.getPropertyValue('--dropdown-padding-top')) + parseFloat(styles.getPropertyValue('--dropdown-padding-bottom')); const maxSelectDropDownHeightBelow = (window.innerHeight - selectPosition.top - selectPosition.height - (this.selectBoxOptions.minBottomMargin || 0)); const maxSelectDropDownHeightAbove = (selectPosition.top - SelectBoxList.DEFAULT_DROPDOWN_MINIMUM_TOP_MARGIN); // Determine optimal width - min(longest option), opt(parent select, excluding margins), max(ContextView controlled) const selectWidth = this.selectElement.offsetWidth; const selectMinWidth = this.setWidthControlElement(this.widthControlElement); - const selectOptimalWidth = Math.max(selectMinWidth, Math.round(selectWidth)).toString() + 'px'; + const selectOptimalWidth = `${Math.max(selectMinWidth, Math.round(selectWidth))}px`; this.selectDropDownContainer.style.width = selectOptimalWidth; @@ -580,9 +573,9 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi } const maxDetailsPaneHeight = this._hasDetails ? this._cachedMaxDetailsHeight! : 0; - const minRequiredDropDownHeight = listHeight + verticalPadding + maxDetailsPaneHeight; - const maxVisibleOptionsBelow = ((Math.floor((maxSelectDropDownHeightBelow - verticalPadding - maxDetailsPaneHeight) / this.getHeight()))); - const maxVisibleOptionsAbove = ((Math.floor((maxSelectDropDownHeightAbove - verticalPadding - maxDetailsPaneHeight) / this.getHeight()))); + const minRequiredDropDownHeight = listHeight + maxDetailsPaneHeight; + const maxVisibleOptionsBelow = ((Math.floor((maxSelectDropDownHeightBelow - maxDetailsPaneHeight) / this.getHeight()))); + const maxVisibleOptionsAbove = ((Math.floor((maxSelectDropDownHeightAbove - maxDetailsPaneHeight) / this.getHeight()))); // If we are only doing pre-layout check/adjust position only // Calculate vertical space available, flip up if insufficient @@ -672,20 +665,16 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi if (this._hasDetails) { // Leave the selectDropDownContainer to size itself according to children (list + details) - #57447 - this.selectList.getHTMLElement().style.height = (listHeight + verticalPadding) + 'px'; + this.selectList.getHTMLElement().style.height = `${listHeight}px`; this.selectDropDownContainer.style.height = ''; } else { - this.selectDropDownContainer.style.height = (listHeight + verticalPadding) + 'px'; + this.selectDropDownContainer.style.height = `${listHeight}px`; } this.updateDetail(this.selected); this.selectDropDownContainer.style.width = selectOptimalWidth; - - // Maintain focus outline on parent select as well as list container - tabindex for focus this.selectDropDownListContainer.setAttribute('tabindex', '0'); - this.selectElement.classList.add('synthetic-focus'); - this.selectDropDownContainer.classList.add('synthetic-focus'); return true; } else { @@ -712,7 +701,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi }); - container.textContent = this.options[longest].text + (!!this.options[longest].decoratorRight ? (this.options[longest].decoratorRight + ' ') : ''); + container.textContent = this.options[longest].text + (!!this.options[longest].decoratorRight ? `${this.options[longest].decoratorRight} ` : ''); elementWidth = dom.getTotalWidth(container); } @@ -868,7 +857,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi } - private renderDescriptionMarkdown(text: string, actionHandler?: MarkdownActionHandler): HTMLElement { + private renderDescriptionMarkdown(text: string, actionHandler?: MarkdownActionHandler): IRenderedMarkdown { const cleanRenderedMarkdown = (element: Node) => { for (let i = 0; i < element.childNodes.length; i++) { const child = element.childNodes.item(i); @@ -887,7 +876,7 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi rendered.element.classList.add('select-box-description-markdown'); cleanRenderedMarkdown(rendered.element); - return rendered.element; + return rendered; } // List Focus Change - passive - update details pane with newly focused element's data @@ -901,7 +890,10 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi } private updateDetail(selectedIndex: number): void { + // Reset + this._selectionDetailsDisposables.clear(); this.selectionDetailsPane.textContent = ''; + const option = this.options[selectedIndex]; const description = option?.description ?? ''; const descriptionIsMarkdown = option?.descriptionIsMarkdown ?? false; @@ -909,7 +901,8 @@ export class SelectBoxList extends Disposable implements ISelectBoxDelegate, ILi if (description) { if (descriptionIsMarkdown) { const actionHandler = option.descriptionMarkdownActionHandler; - this.selectionDetailsPane.appendChild(this.renderDescriptionMarkdown(description, actionHandler)); + const result = this._selectionDetailsDisposables.add(this.renderDescriptionMarkdown(description, actionHandler)); + this.selectionDetailsPane.appendChild(result.element); } else { this.selectionDetailsPane.textContent = description; } diff --git a/src/vs/base/browser/ui/splitview/paneview.ts b/src/vs/base/browser/ui/splitview/paneview.ts index 42d2234a131..fb2e1f406ae 100644 --- a/src/vs/base/browser/ui/splitview/paneview.ts +++ b/src/vs/base/browser/ui/splitview/paneview.ts @@ -657,6 +657,7 @@ export class PaneView extends Disposable { } private getPaneHeaderElements(): HTMLElement[] { + // eslint-disable-next-line no-restricted-syntax return [...this.element.querySelectorAll('.pane-header')] as HTMLElement[]; } diff --git a/src/vs/base/browser/ui/toggle/toggle.ts b/src/vs/base/browser/ui/toggle/toggle.ts index 34e08dba3f1..e490c9820d6 100644 --- a/src/vs/base/browser/ui/toggle/toggle.ts +++ b/src/vs/base/browser/ui/toggle/toggle.ts @@ -11,10 +11,8 @@ import { ThemeIcon } from '../../../common/themables.js'; import { $, addDisposableListener, EventType, isActiveElement } from '../../dom.js'; import { IKeyboardEvent } from '../../keyboardEvent.js'; import { BaseActionViewItem, IActionViewItemOptions } from '../actionbar/actionViewItems.js'; -import type { IManagedHover } from '../hover/hover.js'; -import { IHoverDelegate } from '../hover/hoverDelegate.js'; +import { HoverStyle, IHoverLifecycleOptions } from '../hover/hover.js'; import { getBaseLayerHoverDelegate } from '../hover/hoverDelegate2.js'; -import { getDefaultHoverDelegate } from '../hover/hoverDelegateFactory.js'; import { Widget } from '../widget.js'; import './toggle.css'; @@ -24,7 +22,7 @@ export interface IToggleOpts extends IToggleStyles { readonly title: string; readonly isChecked: boolean; readonly notFocusable?: boolean; - readonly hoverDelegate?: IHoverDelegate; + readonly hoverLifecycleOptions?: IHoverLifecycleOptions; } export interface IToggleStyles { @@ -40,7 +38,7 @@ export interface ICheckboxStyles { readonly checkboxDisabledBackground: string | undefined; readonly checkboxDisabledForeground: string | undefined; readonly size?: number; - readonly hoverDelegate?: IHoverDelegate; + readonly hoverLifecycleOptions?: IHoverLifecycleOptions; } export const unthemedToggleStyles = { @@ -66,7 +64,6 @@ export class ToggleActionViewItem extends BaseActionViewItem { inputActiveOptionBackground: options.toggleStyles?.inputActiveOptionBackground, inputActiveOptionBorder: options.toggleStyles?.inputActiveOptionBorder, inputActiveOptionForeground: options.toggleStyles?.inputActiveOptionForeground, - hoverDelegate: options.hoverDelegate })); this._register(this.toggle.onChange(() => { this._action.checked = !!this.toggle && this.toggle.checked; @@ -128,16 +125,17 @@ export class Toggle extends Widget { get onKeyDown(): Event { return this._onKeyDown.event; } private readonly _opts: IToggleOpts; + private _title: string; private _icon: ThemeIcon | undefined; readonly domNode: HTMLElement; private _checked: boolean; - private _hover: IManagedHover; constructor(opts: IToggleOpts) { super(); this._opts = opts; + this._title = this._opts.title; this._checked = this._opts.isChecked; const classes = ['monaco-custom-toggle']; @@ -153,15 +151,18 @@ export class Toggle extends Widget { } this.domNode = document.createElement('div'); - this._hover = this._register(getBaseLayerHoverDelegate().setupManagedHover(opts.hoverDelegate ?? getDefaultHoverDelegate('mouse'), this.domNode, this._opts.title)); + this._register(getBaseLayerHoverDelegate().setupDelayedHover(this.domNode, () => ({ + content: this._title, + style: HoverStyle.Pointer, + }), this._opts.hoverLifecycleOptions)); this.domNode.classList.add(...classes); if (!this._opts.notFocusable) { this.domNode.tabIndex = 0; } this.domNode.setAttribute('role', 'checkbox'); this.domNode.setAttribute('aria-checked', String(this._checked)); - this.domNode.setAttribute('aria-label', this._opts.title); + this.setTitle(this._opts.title); this.applyStyles(); this.onclick(this.domNode, (ev) => { @@ -245,7 +246,7 @@ export class Toggle extends Widget { } setTitle(newTitle: string): void { - this._hover.update(newTitle); + this._title = newTitle; this.domNode.setAttribute('aria-label', newTitle); } @@ -316,7 +317,7 @@ abstract class BaseCheckbox extends Widget { export class Checkbox extends BaseCheckbox { constructor(title: string, isChecked: boolean, styles: ICheckboxStyles) { - const toggle = new Toggle({ title, isChecked, icon: Codicon.check, actionClassName: BaseCheckbox.CLASS_NAME, hoverDelegate: styles.hoverDelegate, ...unthemedToggleStyles }); + const toggle = new Toggle({ title, isChecked, icon: Codicon.check, actionClassName: BaseCheckbox.CLASS_NAME, hoverLifecycleOptions: styles.hoverLifecycleOptions, ...unthemedToggleStyles }); super(toggle, toggle.domNode, styles); this._register(toggle); @@ -348,7 +349,7 @@ export class Checkbox extends BaseCheckbox { export class TriStateCheckbox extends BaseCheckbox { constructor( title: string, - private _state: boolean | 'partial', + private _state: boolean | 'mixed', styles: ICheckboxStyles ) { let icon: ThemeIcon | undefined; @@ -356,7 +357,7 @@ export class TriStateCheckbox extends BaseCheckbox { case true: icon = Codicon.check; break; - case 'partial': + case 'mixed': icon = Codicon.dash; break; case false: @@ -368,7 +369,7 @@ export class TriStateCheckbox extends BaseCheckbox { isChecked: _state === true, icon, actionClassName: Checkbox.CLASS_NAME, - hoverDelegate: styles.hoverDelegate, + hoverLifecycleOptions: styles.hoverLifecycleOptions, ...unthemedToggleStyles }); super( @@ -385,11 +386,11 @@ export class TriStateCheckbox extends BaseCheckbox { })); } - get checked(): boolean | 'partial' { + get checked(): boolean | 'mixed' { return this._state; } - set checked(newState: boolean | 'partial') { + set checked(newState: boolean | 'mixed') { if (this._state !== newState) { this._state = newState; this.checkbox.checked = newState === true; @@ -402,7 +403,7 @@ export class TriStateCheckbox extends BaseCheckbox { case true: this.checkbox.setIcon(Codicon.check); break; - case 'partial': + case 'mixed': this.checkbox.setIcon(Codicon.dash); break; case false: diff --git a/src/vs/base/browser/ui/toolbar/toolbar.css b/src/vs/base/browser/ui/toolbar/toolbar.css index 8182fbd9c29..4c4c684755e 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.css +++ b/src/vs/base/browser/ui/toolbar/toolbar.css @@ -11,3 +11,10 @@ display: inline-block; padding: 0; } + +.monaco-toolbar.responsive { + .monaco-action-bar > .actions-container > .action-item { + flex-shrink: 1; + min-width: 20px; + } +} diff --git a/src/vs/base/browser/ui/toolbar/toolbar.ts b/src/vs/base/browser/ui/toolbar/toolbar.ts index b493b10af6c..e2286ab838a 100644 --- a/src/vs/base/browser/ui/toolbar/toolbar.ts +++ b/src/vs/base/browser/ui/toolbar/toolbar.ts @@ -12,12 +12,14 @@ import { Codicon } from '../../../common/codicons.js'; import { ThemeIcon } from '../../../common/themables.js'; import { EventMultiplexer } from '../../../common/event.js'; import { ResolvedKeybinding } from '../../../common/keybindings.js'; -import { Disposable, DisposableStore } from '../../../common/lifecycle.js'; +import { Disposable, DisposableStore, toDisposable } from '../../../common/lifecycle.js'; import './toolbar.css'; import * as nls from '../../../../nls.js'; import { IHoverDelegate } from '../hover/hoverDelegate.js'; import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js'; +const ACTION_MIN_WIDTH = 24; /* 20px codicon + 4px left padding*/ + export interface IToolBarOptions { orientation?: ActionsOrientation; actionViewItemProvider?: IActionViewItemProvider; @@ -47,6 +49,13 @@ export interface IToolBarOptions { * Render action with label (default: `false`) */ label?: boolean; + + /** + * Controls the responsive behavior of the primary group of the toolbar. + * - `enabled`: Whether the responsive behavior is enabled. + * - `minItems`: The minimum number of items that should always be visible. + */ + responsiveBehavior?: { enabled: boolean; minItems?: number }; } /** @@ -63,9 +72,12 @@ export class ToolBar extends Disposable { private _onDidChangeDropdownVisibility = this._register(new EventMultiplexer()); get onDidChangeDropdownVisibility() { return this._onDidChangeDropdownVisibility.event; } + private originalPrimaryActions: ReadonlyArray = []; + private originalSecondaryActions: ReadonlyArray = []; + private hiddenActions: { action: IAction; size: number }[] = []; private readonly disposables = this._register(new DisposableStore()); - constructor(container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) { + constructor(private readonly container: HTMLElement, contextMenuProvider: IContextMenuProvider, options: IToolBarOptions = { orientation: ActionsOrientation.HORIZONTAL }) { super(); options.hoverDelegate = options.hoverDelegate ?? this._register(createInstantHoverDelegate()); @@ -88,7 +100,7 @@ export class ToolBar extends Disposable { if (action.id === ToggleMenuAction.ID) { this.toggleMenuActionViewItem = new DropdownMenuActionViewItem( action, - (action).menuActions, + { getActions: () => this.toggleMenuAction.menuActions }, contextMenuProvider, { actionViewItemProvider: this.options.actionViewItemProvider, @@ -142,6 +154,17 @@ export class ToolBar extends Disposable { return undefined; } })); + + // Responsive support + if (this.options.responsiveBehavior?.enabled) { + this.element.classList.add('responsive'); + + const observer = new ResizeObserver(() => { + this.updateActions(this.element.getBoundingClientRect().width); + }); + observer.observe(this.element); + this._store.add(toDisposable(() => observer.disconnect())); + } } set actionRunner(actionRunner: IActionRunner) { @@ -195,6 +218,10 @@ export class ToolBar extends Disposable { setActions(primaryActions: ReadonlyArray, secondaryActions?: ReadonlyArray): void { this.clear(); + // Store primary and secondary actions as rendered initially + this.originalPrimaryActions = primaryActions ? primaryActions.slice(0) : []; + this.originalSecondaryActions = secondaryActions ? secondaryActions.slice(0) : []; + const primaryActionsToSet = primaryActions ? primaryActions.slice(0) : []; // Inject additional action to open secondary actions if present @@ -211,6 +238,33 @@ export class ToolBar extends Disposable { primaryActionsToSet.forEach(action => { this.actionBar.push(action, { icon: this.options.icon ?? true, label: this.options.label ?? false, keybinding: this.getKeybindingLabel(action) }); }); + + if (this.options.responsiveBehavior?.enabled) { + // Reset hidden actions + this.hiddenActions.length = 0; + + // Set the minimum width + if (this.options.responsiveBehavior?.minItems !== undefined) { + let itemCount = this.options.responsiveBehavior.minItems; + + // Account for overflow menu + if ( + this.originalSecondaryActions.length > 0 || + itemCount < this.originalPrimaryActions.length + ) { + itemCount += 1; + } + + this.container.style.minWidth = `${itemCount * ACTION_MIN_WIDTH}px`; + this.element.style.minWidth = `${itemCount * ACTION_MIN_WIDTH}px`; + } else { + this.container.style.minWidth = `${ACTION_MIN_WIDTH}px`; + this.element.style.minWidth = `${ACTION_MIN_WIDTH}px`; + } + + // Update toolbar actions to fit with container width + this.updateActions(this.element.getBoundingClientRect().width); + } } isEmpty(): boolean { @@ -223,6 +277,95 @@ export class ToolBar extends Disposable { return key?.getLabel() ?? undefined; } + private updateActions(containerWidth: number) { + // Actions bar is empty + if (this.actionBar.isEmpty()) { + return; + } + + // Each action is assumed to have a minimum width so that actions with a label + // can shrink to the action's minimum width. We do this so that action visibility + // takes precedence over the action label. + const actionBarWidth = () => this.actionBar.length() * ACTION_MIN_WIDTH; + + // Action bar fits and there are no hidden actions to show + if (actionBarWidth() <= containerWidth && this.hiddenActions.length === 0) { + return; + } + + if (actionBarWidth() > containerWidth) { + // Check for max items limit + if (this.options.responsiveBehavior?.minItems !== undefined) { + const primaryActionsCount = this.actionBar.hasAction(this.toggleMenuAction) + ? this.actionBar.length() - 1 + : this.actionBar.length(); + + if (primaryActionsCount <= this.options.responsiveBehavior.minItems) { + return; + } + } + + // Hide actions from the right + while (actionBarWidth() > containerWidth && this.actionBar.length() > 0) { + const index = this.originalPrimaryActions.length - this.hiddenActions.length - 1; + if (index < 0) { + break; + } + + // Store the action and its size + const size = Math.min(ACTION_MIN_WIDTH, this.getItemWidth(index)); + const action = this.originalPrimaryActions[index]; + this.hiddenActions.unshift({ action, size }); + + // Remove the action + this.actionBar.pull(index); + + // There are no secondary actions, but we have actions that we need to hide so we + // create the overflow menu. This will ensure that another primary action will be + // removed making space for the overflow menu. + if (this.originalSecondaryActions.length === 0 && this.hiddenActions.length === 1) { + this.actionBar.push(this.toggleMenuAction, { + icon: this.options.icon ?? true, + label: this.options.label ?? false, + keybinding: this.getKeybindingLabel(this.toggleMenuAction), + }); + } + } + } else { + // Show actions from the top of the toggle menu + while (this.hiddenActions.length > 0) { + const entry = this.hiddenActions.shift()!; + if (actionBarWidth() + entry.size > containerWidth) { + // Not enough space to show the action + this.hiddenActions.unshift(entry); + break; + } + + // Add the action + this.actionBar.push(entry.action, { + icon: this.options.icon ?? true, + label: this.options.label ?? false, + keybinding: this.getKeybindingLabel(entry.action), + index: this.originalPrimaryActions.length - this.hiddenActions.length - 1 + }); + + // There are no secondary actions, and there is only one hidden item left so we + // remove the overflow menu making space for the last hidden action to be shown. + if (this.originalSecondaryActions.length === 0 && this.hiddenActions.length === 1) { + this.toggleMenuAction.menuActions = []; + this.actionBar.pull(this.actionBar.length() - 1); + } + } + } + + // Update overflow menu + const hiddenActions = this.hiddenActions.map(entry => entry.action); + if (this.originalSecondaryActions.length > 0 || hiddenActions.length > 0) { + const secondaryActions = this.originalSecondaryActions.slice(0); + this.toggleMenuAction.menuActions = Separator.join(hiddenActions, secondaryActions); + } + } + private clear(): void { this.submenuActionViewItems = []; this.disposables.clear(); diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index d00b38b2b7a..a65a645871d 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -33,11 +33,10 @@ import { clamp } from '../../../common/numbers.js'; import { ScrollEvent } from '../../../common/scrollable.js'; import './media/tree.css'; import { localize } from '../../../../nls.js'; -import { IHoverDelegate } from '../hover/hoverDelegate.js'; -import { createInstantHoverDelegate } from '../hover/hoverDelegateFactory.js'; import { autorun, constObservable } from '../../../common/observable.js'; import { alert } from '../aria/aria.js'; import { IMouseWheelEvent } from '../../mouseEvent.js'; +import { type IHoverLifecycleOptions } from '../hover/hover.js'; class TreeElementsDragAndDropData extends ElementsDragAndDropData { @@ -168,10 +167,12 @@ function asListOptions(modelProvider: () => ITreeModel | IListTouchEvent); + // eslint-disable-next-line local/code-no-dangerous-type-assertions + return options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element } as IListMouseEvent | IListTouchEvent); }, isSelectionRangeChangeEvent(e) { - return options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element }! as IListMouseEvent | IListTouchEvent); + // eslint-disable-next-line local/code-no-dangerous-type-assertions + return options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element } as IListMouseEvent | IListTouchEvent); } }, accessibilityProvider: options.accessibilityProvider && { @@ -303,11 +304,12 @@ export enum RenderIndentGuides { Always = 'always' } -interface ITreeRendererOptions { +interface ITreeRendererOptions { readonly indent?: number; readonly renderIndentGuides?: RenderIndentGuides; // TODO@joao replace this with collapsible: boolean | 'ondemand' readonly hideTwistiesOfChildlessElements?: boolean; + readonly twistieAdditionalCssClass?: (element: T) => string | undefined; } interface Collection { @@ -342,6 +344,7 @@ export class TreeRenderer implements IListR private renderedNodes = new Map, ITreeListTemplateData>(); private indent: number = TreeRenderer.DefaultIndent; private hideTwistiesOfChildlessElements: boolean = false; + private twistieAdditionalCssClass?: (element: T) => string | undefined; private shouldRenderIndentGuides: boolean = false; private activeIndentNodes = new Set>(); @@ -355,7 +358,7 @@ export class TreeRenderer implements IListR onDidChangeCollapseState: Event>, private readonly activeNodes: Collection>, private readonly renderedIndentGuides: SetMap, HTMLDivElement>, - options: ITreeRendererOptions = {} + options: ITreeRendererOptions = {} ) { this.templateId = renderer.templateId; this.updateOptions(options); @@ -364,7 +367,7 @@ export class TreeRenderer implements IListR renderer.onDidChangeTwistieState?.(this.onDidChangeTwistieState, this, this.disposables); } - updateOptions(options: ITreeRendererOptions = {}): void { + updateOptions(options: ITreeRendererOptions = {}): void { if (typeof options.indent !== 'undefined') { const indent = clamp(options.indent, 0, 40); @@ -403,6 +406,10 @@ export class TreeRenderer implements IListR if (typeof options.hideTwistiesOfChildlessElements !== 'undefined') { this.hideTwistiesOfChildlessElements = options.hideTwistiesOfChildlessElements; } + + if (typeof options.twistieAdditionalCssClass !== 'undefined') { + this.twistieAdditionalCssClass = options.twistieAdditionalCssClass; + } } renderTemplate(container: HTMLElement): ITreeListTemplateData { @@ -461,6 +468,7 @@ export class TreeRenderer implements IListR } private renderTreeElement(node: ITreeNode, templateData: ITreeListTemplateData): void { + templateData.twistie.className = templateData.twistie.classList.item(0)!; templateData.twistie.style.paddingLeft = `${templateData.indentSize}px`; templateData.indent.style.width = `${templateData.indentSize + this.indent - 16}px`; @@ -489,6 +497,14 @@ export class TreeRenderer implements IListR templateData.twistie.classList.remove('collapsible', 'collapsed'); } + // Additional twistie class + if (this.twistieAdditionalCssClass) { + const additionalClass = this.twistieAdditionalCssClass(node.element); + if (additionalClass) { + templateData.twistie.classList.add(additionalClass); + } + } + this._renderIndentGuides(node, templateData); } @@ -708,7 +724,7 @@ class TreeFindToggle extends Toggle { readonly id: string; - constructor(contribution: ITreeFindToggleContribution, opts: IToggleStyles, hoverDelegate?: IHoverDelegate) { + constructor(contribution: ITreeFindToggleContribution, opts: IToggleStyles, hoverLifecycleOptions?: IHoverLifecycleOptions) { super({ icon: contribution.icon, title: contribution.title, @@ -716,7 +732,7 @@ class TreeFindToggle extends Toggle { inputActiveOptionBorder: opts.inputActiveOptionBorder, inputActiveOptionForeground: opts.inputActiveOptionForeground, inputActiveOptionBackground: opts.inputActiveOptionBackground, - hoverDelegate, + hoverLifecycleOptions, }); this.id = contribution.id; @@ -840,8 +856,9 @@ class FindWidget extends Disposable { this.elements.root.style.boxShadow = `0 0 8px 2px ${styles.listFilterWidgetShadow}`; } - const toggleHoverDelegate = this._register(createInstantHoverDelegate()); - this.toggles = toggleContributions.map(contribution => this._register(new TreeFindToggle(contribution, styles.toggleStyles, toggleHoverDelegate))); + // const toggleHoverDelegate = this._register(createInstantHoverDelegate()); + const hoverLifecycleOptions: IHoverLifecycleOptions = { groupId: 'abstract-tree' }; + this.toggles = toggleContributions.map(contribution => this._register(new TreeFindToggle(contribution, styles.toggleStyles, hoverLifecycleOptions))); this.onDidToggleChange = Event.any(...this.toggles.map(toggle => Event.map(toggle.onChange, () => ({ id: toggle.id, isChecked: toggle.checked })))); const history = options?.history || []; @@ -852,7 +869,8 @@ class FindWidget extends Disposable { showCommonFindToggles: false, inputBoxStyles: styles.inputBoxStyles, toggleStyles: styles.toggleStyles, - history: new Set(history) + history: new Set(history), + hoverLifecycleOptions, })); this.actionbar = this._register(new ActionBar(this.elements.actionbar)); @@ -1167,7 +1185,7 @@ export class FindController extends AbstractFindController this.filter.reset())); } - updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { + updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { if (optionsUpdate.defaultFindMode !== undefined) { this.mode = optionsUpdate.defaultFindMode; } @@ -1615,7 +1633,7 @@ class StickyScrollController extends Disposable { return this._widget.focusedLast(); } - updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { + updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { if (optionsUpdate.paddingTop !== undefined) { this.paddingTop = optionsUpdate.paddingTop; } @@ -1629,7 +1647,7 @@ class StickyScrollController extends Disposable { } } - validateStickySettings(options: IAbstractTreeOptionsUpdate): { stickyScrollMaxItemCount: number } { + validateStickySettings(options: IAbstractTreeOptionsUpdate): { stickyScrollMaxItemCount: number } { let stickyScrollMaxItemCount = 7; if (typeof options.stickyScrollMaxItemCount === 'number') { stickyScrollMaxItemCount = Math.max(options.stickyScrollMaxItemCount, 1); @@ -2169,7 +2187,7 @@ function asTreeContextMenuEvent(event: IListContextMenuEv }; } -export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { +export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { readonly multipleSelectionSupport?: boolean; readonly typeNavigationEnabled?: boolean; readonly typeNavigationMode?: TypeNavigationMode; @@ -2182,13 +2200,13 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { readonly mouseWheelScrollSensitivity?: number; readonly fastScrollSensitivity?: number; readonly expandOnDoubleClick?: boolean; - readonly expandOnlyOnTwistieClick?: boolean | ((e: any) => boolean); // e is the tree element (T) + readonly expandOnlyOnTwistieClick?: boolean | ((e: T) => boolean); readonly enableStickyScroll?: boolean; readonly stickyScrollMaxItemCount?: number; readonly paddingTop?: number; } -export interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions { +export interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions { readonly contextViewProvider?: IContextViewProvider; readonly collapseByDefault?: boolean; // defaults to false readonly allowNonCollapsibleParents?: boolean; // defaults to false @@ -2691,7 +2709,7 @@ export abstract class AbstractTree implements IDisposable this.getHTMLElement().classList.toggle('always', this._options.renderIndentGuides === RenderIndentGuides.Always); } - updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { + updateOptions(optionsUpdate: IAbstractTreeOptionsUpdate = {}): void { this._options = { ...this._options, ...optionsUpdate }; for (const renderer of this.renderers) { @@ -2711,7 +2729,7 @@ export abstract class AbstractTree implements IDisposable return this._options; } - private updateStickyScroll(optionsUpdate: IAbstractTreeOptionsUpdate) { + private updateStickyScroll(optionsUpdate: IAbstractTreeOptionsUpdate) { if (!this.stickyScrollController && this._options.enableStickyScroll) { this.stickyScrollController = new StickyScrollController(this, this.model, this.view, this.renderers, this.treeDelegate, this._options); this.onDidChangeStickyScrollFocused = this.stickyScrollController.onDidChangeHasFocus; @@ -3199,7 +3217,7 @@ export abstract class AbstractTree implements IDisposable // a nice to have UI feature. const activeNodesEmitter = this.modelDisposables.add(new Emitter[]>()); const activeNodesDebounce = this.modelDisposables.add(new Delayer(0)); - this.modelDisposables.add(Event.any(onDidModelSplice, this.focus.onDidChange, this.selection.onDidChange)(() => { + this.modelDisposables.add(Event.any(onDidModelSplice, this.focus.onDidChange, this.selection.onDidChange)(() => { activeNodesDebounce.trigger(() => { const set = new Set>(); @@ -3238,12 +3256,12 @@ export abstract class AbstractTree implements IDisposable } } -interface ITreeNavigatorView, TFilterData> { +interface ITreeNavigatorView { readonly length: number; element(index: number): ITreeNode; } -class TreeNavigator, TFilterData, TRef> implements ITreeNavigator { +class TreeNavigator implements ITreeNavigator { private index: number; diff --git a/src/vs/base/browser/ui/tree/asyncDataTree.ts b/src/vs/base/browser/ui/tree/asyncDataTree.ts index ba324c8278a..6112f2bfba3 100644 --- a/src/vs/base/browser/ui/tree/asyncDataTree.ts +++ b/src/vs/base/browser/ui/tree/asyncDataTree.ts @@ -27,7 +27,7 @@ import { FuzzyScore } from '../../../common/filters.js'; import { insertInto, splice } from '../../../common/arrays.js'; import { localize } from '../../../../nls.js'; -interface IAsyncDataTreeNode { +export interface IAsyncDataTreeNode { element: TInput | T; readonly parent: IAsyncDataTreeNode | null; readonly children: IAsyncDataTreeNode[]; @@ -429,10 +429,12 @@ function asObjectTreeOptions(options?: IAsyncDataTreeOpt dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd), multipleSelectionController: options.multipleSelectionController && { isSelectionSingleChangeEvent(e) { - return options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element }! as IListMouseEvent | IListTouchEvent); + // eslint-disable-next-line local/code-no-dangerous-type-assertions + return options.multipleSelectionController!.isSelectionSingleChangeEvent({ ...e, element: e.element } as IListMouseEvent | IListTouchEvent); }, isSelectionRangeChangeEvent(e) { - return options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element }! as IListMouseEvent | IListTouchEvent); + // eslint-disable-next-line local/code-no-dangerous-type-assertions + return options.multipleSelectionController!.isSelectionRangeChangeEvent({ ...e, element: e.element } as IListMouseEvent | IListTouchEvent); } }, accessibilityProvider: options.accessibilityProvider && { @@ -476,6 +478,9 @@ function asObjectTreeOptions(options?: IAsyncDataTreeOpt ((e: IAsyncDataTreeNode) => (options.expandOnlyOnTwistieClick as ((e: T) => boolean))(e.element as T)) as ((e: unknown) => boolean) ) ), + twistieAdditionalCssClass: typeof options.twistieAdditionalCssClass === 'undefined' ? undefined : ( + ((e: IAsyncDataTreeNode) => (options.twistieAdditionalCssClass as ((e: T) => string | undefined))(e.element as T)) as ((e: unknown) => string | undefined) + ), defaultFindVisibility: (e: IAsyncDataTreeNode) => { if (e.hasChildren && e.stale) { return TreeVisibility.Visible; @@ -490,10 +495,10 @@ function asObjectTreeOptions(options?: IAsyncDataTreeOpt stickyScrollDelegate: options.stickyScrollDelegate as IStickyScrollDelegate, TFilterData> | undefined }; } -export interface IAsyncDataTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { } +export interface IAsyncDataTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { } export interface IAsyncDataTreeUpdateChildrenOptions extends IObjectTreeSetChildrenOptions { } -export interface IAsyncDataTreeOptions extends IAsyncDataTreeOptionsUpdate, Pick, Exclude, 'collapseByDefault'>> { +export interface IAsyncDataTreeOptions extends IAsyncDataTreeOptionsUpdate, Pick, Exclude, 'collapseByDefault'>> { readonly collapseByDefault?: { (e: T): boolean }; readonly identityProvider?: IIdentityProvider; readonly sorter?: ITreeSorter; @@ -562,7 +567,7 @@ export class AsyncDataTree implements IDisposable get onDidChangeModel(): Event { return this.tree.onDidChangeModel; } get onDidChangeCollapseState(): Event | null, TFilterData>> { return this.tree.onDidChangeCollapseState; } - get onDidUpdateOptions(): Event { return this.tree.onDidUpdateOptions; } + get onDidUpdateOptions(): Event>> { return this.tree.onDidUpdateOptions; } private focusNavigationFilter: ((node: ITreeNode | null, TFilterData>) => boolean) | undefined; @@ -592,7 +597,7 @@ export class AsyncDataTree implements IDisposable protected user: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private dataSource: IAsyncDataSource, options: IAsyncDataTreeOptions = {} ) { @@ -638,9 +643,9 @@ export class AsyncDataTree implements IDisposable this.findController = this.disposables.add(new AsyncFindController(this.tree, options.findProvider!, findFilter!, this.tree.options.contextViewProvider!, findOptions)); this.focusNavigationFilter = node => this.findController!.shouldFocusWhenNavigating(node); - this.onDidChangeFindOpenState = this.findController!.onDidChangeOpenState; - this.onDidChangeFindMode = this.findController!.onDidChangeMode; - this.onDidChangeFindMatchType = this.findController!.onDidChangeMatchType; + this.onDidChangeFindOpenState = this.findController.onDidChangeOpenState; + this.onDidChangeFindMode = this.findController.onDidChangeMode; + this.onDidChangeFindMatchType = this.findController.onDidChangeMatchType; } else { this.onDidChangeFindOpenState = this.tree.onDidChangeFindOpenState; this.onDidChangeFindMode = this.tree.onDidChangeFindMode; @@ -652,7 +657,7 @@ export class AsyncDataTree implements IDisposable user: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], options: IAsyncDataTreeOptions ): ObjectTree, TFilterData> { const objectTreeDelegate = new ComposedTreeDelegate>(delegate); @@ -662,7 +667,7 @@ export class AsyncDataTree implements IDisposable return new ObjectTree(user, container, objectTreeDelegate, objectTreeRenderers, objectTreeOptions); } - updateOptions(optionsUpdate: IAsyncDataTreeOptionsUpdate = {}): void { + updateOptions(optionsUpdate: IAsyncDataTreeOptionsUpdate | null> = {}): void { if (this.findController) { if (optionsUpdate.defaultFindMode !== undefined) { this.findController.mode = optionsUpdate.defaultFindMode; @@ -1179,7 +1184,7 @@ export class AsyncDataTree implements IDisposable } } - private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent | null, any>): void { + private _onDidChangeCollapseState({ node, deep }: ICollapseStateChangeEvent | null, TFilterData>): void { if (node.element === null) { return; } @@ -1487,7 +1492,7 @@ export interface ICompressibleAsyncDataTreeOptions extend readonly keyboardNavigationLabelProvider?: ICompressibleKeyboardNavigationLabelProvider; } -export interface ICompressibleAsyncDataTreeOptionsUpdate extends IAsyncDataTreeOptionsUpdate { +export interface ICompressibleAsyncDataTreeOptionsUpdate extends IAsyncDataTreeOptionsUpdate { readonly compressionEnabled?: boolean; } @@ -1502,7 +1507,7 @@ export class CompressibleAsyncDataTree extends As container: HTMLElement, virtualDelegate: IListVirtualDelegate, private compressionDelegate: ITreeCompressionDelegate, - renderers: ICompressibleTreeRenderer[], + renderers: ICompressibleTreeRenderer[], dataSource: IAsyncDataSource, options: ICompressibleAsyncDataTreeOptions = {} ) { @@ -1519,7 +1524,7 @@ export class CompressibleAsyncDataTree extends As user: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ICompressibleTreeRenderer[], + renderers: ICompressibleTreeRenderer[], options: ICompressibleAsyncDataTreeOptions ): ObjectTree, TFilterData> { const objectTreeDelegate = new ComposedTreeDelegate>(delegate); diff --git a/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts b/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts index f8057a418c0..e4adc832676 100644 --- a/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts +++ b/src/vs/base/browser/ui/tree/compressedObjectTreeModel.ts @@ -117,7 +117,7 @@ const wrapIdentityProvider = (base: IIdentityProvider): IIdentityProvider< }); // Exported only for test reasons, do not use directly -export class CompressedObjectTreeModel, TFilterData extends NonNullable = void> implements ITreeModel | null, TFilterData, T | null> { +export class CompressedObjectTreeModel implements ITreeModel | null, TFilterData, T | null> { readonly rootRef = null; @@ -351,7 +351,7 @@ export class CompressedObjectTreeModel, TFilterData e // Compressible Object Tree export type ElementMapper = (elements: T[]) => T; -export const DefaultElementMapper: ElementMapper = elements => elements[elements.length - 1]; +export const DefaultElementMapper: ElementMapper = elements => elements[elements.length - 1]; export type CompressedNodeUnwrapper = (node: ICompressedTreeNode) => T; type CompressedNodeWeakMapper = WeakMapper | null, TFilterData>, ITreeNode>; @@ -405,7 +405,7 @@ export interface ICompressibleObjectTreeModelOptions extends IOb readonly elementMapper?: ElementMapper; } -export class CompressibleObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel { +export class CompressibleObjectTreeModel implements IObjectTreeModel { readonly rootRef = null; @@ -443,7 +443,7 @@ export class CompressibleObjectTreeModel, TFilterData user: string, options: ICompressibleObjectTreeModelOptions = {} ) { - this.elementMapper = options.elementMapper || DefaultElementMapper; + this.elementMapper = options.elementMapper || (DefaultElementMapper as ElementMapper); const compressedNodeUnwrapper: CompressedNodeUnwrapper = node => this.elementMapper(node.elements); this.nodeMapper = new WeakMapper(node => new CompressedTreeNodeWrapper(compressedNodeUnwrapper, node)); @@ -478,11 +478,11 @@ export class CompressibleObjectTreeModel, TFilterData return this.model.getListRenderCount(location); } - getNode(location?: T | null | undefined): ITreeNode { + getNode(location?: T | null | undefined): ITreeNode { return this.nodeMapper.map(this.model.getNode(location)); } - getNodeLocation(node: ITreeNode): T | null { + getNodeLocation(node: ITreeNode): T | null { return node.element; } diff --git a/src/vs/base/browser/ui/tree/dataTree.ts b/src/vs/base/browser/ui/tree/dataTree.ts index 5acc18dc7a2..ff3fd98af78 100644 --- a/src/vs/base/browser/ui/tree/dataTree.ts +++ b/src/vs/base/browser/ui/tree/dataTree.ts @@ -25,7 +25,7 @@ export class DataTree extends AbstractTree, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private dataSource: IDataSource, options: IDataTreeOptions = {} ) { diff --git a/src/vs/base/browser/ui/tree/indexTree.ts b/src/vs/base/browser/ui/tree/indexTree.ts index cc43faca89e..f3e2bb30c75 100644 --- a/src/vs/base/browser/ui/tree/indexTree.ts +++ b/src/vs/base/browser/ui/tree/indexTree.ts @@ -20,7 +20,7 @@ export class IndexTree extends AbstractTree, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], private rootElement: T, options: IIndexTreeOptions = {} ) { diff --git a/src/vs/base/browser/ui/tree/indexTreeModel.ts b/src/vs/base/browser/ui/tree/indexTreeModel.ts index a7a2f738145..a9a2a8ae65b 100644 --- a/src/vs/base/browser/ui/tree/indexTreeModel.ts +++ b/src/vs/base/browser/ui/tree/indexTreeModel.ts @@ -89,7 +89,7 @@ function isCollapsibleStateUpdate(update: CollapseStateUpdate): update is Collap return 'collapsible' in update; } -export class IndexTreeModel, TFilterData = void> implements ITreeModel { +export class IndexTreeModel, TFilterData = void> implements ITreeModel { readonly rootRef = []; diff --git a/src/vs/base/browser/ui/tree/objectTree.ts b/src/vs/base/browser/ui/tree/objectTree.ts index 7b603cf35fe..d9100592a4b 100644 --- a/src/vs/base/browser/ui/tree/objectTree.ts +++ b/src/vs/base/browser/ui/tree/objectTree.ts @@ -35,7 +35,7 @@ export interface IObjectTreeSetChildrenOptions { readonly diffIdentityProvider?: IIdentityProvider; } -export class ObjectTree, TFilterData = void> extends AbstractTree { +export class ObjectTree extends AbstractTree { protected declare model: IObjectTreeModel; @@ -45,7 +45,7 @@ export class ObjectTree, TFilterData = void> extends protected readonly user: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ITreeRenderer[], + renderers: ITreeRenderer[], options: IObjectTreeOptions = {} ) { super(user, container, delegate, renderers, options as IObjectTreeOptions); @@ -100,7 +100,7 @@ interface CompressibleTemplateData { readonly data: TTemplateData; } -class CompressibleRenderer, TFilterData, TTemplateData> implements ITreeRenderer> { +class CompressibleRenderer implements ITreeRenderer> { readonly templateId: string; readonly onDidChangeTwistieState: Event | undefined; @@ -271,11 +271,11 @@ function asObjectTreeOptions(compressedTreeNodeProvider: () => I }; } -export interface ICompressibleObjectTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { +export interface ICompressibleObjectTreeOptionsUpdate extends IAbstractTreeOptionsUpdate { readonly compressionEnabled?: boolean; } -export class CompressibleObjectTree, TFilterData = void> extends ObjectTree implements ICompressedTreeNodeProvider { +export class CompressibleObjectTree extends ObjectTree implements ICompressedTreeNodeProvider { protected declare model: CompressibleObjectTreeModel; @@ -283,12 +283,12 @@ export class CompressibleObjectTree, TFilterData = vo user: string, container: HTMLElement, delegate: IListVirtualDelegate, - renderers: ICompressibleTreeRenderer[], + renderers: ICompressibleTreeRenderer[], options: ICompressibleObjectTreeOptions = {} ) { const compressedTreeNodeProvider = () => this; const stickyScrollDelegate = new CompressibleStickyScrollDelegate(() => this.model); - const compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, stickyScrollDelegate, r)); + const compressibleRenderers = renderers.map(r => new CompressibleRenderer(compressedTreeNodeProvider, stickyScrollDelegate, r)); super(user, container, delegate, compressibleRenderers, { ...asObjectTreeOptions(compressedTreeNodeProvider, options), stickyScrollDelegate }); } @@ -301,7 +301,7 @@ export class CompressibleObjectTree, TFilterData = vo return new CompressibleObjectTreeModel(user, options); } - override updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void { + override updateOptions(optionsUpdate: ICompressibleObjectTreeOptionsUpdate = {}): void { super.updateOptions(optionsUpdate); if (typeof optionsUpdate.compressionEnabled !== 'undefined') { diff --git a/src/vs/base/browser/ui/tree/objectTreeModel.ts b/src/vs/base/browser/ui/tree/objectTreeModel.ts index 57bec495e51..39bb3412e0c 100644 --- a/src/vs/base/browser/ui/tree/objectTreeModel.ts +++ b/src/vs/base/browser/ui/tree/objectTreeModel.ts @@ -11,7 +11,7 @@ import { Iterable } from '../../../common/iterator.js'; export type ITreeNodeCallback = (node: ITreeNode) => void; -export interface IObjectTreeModel, TFilterData extends NonNullable = void> extends ITreeModel { +export interface IObjectTreeModel extends ITreeModel { setChildren(element: T | null, children: Iterable> | undefined, options?: IObjectTreeModelSetChildrenOptions): void; resort(element?: T | null, recursive?: boolean): void; } @@ -24,7 +24,7 @@ export interface IObjectTreeModelOptions extends IIndexTreeModel readonly identityProvider?: IIdentityProvider; } -export class ObjectTreeModel, TFilterData extends NonNullable = void> implements IObjectTreeModel { +export class ObjectTreeModel implements IObjectTreeModel { readonly rootRef = null; diff --git a/src/vs/base/browser/ui/tree/tree.ts b/src/vs/base/browser/ui/tree/tree.ts index a3474b3dfa3..fe579cfa9f8 100644 --- a/src/vs/base/browser/ui/tree/tree.ts +++ b/src/vs/base/browser/ui/tree/tree.ts @@ -142,8 +142,8 @@ export interface ITreeModel { getListIndex(location: TRef): number; getListRenderCount(location: TRef): number; - getNode(location?: TRef): ITreeNode; - getNodeLocation(node: ITreeNode): TRef; + getNode(location?: TRef): ITreeNode; + getNodeLocation(node: ITreeNode): TRef; getParentNodeLocation(location: TRef): TRef | undefined; getFirstElementChild(location: TRef): T | undefined; diff --git a/src/vs/base/common/actions.ts b/src/vs/base/common/actions.ts index 0970509e98c..9660e763095 100644 --- a/src/vs/base/common/actions.ts +++ b/src/vs/base/common/actions.ts @@ -52,6 +52,11 @@ export interface IActionChangeEvent { readonly checked?: boolean; } +/** + * A concrete implementation of {@link IAction}. + * + * Note that in most cases you should use the lighter-weight {@linkcode toAction} function instead. + */ export class Action extends Disposable implements IAction { protected _onDidChange = this._register(new Emitter()); diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 2f16dbccda4..a7b52b435bd 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -109,7 +109,16 @@ export function binarySearch2(length: number, compareToKey: (index: number) => n type Compare = (a: T, b: T) => number; - +/** + * Finds the nth smallest element in the array using quickselect algorithm. + * The data does not need to be sorted. + * + * @param nth The zero-based index of the element to find (0 = smallest, 1 = second smallest, etc.) + * @param data The unsorted array + * @param compare A comparator function that defines the sort order + * @returns The nth smallest element + * @throws TypeError if nth is >= data.length + */ export function quickSelect(nth: number, data: T[], compare: Compare): T { nth = nth | 0; @@ -193,8 +202,8 @@ export function forEachWithNeighbors(arr: T[], f: (before: T | undefined, ele } } -export function concatArrays(...arrays: TArr): TArr[number][number][] { - return ([] as any[]).concat(...arrays); +export function concatArrays(...arrays: T): T[number][number][] { + return [].concat(...arrays); } interface IMutableSplice extends ISplice { @@ -393,7 +402,7 @@ export function distinct(array: ReadonlyArray, keyFn: (value: T) => unknow const seen = new Set(); return array.filter(element => { - const key = keyFn!(element); + const key = keyFn(element); if (seen.has(key)) { return false; } @@ -563,6 +572,22 @@ export function mapArrayOrNot(items: T | T[], fn: (_: T) => U): U | U[] { fn(items); } +export function mapFilter(array: ReadonlyArray, fn: (t: T) => U | undefined): U[] { + const result: U[] = []; + for (const item of array) { + const mapped = fn(item); + if (mapped !== undefined) { + result.push(mapped); + } + } + return result; +} + +export function withoutDuplicates(array: ReadonlyArray): T[] { + const s = new Set(array); + return Array.from(s); +} + export function asArray(x: T | T[]): T[]; export function asArray(x: T | readonly T[]): readonly T[]; export function asArray(x: T | T[]): T[] { diff --git a/src/vs/base/common/arraysFind.ts b/src/vs/base/common/arraysFind.ts index ea75386c4a9..8ed34987f63 100644 --- a/src/vs/base/common/arraysFind.ts +++ b/src/vs/base/common/arraysFind.ts @@ -5,9 +5,9 @@ import { Comparator } from './arrays.js'; -export function findLast(array: readonly T[], predicate: (item: T) => item is R, fromIndex?: number): R | undefined; -export function findLast(array: readonly T[], predicate: (item: T) => unknown, fromIndex?: number): T | undefined; -export function findLast(array: readonly T[], predicate: (item: T) => unknown, fromIndex = array.length - 1): T | undefined { +export function findLast(array: readonly T[], predicate: (item: T, index: number) => item is R, fromIndex?: number): R | undefined; +export function findLast(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex?: number): T | undefined; +export function findLast(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = array.length - 1): T | undefined { const idx = findLastIdx(array, predicate, fromIndex); if (idx === -1) { return undefined; @@ -15,11 +15,33 @@ export function findLast(array: readonly T[], predicate: (item: T) => unknown return array[idx]; } -export function findLastIdx(array: readonly T[], predicate: (item: T) => unknown, fromIndex = array.length - 1): number { +export function findLastIdx(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = array.length - 1): number { for (let i = fromIndex; i >= 0; i--) { const element = array[i]; - if (predicate(element)) { + if (predicate(element, i)) { + return i; + } + } + + return -1; +} + +export function findFirst(array: readonly T[], predicate: (item: T, index: number) => item is R, fromIndex?: number): R | undefined; +export function findFirst(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex?: number): T | undefined; +export function findFirst(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = 0): T | undefined { + const idx = findFirstIdx(array, predicate, fromIndex); + if (idx === -1) { + return undefined; + } + return array[idx]; +} + +export function findFirstIdx(array: readonly T[], predicate: (item: T, index: number) => unknown, fromIndex = 0): number { + for (let i = fromIndex; i < array.length; i++) { + const element = array[i]; + + if (predicate(element, i)) { return i; } } diff --git a/src/vs/base/common/assert.ts b/src/vs/base/common/assert.ts index 860c3e816d5..b8f47aefd66 100644 --- a/src/vs/base/common/assert.ts +++ b/src/vs/base/common/assert.ts @@ -29,6 +29,10 @@ export function assertNever(value: never, message = 'Unreachable'): never { throw new Error(message); } +export function softAssertNever(value: never): void { + // no-op +} + /** * Asserts that a condition is `truthy`. * diff --git a/src/vs/base/common/async.ts b/src/vs/base/common/async.ts index 5e4cd533c9a..3dcfa0c5130 100644 --- a/src/vs/base/common/async.ts +++ b/src/vs/base/common/async.ts @@ -191,6 +191,10 @@ export interface ITask { (): T; } +export interface ICancellableTask { + (token: CancellationToken): T; +} + /** * A helper to prevent accumulation of sequential async tasks. * @@ -221,18 +225,19 @@ export class Throttler implements IDisposable { private activePromise: Promise | null; private queuedPromise: Promise | null; - private queuedPromiseFactory: ITask> | null; - - private isDisposed = false; + private queuedPromiseFactory: ICancellableTask> | null; + private cancellationTokenSource: CancellationTokenSource; constructor() { this.activePromise = null; this.queuedPromise = null; this.queuedPromiseFactory = null; + + this.cancellationTokenSource = new CancellationTokenSource(); } - queue(promiseFactory: ITask>): Promise { - if (this.isDisposed) { + queue(promiseFactory: ICancellableTask>): Promise { + if (this.cancellationTokenSource.token.isCancellationRequested) { return Promise.reject(new Error('Throttler is disposed')); } @@ -243,7 +248,7 @@ export class Throttler implements IDisposable { const onComplete = () => { this.queuedPromise = null; - if (this.isDisposed) { + if (this.cancellationTokenSource.token.isCancellationRequested) { return; } @@ -263,7 +268,7 @@ export class Throttler implements IDisposable { }); } - this.activePromise = promiseFactory(); + this.activePromise = promiseFactory(this.cancellationTokenSource.token); return new Promise((resolve, reject) => { this.activePromise!.then((result: T) => { @@ -277,7 +282,7 @@ export class Throttler implements IDisposable { } dispose(): void { - this.isDisposed = true; + this.cancellationTokenSource.cancel(); } } @@ -308,6 +313,10 @@ export class SequencerByKey { return newPromise; } + peek(key: TKey): Promise | undefined { + return this.promiseMap.get(key) || undefined; + } + keys(): IterableIterator { return this.promiseMap.keys(); } @@ -458,7 +467,7 @@ export class ThrottledDelayer { this.throttler = new Throttler(); } - trigger(promiseFactory: ITask>, delay?: number): Promise { + trigger(promiseFactory: ICancellableTask>, delay?: number): Promise { return this.delayer.trigger(() => this.throttler.queue(promiseFactory), delay) as unknown as Promise; } @@ -919,6 +928,12 @@ export class ResourceQueue implements IDisposable { export type Task = () => (Promise | T); +/** + * Wrap a type in an optional promise. This can be useful to avoid the runtime + * overhead of creating a promise. + */ +export type MaybePromise = Promise | T; + /** * Processes tasks in the order they were scheduled. */ @@ -1642,8 +1657,8 @@ export class TaskSequentializer { this._queued = { run, promise, - promiseResolve: promiseResolve!, - promiseReject: promiseReject! + promiseResolve, + promiseReject }; } @@ -2415,6 +2430,42 @@ export class AsyncIterableProducer implements AsyncIterable { }); } + public static tee(iterable: AsyncIterable): [AsyncIterableProducer, AsyncIterableProducer] { + let emitter1: AsyncIterableEmitter | undefined; + let emitter2: AsyncIterableEmitter | undefined; + + const defer = new DeferredPromise(); + + const start = async () => { + if (!emitter1 || !emitter2) { + return; // not yet ready + } + try { + for await (const item of iterable) { + emitter1.emitOne(item); + emitter2.emitOne(item); + } + } catch (err) { + emitter1.reject(err); + emitter2.reject(err); + } finally { + defer.complete(); + } + }; + + const p1 = new AsyncIterableProducer(async (emitter) => { + emitter1 = emitter; + start(); + return defer.p; + }); + const p2 = new AsyncIterableProducer(async (emitter) => { + emitter2 = emitter; + start(); + return defer.p; + }); + return [p1, p2]; + } + public map(mapFn: (item: T) => R): AsyncIterableProducer { return AsyncIterableProducer.map(this, mapFn); } diff --git a/src/vs/base/common/buffer.ts b/src/vs/base/common/buffer.ts index 5de29e7d74f..244fb8e1c0d 100644 --- a/src/vs/base/common/buffer.ts +++ b/src/vs/base/common/buffer.ts @@ -127,7 +127,7 @@ export class VSBuffer { return this.buffer.toString(); } else { if (!textDecoder) { - textDecoder = new TextDecoder(); + textDecoder = new TextDecoder(undefined, { ignoreBOM: true }); } return textDecoder.decode(this.buffer); } diff --git a/src/vs/base/common/cancellation.ts b/src/vs/base/common/cancellation.ts index 3be4a90a103..e04c9277b85 100644 --- a/src/vs/base/common/cancellation.ts +++ b/src/vs/base/common/cancellation.ts @@ -21,10 +21,10 @@ export interface CancellationToken { * * @event */ - readonly onCancellationRequested: (listener: (e: any) => any, thisArgs?: any, disposables?: IDisposable[]) => IDisposable; + readonly onCancellationRequested: (listener: (e: void) => unknown, thisArgs?: unknown, disposables?: IDisposable[]) => IDisposable; } -const shortcutEvent: Event = Object.freeze(function (callback, context?): IDisposable { +const shortcutEvent: Event = Object.freeze(function (callback, context?): IDisposable { const handle = setTimeout(callback.bind(context), 0); return { dispose() { clearTimeout(handle); } }; }); @@ -60,7 +60,7 @@ export namespace CancellationToken { class MutableToken implements CancellationToken { private _isCancelled: boolean = false; - private _emitter: Emitter | null = null; + private _emitter: Emitter | null = null; public cancel() { if (!this._isCancelled) { @@ -76,12 +76,12 @@ class MutableToken implements CancellationToken { return this._isCancelled; } - get onCancellationRequested(): Event { + get onCancellationRequested(): Event { if (this._isCancelled) { return shortcutEvent; } if (!this._emitter) { - this._emitter = new Emitter(); + this._emitter = new Emitter(); } return this._emitter.event; } diff --git a/src/vs/base/common/codiconsLibrary.ts b/src/vs/base/common/codiconsLibrary.ts index 48292758fa6..233ea2a4dfd 100644 --- a/src/vs/base/common/codiconsLibrary.ts +++ b/src/vs/base/common/codiconsLibrary.ts @@ -31,9 +31,6 @@ export const codiconsLibrary = { personFollow: register('person-follow', 0xea67), personOutline: register('person-outline', 0xea67), personFilled: register('person-filled', 0xea67), - gitBranch: register('git-branch', 0xea68), - gitBranchCreate: register('git-branch-create', 0xea68), - gitBranchDelete: register('git-branch-delete', 0xea68), sourceControl: register('source-control', 0xea68), mirror: register('mirror', 0xea69), mirrorPublic: register('mirror-public', 0xea69), @@ -624,4 +621,22 @@ export const codiconsLibrary = { quotes: register('quotes', 0xec60), rename: register('rename', 0xec61), runWithDeps: register('run-with-deps', 0xec62), + debugConnected: register('debug-connected', 0xec63), + strikethrough: register('strikethrough', 0xec64), + openInProduct: register('open-in-product', 0xec65), + indexZero: register('index-zero', 0xec66), + agent: register('agent', 0xec67), + editCode: register('edit-code', 0xec68), + repoSelected: register('repo-selected', 0xec69), + skip: register('skip', 0xec6a), + mergeInto: register('merge-into', 0xec6b), + gitBranchChanges: register('git-branch-changes', 0xec6c), + gitBranchStagedChanges: register('git-branch-staged-changes', 0xec6d), + gitBranchConflicts: register('git-branch-conflicts', 0xec6e), + gitBranch: register('git-branch', 0xec6f), + gitBranchCreate: register('git-branch-create', 0xec6f), + gitBranchDelete: register('git-branch-delete', 0xec6f), + searchLarge: register('search-large', 0xec70), + terminalGitBash: register('terminal-git-bash', 0xec71), + windowActive: register('window-active', 0xec72), } as const; diff --git a/src/vs/base/common/collections.ts b/src/vs/base/common/collections.ts index 81a8bfae1cb..f64ad848bf4 100644 --- a/src/vs/base/common/collections.ts +++ b/src/vs/base/common/collections.ts @@ -19,8 +19,8 @@ export type INumberDictionary = Record; * Groups the collection into a dictionary based on the provided * group function. */ -export function groupBy(data: V[], groupFn: (element: V) => K): Record { - const result: Record = Object.create(null); +export function groupBy(data: readonly V[], groupFn: (element: V) => K): Partial> { + const result: Partial> = Object.create(null); for (const element of data) { const key = groupFn(element); let target = result[key]; @@ -96,7 +96,7 @@ export function intersection(setA: Set, setB: Iterable): Set { } export class SetWithKey implements Set { - private _map = new Map(); + private _map = new Map(); constructor(values: T[], private toKey: (t: T) => unknown) { for (const value of values) { @@ -142,7 +142,7 @@ export class SetWithKey implements Set { this._map.clear(); } - forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void { + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: unknown): void { this._map.forEach(entry => callbackfn.call(thisArg, entry, entry, this)); } diff --git a/src/vs/base/common/controlFlow.ts b/src/vs/base/common/controlFlow.ts index 35f860a222d..8fc6b19d3b1 100644 --- a/src/vs/base/common/controlFlow.ts +++ b/src/vs/base/common/controlFlow.ts @@ -53,9 +53,8 @@ export class ReentrancyBarrier { return this._isOccupied; } - public makeExclusiveOrSkip(fn: TFunction): TFunction { - // eslint-disable-next-line local/code-no-any-casts - return ((...args: any[]) => { + public makeExclusiveOrSkip(fn: (...args: TArgs) => void): (...args: TArgs) => void { + return ((...args: TArgs) => { if (this._isOccupied) { return; } @@ -65,6 +64,6 @@ export class ReentrancyBarrier { } finally { this._isOccupied = false; } - }) as any; + }); } } diff --git a/src/vs/base/common/decorators/cancelPreviousCalls.ts b/src/vs/base/common/decorators/cancelPreviousCalls.ts index 7e901a24ca4..50a4ca8d819 100644 --- a/src/vs/base/common/decorators/cancelPreviousCalls.ts +++ b/src/vs/base/common/decorators/cancelPreviousCalls.ts @@ -87,7 +87,7 @@ type TWithOptionalCancellationToken = TFunction exte export function cancelPreviousCalls< TObject extends Disposable, TArgs extends unknown[], - TReturn extends unknown, + TReturn, >( _proto: TObject, methodName: string, diff --git a/src/vs/base/common/equals.ts b/src/vs/base/common/equals.ts index df2db9256f1..88f9d2c36c6 100644 --- a/src/vs/base/common/equals.ts +++ b/src/vs/base/common/equals.ts @@ -10,7 +10,7 @@ export type EqualityComparer = (a: T, b: T) => boolean; /** * Compares two items for equality using strict equality. */ -export const strictEquals: EqualityComparer = (a, b) => a === b; +export const strictEquals = (a: T, b: T): boolean => a === b; /** * Checks if the items of two arrays are equal. diff --git a/src/vs/base/common/event.ts b/src/vs/base/common/event.ts index 5a33d03fcf1..ad51d8ff70a 100644 --- a/src/vs/base/common/event.ts +++ b/src/vs/base/common/event.ts @@ -601,13 +601,22 @@ export namespace Event { */ export function toPromise(event: Event, disposables?: IDisposable[] | DisposableStore): CancelablePromise { let cancelRef: () => void; - const promise = new Promise((resolve, reject) => { - const listener = once(event)(resolve, null, disposables); + let listener: IDisposable; + const promise = new Promise((resolve) => { + listener = once(event)(resolve); + addToDisposables(listener, disposables); + // not resolved, matching the behavior of a normal disposal - cancelRef = () => listener.dispose(); + cancelRef = () => { + disposeAndRemove(listener, disposables); + }; }) as CancelablePromise; promise.cancel = cancelRef!; + if (disposables) { + promise.finally(() => disposeAndRemove(listener, disposables)); + } + return promise; } @@ -746,11 +755,7 @@ export namespace Event { } }; - if (disposables instanceof DisposableStore) { - disposables.add(disposable); - } else if (Array.isArray(disposables)) { - disposables.push(disposable); - } + addToDisposables(disposable, disposables); return disposable; }; @@ -886,7 +891,7 @@ class LeakageMonitor { const [topStack, topCount] = this.getMostFrequentStack()!; const message = `[${this.name}] potential listener LEAK detected, having ${listenerCount} listeners already. MOST frequent listener (${topCount}):`; console.warn(message); - console.warn(topStack!); + console.warn(topStack); const error = new ListenerLeakError(message, topStack); this._errorHandler(error); @@ -1129,11 +1134,7 @@ export class Emitter { removeMonitor?.(); this._removeListener(contained); }); - if (disposables instanceof DisposableStore) { - disposables.add(result); - } else if (Array.isArray(disposables)) { - disposables.push(result); - } + addToDisposables(result, disposables); return result; }; @@ -1778,3 +1779,24 @@ export function trackSetChanges(getData: () => ReadonlySet, onDidChangeDat store.add(map); return store; } + + +function addToDisposables(result: IDisposable, disposables: DisposableStore | IDisposable[] | undefined) { + if (disposables instanceof DisposableStore) { + disposables.add(result); + } else if (Array.isArray(disposables)) { + disposables.push(result); + } +} + +function disposeAndRemove(result: IDisposable, disposables: DisposableStore | IDisposable[] | undefined) { + if (disposables instanceof DisposableStore) { + disposables.delete(result); + } else if (Array.isArray(disposables)) { + const index = disposables.indexOf(result); + if (index !== -1) { + disposables.splice(index, 1); + } + } + result.dispose(); +} diff --git a/src/vs/base/common/filters.ts b/src/vs/base/common/filters.ts index aa0b036ac76..fd159b40ab4 100644 --- a/src/vs/base/common/filters.ts +++ b/src/vs/base/common/filters.ts @@ -6,6 +6,7 @@ import { CharCode } from './charCode.js'; import { LRUCache } from './map.js'; import { getKoreanAltChars } from './naturalLanguage/korean.js'; +import { tryNormalizeToBase } from './normalization.js'; import * as strings from './strings.js'; export interface IFilter { @@ -65,6 +66,10 @@ function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: s // Contiguous Substring export function matchesContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { + if (word.length > wordToMatchAgainst.length) { + return null; + } + const index = wordToMatchAgainst.toLowerCase().indexOf(word.toLowerCase()); if (index === -1) { return null; @@ -73,9 +78,28 @@ export function matchesContiguousSubString(word: string, wordToMatchAgainst: str return [{ start: index, end: index + word.length }]; } +export function matchesBaseContiguousSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { + if (word.length > wordToMatchAgainst.length) { + return null; + } + + word = tryNormalizeToBase(word); + wordToMatchAgainst = tryNormalizeToBase(wordToMatchAgainst); + const index = wordToMatchAgainst.indexOf(word); + if (index === -1) { + return null; + } + + return [{ start: index, end: index + word.length }]; +} + // Substring export function matchesSubString(word: string, wordToMatchAgainst: string): IMatch[] | null { + if (word.length > wordToMatchAgainst.length) { + return null; + } + return _matchesSubString(word.toLowerCase(), wordToMatchAgainst.toLowerCase(), 0, 0); } @@ -121,7 +145,7 @@ function isWhitespace(code: number): boolean { } const wordSeparators = new Set(); -// These are chosen as natural word separators based on writen text. +// These are chosen as natural word separators based on written text. // It is a subset of the word separators used by the monaco editor. '()[]{}<>`\'"-/;:,.?!' .split('') @@ -319,8 +343,8 @@ export function matchesWords(word: string, target: string, contiguous: boolean = let result: IMatch[] | null = null; let targetIndex = 0; - word = word.toLowerCase(); - target = target.toLowerCase(); + word = tryNormalizeToBase(word); + target = tryNormalizeToBase(target); while (targetIndex < target.length) { result = _matchesWords(word, target, 0, targetIndex, contiguous); if (result !== null) { diff --git a/src/vs/base/common/fuzzyScorer.ts b/src/vs/base/common/fuzzyScorer.ts index 6d07f13b2d5..d11929f7aae 100644 --- a/src/vs/base/common/fuzzyScorer.ts +++ b/src/vs/base/common/fuzzyScorer.ts @@ -683,25 +683,25 @@ export function compareItemsByFuzzyScore(itemA: T, itemB: T, query: IPrepared } function computeLabelAndDescriptionMatchDistance(item: T, score: IItemScore, accessor: IItemAccessor): number { - let matchStart: number = -1; - let matchEnd: number = -1; + let matchStart = -1; + let matchEnd = -1; // If we have description matches, the start is first of description match - if (score.descriptionMatch && score.descriptionMatch.length) { + if (score.descriptionMatch?.length) { matchStart = score.descriptionMatch[0].start; } // Otherwise, the start is the first label match - else if (score.labelMatch && score.labelMatch.length) { + else if (score.labelMatch?.length) { matchStart = score.labelMatch[0].start; } // If we have label match, the end is the last label match // If we had a description match, we add the length of the description // as offset to the end to indicate this. - if (score.labelMatch && score.labelMatch.length) { + if (score.labelMatch?.length) { matchEnd = score.labelMatch[score.labelMatch.length - 1].end; - if (score.descriptionMatch && score.descriptionMatch.length) { + if (score.descriptionMatch?.length) { const itemDescription = accessor.getItemDescription(item); if (itemDescription) { matchEnd += itemDescription.length; @@ -710,7 +710,7 @@ function computeLabelAndDescriptionMatchDistance(item: T, score: IItemScore, } // If we have just a description match, the end is the last description match - else if (score.descriptionMatch && score.descriptionMatch.length) { + else if (score.descriptionMatch?.length) { matchEnd = score.descriptionMatch[score.descriptionMatch.length - 1].end; } @@ -718,15 +718,15 @@ function computeLabelAndDescriptionMatchDistance(item: T, score: IItemScore, } function compareByMatchLength(matchesA?: IMatch[], matchesB?: IMatch[]): number { - if ((!matchesA && !matchesB) || ((!matchesA || !matchesA.length) && (!matchesB || !matchesB.length))) { + if ((!matchesA && !matchesB) || ((!matchesA?.length) && (!matchesB?.length))) { return 0; // make sure to not cause bad comparing when matches are not provided } - if (!matchesB || !matchesB.length) { + if (!matchesB?.length) { return -1; } - if (!matchesA || !matchesA.length) { + if (!matchesA?.length) { return 1; } diff --git a/src/vs/base/common/glob.ts b/src/vs/base/common/glob.ts index 9914ab91e43..6c2b7680f8b 100644 --- a/src/vs/base/common/glob.ts +++ b/src/vs/base/common/glob.ts @@ -10,7 +10,7 @@ import { isEqualOrParent } from './extpath.js'; import { LRUCache } from './map.js'; import { basename, extname, posix, sep } from './path.js'; import { isLinux } from './platform.js'; -import { escapeRegExpCharacters, ltrim } from './strings.js'; +import { endsWithIgnoreCase, equalsIgnoreCase, escapeRegExpCharacters, ltrim } from './strings.js'; export interface IRelativePattern { @@ -270,7 +270,7 @@ export type ParsedPattern = (path: string, basename?: string) => boolean; // iff `hasSibling` returns a `Promise`. export type ParsedExpression = (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise) => string | null | Promise /* the matching pattern */; -interface IGlobOptions { +export interface IGlobOptions { /** * Simplify patterns for use as exclusion filters during @@ -278,6 +278,17 @@ interface IGlobOptions { * outside of a tree traversal. */ trimForExclusions?: boolean; + + /** + * Whether glob pattern matching should be case insensitive. + */ + ignoreCase?: boolean; +} + +interface IGlobOptionsInternal extends IGlobOptions { + equals: (a: string, b: string) => boolean; + endsWith: (str: string, candidate: string) => boolean; + isEqualOrParent: (base: string, candidate: string) => boolean; } interface ParsedStringPattern { @@ -339,45 +350,55 @@ function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): P // Whitespace trimming pattern = pattern.trim(); + const ignoreCase = options.ignoreCase ?? false; + const internalOptions = { + ...options, + equals: ignoreCase ? equalsIgnoreCase : (a: string, b: string) => a === b, + endsWith: ignoreCase ? endsWithIgnoreCase : (str: string, candidate: string) => str.endsWith(candidate), + // TODO: the '!isLinux' part below is to keep current behavior unchanged, but it should probably be removed + // in favor of passing correct options from the caller. + isEqualOrParent: (base: string, candidate: string) => isEqualOrParent(base, candidate, !isLinux || ignoreCase) + }; + // Check cache - const patternKey = `${pattern}_${!!options.trimForExclusions}`; + const patternKey = `${ignoreCase ? pattern.toLowerCase() : pattern}_${!!options.trimForExclusions}_${ignoreCase}`; let parsedPattern = CACHE.get(patternKey); if (parsedPattern) { - return wrapRelativePattern(parsedPattern, arg1); + return wrapRelativePattern(parsedPattern, arg1, internalOptions); } // Check for Trivials let match: RegExpExecArray | null; if (T1.test(pattern)) { - parsedPattern = trivia1(pattern.substr(4), pattern); // common pattern: **/*.txt just need endsWith check - } else if (match = T2.exec(trimForExclusions(pattern, options))) { // common pattern: **/some.txt just need basename check - parsedPattern = trivia2(match[1], pattern); + parsedPattern = trivia1(pattern.substring(4), pattern, internalOptions); // common pattern: **/*.txt just need endsWith check + } else if (match = T2.exec(trimForExclusions(pattern, internalOptions))) { // common pattern: **/some.txt just need basename check + parsedPattern = trivia2(match[1], pattern, internalOptions); } else if ((options.trimForExclusions ? T3_2 : T3).test(pattern)) { // repetition of common patterns (see above) {**/*.txt,**/*.png} - parsedPattern = trivia3(pattern, options); - } else if (match = T4.exec(trimForExclusions(pattern, options))) { // common pattern: **/something/else just need endsWith check - parsedPattern = trivia4and5(match[1].substr(1), pattern, true); - } else if (match = T5.exec(trimForExclusions(pattern, options))) { // common pattern: something/else just need equals check - parsedPattern = trivia4and5(match[1], pattern, false); + parsedPattern = trivia3(pattern, internalOptions); + } else if (match = T4.exec(trimForExclusions(pattern, internalOptions))) { // common pattern: **/something/else just need endsWith check + parsedPattern = trivia4and5(match[1].substring(1), pattern, true, internalOptions); + } else if (match = T5.exec(trimForExclusions(pattern, internalOptions))) { // common pattern: something/else just need equals check + parsedPattern = trivia4and5(match[1], pattern, false, internalOptions); } // Otherwise convert to pattern else { - parsedPattern = toRegExp(pattern); + parsedPattern = toRegExp(pattern, internalOptions); } // Cache CACHE.set(patternKey, parsedPattern); - return wrapRelativePattern(parsedPattern, arg1); + return wrapRelativePattern(parsedPattern, arg1, internalOptions); } -function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | IRelativePattern): ParsedStringPattern { +function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | IRelativePattern, options: IGlobOptionsInternal): ParsedStringPattern { if (typeof arg2 === 'string') { return parsedPattern; } const wrappedPattern: ParsedStringPattern = function (path, basename) { - if (!isEqualOrParent(path, arg2.base, !isLinux)) { + if (!options.isEqualOrParent(path, arg2.base)) { // skip glob matching if `base` is not a parent of `path` return null; } @@ -390,7 +411,7 @@ function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | // for the fact that `base` might end in a path separator // (https://github.com/microsoft/vscode/issues/162498) - return parsedPattern(ltrim(path.substr(arg2.base.length), sep), basename); + return parsedPattern(ltrim(path.substring(arg2.base.length), sep), basename); }; // Make sure to preserve associated metadata @@ -403,18 +424,18 @@ function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | } function trimForExclusions(pattern: string, options: IGlobOptions): string { - return options.trimForExclusions && pattern.endsWith('/**') ? pattern.substr(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later + return options.trimForExclusions && pattern.endsWith('/**') ? pattern.substring(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later } // common pattern: **/*.txt just need endsWith check -function trivia1(base: string, pattern: string): ParsedStringPattern { +function trivia1(base: string, pattern: string, options: IGlobOptionsInternal): ParsedStringPattern { return function (path: string, basename?: string) { - return typeof path === 'string' && path.endsWith(base) ? pattern : null; + return typeof path === 'string' && options.endsWith(path, base) ? pattern : null; }; } // common pattern: **/some.txt just need basename check -function trivia2(base: string, pattern: string): ParsedStringPattern { +function trivia2(base: string, pattern: string, options: IGlobOptionsInternal): ParsedStringPattern { const slashBase = `/${base}`; const backslashBase = `\\${base}`; @@ -424,10 +445,10 @@ function trivia2(base: string, pattern: string): ParsedStringPattern { } if (basename) { - return basename === base ? pattern : null; + return options.equals(basename, base) ? pattern : null; } - return path === base || path.endsWith(slashBase) || path.endsWith(backslashBase) ? pattern : null; + return options.equals(path, base) || options.endsWith(path, slashBase) || options.endsWith(path, backslashBase) ? pattern : null; }; const basenames = [base]; @@ -439,7 +460,7 @@ function trivia2(base: string, pattern: string): ParsedStringPattern { } // repetition of common patterns (see above) {**/*.txt,**/*.png} -function trivia3(pattern: string, options: IGlobOptions): ParsedStringPattern { +function trivia3(pattern: string, options: IGlobOptionsInternal): ParsedStringPattern { const parsedPatterns = aggregateBasenameMatches(pattern.slice(1, -1) .split(',') .map(pattern => parsePattern(pattern, options)) @@ -478,7 +499,7 @@ function trivia3(pattern: string, options: IGlobOptions): ParsedStringPattern { } // common patterns: **/something/else just need endsWith check, something/else just needs and equals check -function trivia4and5(targetPath: string, pattern: string, matchPathEnds: boolean): ParsedStringPattern { +function trivia4and5(targetPath: string, pattern: string, matchPathEnds: boolean, options: IGlobOptionsInternal): ParsedStringPattern { const usingPosixSep = sep === posix.sep; const nativePath = usingPosixSep ? targetPath : targetPath.replace(ALL_FORWARD_SLASHES, sep); const nativePathEnd = sep + nativePath; @@ -487,11 +508,14 @@ function trivia4and5(targetPath: string, pattern: string, matchPathEnds: boolean let parsedPattern: ParsedStringPattern; if (matchPathEnds) { parsedPattern = function (path: string, basename?: string) { - return typeof path === 'string' && ((path === nativePath || path.endsWith(nativePathEnd)) || !usingPosixSep && (path === targetPath || path.endsWith(targetPathEnd))) ? pattern : null; + return typeof path === 'string' && ( + (options.equals(path, nativePath) || options.endsWith(path, nativePathEnd)) || + !usingPosixSep && (options.equals(path, targetPath) || options.endsWith(path, targetPathEnd)) + ) ? pattern : null; }; } else { parsedPattern = function (path: string, basename?: string) { - return typeof path === 'string' && (path === nativePath || (!usingPosixSep && path === targetPath)) ? pattern : null; + return typeof path === 'string' && (options.equals(path, nativePath) || (!usingPosixSep && options.equals(path, targetPath))) ? pattern : null; }; } @@ -500,9 +524,9 @@ function trivia4and5(targetPath: string, pattern: string, matchPathEnds: boolean return parsedPattern; } -function toRegExp(pattern: string): ParsedStringPattern { +function toRegExp(pattern: string, options: IGlobOptions): ParsedStringPattern { try { - const regExp = new RegExp(`^${parseRegExp(pattern)}$`); + const regExp = new RegExp(`^${parseRegExp(pattern)}$`, options.ignoreCase ? 'i' : undefined); return function (path: string) { regExp.lastIndex = 0; // reset RegExp to its initial state to reuse it! @@ -522,14 +546,14 @@ function toRegExp(pattern: string): ParsedStringPattern { * * `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) * * `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`) */ -export function match(pattern: string | IRelativePattern, path: string): boolean; -export function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string /* the matching pattern */; -export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): boolean | string | null | Promise { +export function match(pattern: string | IRelativePattern, path: string, options?: IGlobOptions): boolean; +export function match(expression: IExpression, path: string, options?: IGlobOptions): boolean; +export function match(arg1: string | IExpression | IRelativePattern, path: string, options?: IGlobOptions): boolean { if (!arg1 || typeof path !== 'string') { return false; } - return parse(arg1)(path, undefined, hasSibling); + return parse(arg1, options)(path) as boolean; } /** @@ -572,7 +596,7 @@ export function parse(arg1: string | IExpression | IRelativePattern, options: IG } // Glob with Expression - return parsedExpression(arg1, options); + return parsedExpression(arg1, options); } export function isRelativePattern(obj: unknown): obj is IRelativePattern { @@ -672,7 +696,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse } if (!name) { - name = base.substr(0, base.length - extname(path).length); + name = base.substring(0, base.length - extname(path).length); } } @@ -805,7 +829,7 @@ function aggregateBasenameMatches(parsedPatterns: Array | undefined, patternsB: Array | undefined): boolean { return equals(patternsA, patternsB, (a, b) => { if (typeof a === 'string' && typeof b === 'string') { diff --git a/src/vs/base/common/history.ts b/src/vs/base/common/history.ts index 1e34d03e159..d75120336f6 100644 --- a/src/vs/base/common/history.ts +++ b/src/vs/base/common/history.ts @@ -13,7 +13,7 @@ export interface IHistory { add(t: T): this; has(t: T): boolean; clear(): void; - forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: any): void; + forEach(callbackfn: (value: T, value2: T, set: Set) => void, thisArg?: unknown): void; replace?(t: T[]): void; readonly onDidChange?: Event; } diff --git a/src/vs/base/common/hotReload.ts b/src/vs/base/common/hotReload.ts index 7b983362ea5..f7fc624c5aa 100644 --- a/src/vs/base/common/hotReload.ts +++ b/src/vs/base/common/hotReload.ts @@ -5,9 +5,14 @@ import { IDisposable } from './lifecycle.js'; +let _isHotReloadEnabled = false; + +export function enableHotReload() { + _isHotReloadEnabled = true; +} + export function isHotReloadEnabled(): boolean { - // return env && !!env['VSCODE_DEV_DEBUG']; - return false; // TODO@hediet investigate how to get hot reload + return _isHotReloadEnabled; } export function registerHotReloadHandler(handler: HotReloadHandler): IDisposable { if (!isHotReloadEnabled()) { diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index 6505279e917..ecd9eb445c8 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -19,6 +19,8 @@ export interface IMarkdownString { readonly isTrusted?: boolean | MarkdownStringTrustedOptions; readonly supportThemeIcons?: boolean; readonly supportHtml?: boolean; + /** @internal */ + readonly supportAlertSyntax?: boolean; readonly baseUri?: UriComponents; uris?: { [href: string]: UriComponents }; } @@ -34,6 +36,7 @@ export class MarkdownString implements IMarkdownString { public isTrusted?: boolean | MarkdownStringTrustedOptions; public supportThemeIcons?: boolean; public supportHtml?: boolean; + public supportAlertSyntax?: boolean; public baseUri?: URI; public uris?: { [href: string]: UriComponents } | undefined; @@ -46,7 +49,7 @@ export class MarkdownString implements IMarkdownString { constructor( value: string = '', - isTrustedOrOptions: boolean | { isTrusted?: boolean | MarkdownStringTrustedOptions; supportThemeIcons?: boolean; supportHtml?: boolean } = false, + isTrustedOrOptions: boolean | { isTrusted?: boolean | MarkdownStringTrustedOptions; supportThemeIcons?: boolean; supportHtml?: boolean; supportAlertSyntax?: boolean } = false, ) { this.value = value; if (typeof this.value !== 'string') { @@ -57,11 +60,13 @@ export class MarkdownString implements IMarkdownString { this.isTrusted = isTrustedOrOptions; this.supportThemeIcons = false; this.supportHtml = false; + this.supportAlertSyntax = false; } else { this.isTrusted = isTrustedOrOptions.isTrusted ?? undefined; this.supportThemeIcons = isTrustedOrOptions.supportThemeIcons ?? false; this.supportHtml = isTrustedOrOptions.supportHtml ?? false; + this.supportAlertSyntax = isTrustedOrOptions.supportAlertSyntax ?? false; } } @@ -124,7 +129,8 @@ export function isMarkdownString(thing: unknown): thing is IMarkdownString { } else if (thing && typeof thing === 'object') { return typeof (thing).value === 'string' && (typeof (thing).isTrusted === 'boolean' || typeof (thing).isTrusted === 'object' || (thing).isTrusted === undefined) - && (typeof (thing).supportThemeIcons === 'boolean' || (thing).supportThemeIcons === undefined); + && (typeof (thing).supportThemeIcons === 'boolean' || (thing).supportThemeIcons === undefined) + && (typeof (thing).supportAlertSyntax === 'boolean' || (thing).supportAlertSyntax === undefined); } return false; } @@ -139,6 +145,7 @@ export function markdownStringEqual(a: IMarkdownString, b: IMarkdownString): boo && a.isTrusted === b.isTrusted && a.supportThemeIcons === b.supportThemeIcons && a.supportHtml === b.supportHtml + && a.supportAlertSyntax === b.supportAlertSyntax && (a.baseUri === b.baseUri || !!a.baseUri && !!b.baseUri && isEqual(URI.from(a.baseUri), URI.from(b.baseUri))); } } diff --git a/src/vs/base/common/iterator.ts b/src/vs/base/common/iterator.ts index 59d92ca3994..54db9a8c5b7 100644 --- a/src/vs/base/common/iterator.ts +++ b/src/vs/base/common/iterator.ts @@ -7,13 +7,13 @@ import { isIterable } from './types.js'; export namespace Iterable { - export function is(thing: unknown): thing is Iterable { + export function is(thing: unknown): thing is Iterable { return !!thing && typeof thing === 'object' && typeof (thing as Iterable)[Symbol.iterator] === 'function'; } - const _empty: Iterable = Object.freeze([]); - export function empty(): Iterable { - return _empty; + const _empty: Iterable = Object.freeze([]); + export function empty(): Iterable { + return _empty as Iterable; } export function* single(element: T): Iterable { @@ -29,7 +29,7 @@ export namespace Iterable { } export function from(iterable: Iterable | undefined | null): Iterable { - return iterable || _empty; + return iterable ?? (_empty as Iterable); } export function* reverse(array: ReadonlyArray): Iterable { diff --git a/src/vs/base/common/json.ts b/src/vs/base/common/json.ts index 8623e87503b..d7ac069d3d1 100644 --- a/src/vs/base/common/json.ts +++ b/src/vs/base/common/json.ts @@ -850,7 +850,7 @@ export function parse(text: string, errors: ParseError[] = [], options: ParseOpt function onValue(value: unknown) { if (Array.isArray(currentParent)) { - (currentParent).push(value); + currentParent.push(value); } else if (currentProperty !== null) { currentParent[currentProperty] = value; } @@ -980,7 +980,7 @@ export function findNodeAtLocation(root: Node, path: JSONPath): Node | undefined return undefined; } } else { - const index = segment; + const index = segment; if (node.type !== 'array' || index < 0 || !Array.isArray(node.children) || index >= node.children.length) { return undefined; } diff --git a/src/vs/base/common/jsonSchema.ts b/src/vs/base/common/jsonSchema.ts index 6932da1b2d6..ac98a0ddd5f 100644 --- a/src/vs/base/common/jsonSchema.ts +++ b/src/vs/base/common/jsonSchema.ts @@ -102,31 +102,83 @@ export interface IJSONSchemaSnippet { /** * Converts a basic JSON schema to a TypeScript type. - * - * TODO: only supports basic schemas. Doesn't support all JSON schema features. */ -export type SchemaToType = T extends { type: 'string' } - ? string - : T extends { type: 'number' } - ? number - : T extends { type: 'boolean' } - ? boolean - : T extends { type: 'null' } - ? null - // Object +export type TypeFromJsonSchema = + // enum + T extends { enum: infer EnumValues } + ? UnionOf + + // Object with list of required properties. + // Values are required or optional based on `required` list. + : T extends { type: 'object'; properties: infer P; required: infer RequiredList } + ? { + [K in keyof P]: IsRequired extends true ? TypeFromJsonSchema : TypeFromJsonSchema | undefined; + } & AdditionalPropertiesType + + // Object with no required properties. + // All values are optional : T extends { type: 'object'; properties: infer P } - ? { [K in keyof P]: SchemaToType } + ? { [K in keyof P]: TypeFromJsonSchema | undefined } & AdditionalPropertiesType + // Array - : T extends { type: 'array'; items: infer I } - ? Array> - // OneOf + : T extends { type: 'array'; items: infer Items } + ? Items extends [...infer R] + // If items is an array, we treat it like a tuple + ? { [K in keyof R]: TypeFromJsonSchema } + : Array> + + // oneOf / anyof + // These are handled the same way as they both represent a union type. + // However at the validation level, they have different semantics. : T extends { oneOf: infer I } ? MapSchemaToType + : T extends { anyOf: infer I } + ? MapSchemaToType + + // Primitive types + : T extends { type: infer Type } + // Basic type + ? Type extends 'string' | 'number' | 'integer' | 'boolean' | 'null' + ? SchemaPrimitiveTypeNameToType + // Union of primitive types + : Type extends [...infer R] + ? UnionOf<{ [K in keyof R]: SchemaPrimitiveTypeNameToType }> + : never + // Fallthrough : never; +type SchemaPrimitiveTypeNameToType = + T extends 'string' ? string : + T extends 'number' | 'integer' ? number : + T extends 'boolean' ? boolean : + T extends 'null' ? null : + never; + +type UnionOf = + T extends [infer First, ...infer Rest] + ? First | UnionOf + : never; + +type IsRequired = + RequiredList extends [] + ? false + + : RequiredList extends [K, ...infer _] + ? true + + : RequiredList extends [infer _, ...infer R] + ? IsRequired + + : false; + +type AdditionalPropertiesType = + Schema extends { additionalProperties: infer AP } + ? AP extends false ? {} : { [key: string]: TypeFromJsonSchema } + : {}; + type MapSchemaToType = T extends [infer First, ...infer Rest] - ? SchemaToType | MapSchemaToType + ? TypeFromJsonSchema | MapSchemaToType : never; interface Equals { schemas: IJSONSchema[]; id?: string } diff --git a/src/vs/base/common/keyCodes.ts b/src/vs/base/common/keyCodes.ts index 9f1fd59fddc..8824bd526e3 100644 --- a/src/vs/base/common/keyCodes.ts +++ b/src/vs/base/common/keyCodes.ts @@ -738,14 +738,7 @@ for (let i = 0; i <= KeyCode.MAX_VALUE; i++) { scanCodeLowerCaseStrToInt[scanCodeStr.toLowerCase()] = scanCode; if (immutable) { IMMUTABLE_CODE_TO_KEY_CODE[scanCode] = keyCode; - if ( - (keyCode !== KeyCode.Unknown) - && (keyCode !== KeyCode.Enter) - && (keyCode !== KeyCode.Ctrl) - && (keyCode !== KeyCode.Shift) - && (keyCode !== KeyCode.Alt) - && (keyCode !== KeyCode.Meta) - ) { + if ((keyCode !== KeyCode.Unknown) && (keyCode !== KeyCode.Enter) && !isModifierKey(keyCode)) { IMMUTABLE_KEY_CODE_TO_CODE[keyCode] = scanCode; } } @@ -828,3 +821,12 @@ export function KeyChord(firstPart: number, secondPart: number): number { const chordPart = ((secondPart & 0x0000FFFF) << 16) >>> 0; return (firstPart | chordPart) >>> 0; } + +export function isModifierKey(keyCode: KeyCode): boolean { + return ( + keyCode === KeyCode.Ctrl + || keyCode === KeyCode.Shift + || keyCode === KeyCode.Alt + || keyCode === KeyCode.Meta + ); +} diff --git a/src/vs/base/common/lifecycle.ts b/src/vs/base/common/lifecycle.ts index ff7684f382b..f78aca05b53 100644 --- a/src/vs/base/common/lifecycle.ts +++ b/src/vs/base/common/lifecycle.ts @@ -206,7 +206,9 @@ export class DisposableTracker implements IDisposableTracker { const continuations = groupBy([...prevStarts].map(d => getStackTracePath(d)[i]), v => v); delete continuations[stackTracePath[i]]; for (const [cont, set] of Object.entries(continuations)) { - stackTraceFormattedLines.unshift(` - stacktraces of ${set.length} other leaks continue with ${cont}`); + if (set) { + stackTraceFormattedLines.unshift(` - stacktraces of ${set.length} other leaks continue with ${cont}`); + } } stackTraceFormattedLines.unshift(line); @@ -313,7 +315,7 @@ export interface IDisposable { /** * Check if `thing` is {@link IDisposable disposable}. */ -export function isDisposable(thing: E): thing is E & IDisposable { +export function isDisposable(thing: E): thing is E & IDisposable { // eslint-disable-next-line local/code-no-any-casts return typeof thing === 'object' && thing !== null && typeof (thing).dispose === 'function' && (thing).dispose.length === 0; } diff --git a/src/vs/base/common/linkedList.ts b/src/vs/base/common/linkedList.ts index 42a1c2aad94..b436c611717 100644 --- a/src/vs/base/common/linkedList.ts +++ b/src/vs/base/common/linkedList.ts @@ -5,11 +5,11 @@ class Node { - static readonly Undefined = new Node(undefined); + static readonly Undefined = new Node(undefined); element: E; - next: Node; - prev: Node; + next: Node | typeof Node.Undefined; + prev: Node | typeof Node.Undefined; constructor(element: E) { this.element = element; @@ -20,8 +20,8 @@ class Node { export class LinkedList { - private _first: Node = Node.Undefined; - private _last: Node = Node.Undefined; + private _first: Node | typeof Node.Undefined = Node.Undefined; + private _last: Node | typeof Node.Undefined = Node.Undefined; private _size: number = 0; get size(): number { @@ -91,7 +91,7 @@ export class LinkedList { } else { const res = this._first.element; this._remove(this._first); - return res; + return res as E; } } @@ -101,11 +101,20 @@ export class LinkedList { } else { const res = this._last.element; this._remove(this._last); - return res; + return res as E; } } - private _remove(node: Node): void { + peek(): E | undefined { + if (this._last === Node.Undefined) { + return undefined; + } else { + const res = this._last.element; + return res as E; + } + } + + private _remove(node: Node | typeof Node.Undefined): void { if (node.prev !== Node.Undefined && node.next !== Node.Undefined) { // middle const anchor = node.prev; @@ -135,7 +144,7 @@ export class LinkedList { *[Symbol.iterator](): Iterator { let node = this._first; while (node !== Node.Undefined) { - yield node.element; + yield node.element as E; node = node.next; } } diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 377e37e6ea1..0eb115b0df0 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -116,7 +116,7 @@ export class ResourceMap implements Map { return this.map.delete(this.toKey(resource)); } - forEach(clb: (value: T, key: URI, map: Map) => void, thisArg?: any): void { + forEach(clb: (value: T, key: URI, map: Map) => void, thisArg?: object): void { if (typeof thisArg !== 'undefined') { clb = clb.bind(thisArg); } @@ -185,7 +185,7 @@ export class ResourceSet implements Set { return this._map.delete(value); } - forEach(callbackfn: (value: URI, value2: URI, set: Set) => void, thisArg?: any): void { + forEach(callbackfn: (value: URI, value2: URI, set: Set) => void, thisArg?: unknown): void { this._map.forEach((_value, key) => callbackfn.call(thisArg, key, key, this)); } @@ -340,7 +340,7 @@ export class LinkedMap implements Map { return item.value; } - forEach(callbackfn: (value: V, key: K, map: LinkedMap) => void, thisArg?: any): void { + forEach(callbackfn: (value: V, key: K, map: LinkedMap) => void, thisArg?: unknown): void { const state = this._state; let current = this._head; while (current) { @@ -789,7 +789,7 @@ export class BidirectionalMap { return true; } - forEach(callbackfn: (value: V, key: K, map: BidirectionalMap) => void, thisArg?: any): void { + forEach(callbackfn: (value: V, key: K, map: BidirectionalMap) => void, thisArg?: unknown): void { this._m1.forEach((value, key) => { callbackfn.call(thisArg, value, key, this); }); diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts index 64ebe94abd9..e47b42672fb 100644 --- a/src/vs/base/common/network.ts +++ b/src/vs/base/common/network.ts @@ -87,8 +87,8 @@ export namespace Schemas { /** Scheme used for the chat input part */ export const vscodeChatInput = 'chatSessionInput'; - /** Scheme for chat session content */ - export const vscodeChatSession = 'vscode-chat-session'; + /** Scheme used for local chat session content */ + export const vscodeLocalChatSession = 'vscode-chat-session'; /** * Scheme used internally for webviews that aren't linked to a resource (i.e. not custom editors) @@ -151,6 +151,11 @@ export namespace Schemas { */ export const chatEditingSnapshotScheme = 'chat-editing-snapshot-text-model'; export const chatEditingModel = 'chat-editing-text-model'; + + /** + * Used for rendering multidiffs in copilot agent sessions + */ + export const copilotPr = 'copilot-pr'; } export function matchesScheme(target: URI | string, scheme: string): boolean { @@ -413,8 +418,7 @@ export namespace COI { * isn't enabled the current context */ export function addSearchParam(urlOrSearch: URLSearchParams | Record, coop: boolean, coep: boolean): void { - // eslint-disable-next-line local/code-no-any-casts - if (!(globalThis).crossOriginIsolated) { + if (!(globalThis as typeof globalThis & { crossOriginIsolated?: boolean }).crossOriginIsolated) { // depends on the current context being COI return; } @@ -422,7 +426,7 @@ export namespace COI { if (urlOrSearch instanceof URLSearchParams) { urlOrSearch.set(coiSearchParamName, value); } else { - (>urlOrSearch)[coiSearchParamName] = value; + urlOrSearch[coiSearchParamName] = value; } } } diff --git a/src/vs/base/common/normalization.ts b/src/vs/base/common/normalization.ts index 1d4fbef7f72..8e426391512 100644 --- a/src/vs/base/common/normalization.ts +++ b/src/vs/base/common/normalization.ts @@ -39,11 +39,25 @@ function normalize(str: string, form: string, normalizedCache: LRUCache string = (function () { - // transform into NFD form and remove accents - // see: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463#37511463 - const regex = /[\u0300-\u036f]/g; - return function (str: string) { - return normalizeNFD(str).replace(regex, ''); +/** + * Attempts to normalize the string to Unicode base format (NFD -> remove accents -> lower case). + * When original string contains accent characters directly, only lower casing will be performed. + * This is done so as to keep the string length the same and not affect indices. + * + * @see https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463#37511463 + */ +export const tryNormalizeToBase: (str: string) => string = function () { + const cache = new LRUCache(10000); // bounded to 10000 elements + const accentsRegex = /[\u0300-\u036f]/g; + return function (str: string): string { + const cached = cache.get(str); + if (cached) { + return cached; + } + + const noAccents = normalizeNFD(str).replace(accentsRegex, ''); + const result = (noAccents.length === str.length ? noAccents : str).toLowerCase(); + cache.set(str, result); + return result; }; -})(); +}(); diff --git a/src/vs/base/common/oauth.ts b/src/vs/base/common/oauth.ts index c808bf818b9..32edc99eb39 100644 --- a/src/vs/base/common/oauth.ts +++ b/src/vs/base/common/oauth.ts @@ -1080,7 +1080,7 @@ export function scopesMatch(scopes1: readonly string[] | undefined, scopes2: rea interface CommonResponse { status: number; statusText: string; - json(): Promise; + json(): Promise; text(): Promise; } @@ -1264,34 +1264,47 @@ export async function fetchAuthorizationServerMetadata( const authorizationServerUrl = new URL(authorizationServer); const extraPath = authorizationServerUrl.pathname === '/' ? '' : authorizationServerUrl.pathname; - const doFetch = async (url: string): Promise<{ metadata: IAuthorizationServerMetadata | undefined; rawResponse: CommonResponse }> => { - const rawResponse = await fetchImpl(url, { - method: 'GET', - headers: { - ...additionalHeaders, - 'Accept': 'application/json' + const errors: Error[] = []; + + const doFetch = async (url: string): Promise => { + try { + const rawResponse = await fetchImpl(url, { + method: 'GET', + headers: { + ...additionalHeaders, + 'Accept': 'application/json' + } + }); + const metadata = await tryParseAuthServerMetadata(rawResponse); + if (metadata) { + return metadata; } - }); - const metadata = await tryParseAuthServerMetadata(rawResponse); - return { metadata, rawResponse }; + // No metadata found, collect error from response + errors.push(new Error(`Failed to fetch authorization server metadata from ${url}: ${rawResponse.status} ${await getErrText(rawResponse)}`)); + return undefined; + } catch (e) { + // Collect error from fetch failure + errors.push(e instanceof Error ? e : new Error(String(e))); + return undefined; + } }; // For the oauth server metadata discovery path, we _INSERT_ // the well known path after the origin and before the path. // https://datatracker.ietf.org/doc/html/rfc8414#section-3 const pathToFetch = new URL(AUTH_SERVER_METADATA_DISCOVERY_PATH, authorizationServer).toString() + extraPath; - let result = await doFetch(pathToFetch); - if (result.metadata) { - return result.metadata; + let metadata = await doFetch(pathToFetch); + if (metadata) { + return metadata; } // Try fetching the OpenID Connect Discovery with path insertion. // For issuer URLs with path components, this inserts the well-known path // after the origin and before the path. const openidPathInsertionUrl = new URL(OPENID_CONNECT_DISCOVERY_PATH, authorizationServer).toString() + extraPath; - result = await doFetch(openidPathInsertionUrl); - if (result.metadata) { - return result.metadata; + metadata = await doFetch(openidPathInsertionUrl); + if (metadata) { + return metadata; } // Try fetching the other discovery URL. For the openid metadata discovery @@ -1300,10 +1313,15 @@ export async function fetchAuthorizationServerMetadata( const openidPathAdditionUrl = authorizationServer.endsWith('/') ? authorizationServer + OPENID_CONNECT_DISCOVERY_PATH.substring(1) // Remove leading slash if authServer ends with slash : authorizationServer + OPENID_CONNECT_DISCOVERY_PATH; - result = await doFetch(openidPathAdditionUrl); - if (result.metadata) { - return result.metadata; + metadata = await doFetch(openidPathAdditionUrl); + if (metadata) { + return metadata; } - throw new Error(`Failed to fetch authorization server metadata: ${result.rawResponse.status} ${await getErrText(result.rawResponse)}`); + // If we've tried all URLs and none worked, throw the error(s) + if (errors.length === 1) { + throw errors[0]; + } else { + throw new AggregateError(errors, 'Failed to fetch authorization server metadata from all attempted URLs'); + } } diff --git a/src/vs/base/common/objects.ts b/src/vs/base/common/objects.ts index f25572a931e..e8e60b1ea92 100644 --- a/src/vs/base/common/objects.ts +++ b/src/vs/base/common/objects.ts @@ -69,11 +69,10 @@ function _cloneAndChange(obj: any, changer: (orig: any) => any, seen: Set): throw new Error('Cannot clone recursive data-structure'); } seen.add(obj); - const r2 = {}; + const r2: Record = {}; for (const i2 in obj) { if (_hasOwnProperty.call(obj, i2)) { - // eslint-disable-next-line local/code-no-any-casts - (r2 as any)[i2] = _cloneAndChange(obj[i2], changer, seen); + r2[i2] = _cloneAndChange(obj[i2], changer, seen); } } seen.delete(obj); diff --git a/src/vs/base/common/observableInternal/base.ts b/src/vs/base/common/observableInternal/base.ts index 69922fce403..772297def7f 100644 --- a/src/vs/base/common/observableInternal/base.ts +++ b/src/vs/base/common/observableInternal/base.ts @@ -95,11 +95,6 @@ export interface IObservableWithChange { */ readonly debugName: string; - /** - * ONLY FOR DEBUGGING! - */ - debugGetDependencyGraph(): string; - /** * This property captures the type of the change object. Do not use it at runtime! */ diff --git a/src/vs/base/common/observableInternal/debugLocation.ts b/src/vs/base/common/observableInternal/debugLocation.ts index 43da5b908a2..a0e0d07676f 100644 --- a/src/vs/base/common/observableInternal/debugLocation.ts +++ b/src/vs/base/common/observableInternal/debugLocation.ts @@ -16,8 +16,7 @@ export namespace DebugLocation { if (!enabled) { return undefined; } - // eslint-disable-next-line local/code-no-any-casts - const Err = Error as any as { stackTraceLimit: number }; // For the monaco editor checks, which don't have the nodejs types. + const Err = Error as ErrorConstructor & { stackTraceLimit: number }; const l = Err.stackTraceLimit; Err.stackTraceLimit = 3; diff --git a/src/vs/base/common/observableInternal/debugName.ts b/src/vs/base/common/observableInternal/debugName.ts index d5174f75ab4..a6ce5b71450 100644 --- a/src/vs/base/common/observableInternal/debugName.ts +++ b/src/vs/base/common/observableInternal/debugName.ts @@ -103,8 +103,7 @@ function computeDebugName(self: object, data: DebugNameData): string | undefined function findKey(obj: object, value: object): string | undefined { for (const key in obj) { - // eslint-disable-next-line local/code-no-any-casts - if ((obj as any)[key] === value) { + if ((obj as Record)[key] === value) { return key; } } diff --git a/src/vs/base/common/observableInternal/index.ts b/src/vs/base/common/observableInternal/index.ts index fd23c427331..e3a3e394558 100644 --- a/src/vs/base/common/observableInternal/index.ts +++ b/src/vs/base/common/observableInternal/index.ts @@ -14,7 +14,7 @@ export { type IDerivedReader } from './observables/derivedImpl.js'; export { ObservableLazy, ObservableLazyPromise, ObservablePromise, PromiseResult, } from './utils/promise.js'; export { derivedWithCancellationToken, waitForState } from './utils/utilsCancellation.js'; export { - debouncedObservableDeprecated, debouncedObservable, derivedObservableWithCache, + debouncedObservable, debouncedObservable2, derivedObservableWithCache, derivedObservableWithWritableCache, keepObserved, mapObservableArrayCached, observableFromPromise, recomputeInitiallyAndOnChange, signalFromObservable, wasEventTriggeredRecently, @@ -40,10 +40,10 @@ import { addLogger, setLogObservableFn } from './logging/logging.js'; import { ConsoleObservableLogger, logObservableToConsole } from './logging/consoleObservableLogger.js'; import { DevToolsLogger } from './logging/debugger/devToolsLogger.js'; import { env } from '../process.js'; -import { _setDebugGetDependencyGraph } from './observables/baseObservable.js'; -import { debugGetDependencyGraph } from './logging/debugGetDependencyGraph.js'; +import { _setDebugGetObservableGraph } from './observables/baseObservable.js'; +import { debugGetObservableGraph } from './logging/debugGetDependencyGraph.js'; -_setDebugGetDependencyGraph(debugGetDependencyGraph); +_setDebugGetObservableGraph(debugGetObservableGraph); setLogObservableFn(logObservableToConsole); // Remove "//" in the next line to enable logging diff --git a/src/vs/base/common/observableInternal/logging/debugGetDependencyGraph.ts b/src/vs/base/common/observableInternal/logging/debugGetDependencyGraph.ts index 88c9346d28c..9a13ba8840f 100644 --- a/src/vs/base/common/observableInternal/logging/debugGetDependencyGraph.ts +++ b/src/vs/base/common/observableInternal/logging/debugGetDependencyGraph.ts @@ -10,7 +10,12 @@ import { ObservableValue } from '../observables/observableValue.js'; import { AutorunObserver } from '../reactions/autorunImpl.js'; import { formatValue } from './consoleObservableLogger.js'; -export function debugGetDependencyGraph(obs: IObservable | IObserver, options?: { debugNamePostProcessor?: (name: string) => string }): string { +interface IOptions { + type: 'dependencies' | 'observers'; + debugNamePostProcessor?: (name: string) => string; +} + +export function debugGetObservableGraph(obs: IObservable | IObserver, options: IOptions): string { const debugNamePostProcessor = options?.debugNamePostProcessor ?? ((str: string) => str); const info = Info.from(obs, debugNamePostProcessor); if (!info) { @@ -18,10 +23,15 @@ export function debugGetDependencyGraph(obs: IObservable | IObserver, optio } const alreadyListed = new Set | IObserver>(); - return formatObservableInfo(info, 0, alreadyListed).trim(); + + if (options.type === 'observers') { + return formatObservableInfoWithObservers(info, 0, alreadyListed, options).trim(); + } else { + return formatObservableInfoWithDependencies(info, 0, alreadyListed, options).trim(); + } } -function formatObservableInfo(info: Info, indentLevel: number, alreadyListed: Set | IObserver>): string { +function formatObservableInfoWithDependencies(info: Info, indentLevel: number, alreadyListed: Set | IObserver>, options: IOptions): string { const indent = '\t\t'.repeat(indentLevel); const lines: string[] = []; @@ -40,7 +50,35 @@ function formatObservableInfo(info: Info, indentLevel: number, alreadyListed: Se if (info.dependencies.length > 0) { lines.push(`${indent} dependencies:`); for (const dep of info.dependencies) { - lines.push(formatObservableInfo(dep, indentLevel + 1, alreadyListed)); + const info = Info.from(dep, options.debugNamePostProcessor ?? (name => name)) ?? Info.unknown(dep); + lines.push(formatObservableInfoWithDependencies(info, indentLevel + 1, alreadyListed, options)); + } + } + + return lines.join('\n'); +} + +function formatObservableInfoWithObservers(info: Info, indentLevel: number, alreadyListed: Set | IObserver>, options: IOptions): string { + const indent = '\t\t'.repeat(indentLevel); + const lines: string[] = []; + + const isAlreadyListed = alreadyListed.has(info.sourceObj); + if (isAlreadyListed) { + lines.push(`${indent}* ${info.type} ${info.name} (already listed)`); + return lines.join('\n'); + } + + alreadyListed.add(info.sourceObj); + + lines.push(`${indent}* ${info.type} ${info.name}:`); + lines.push(`${indent} value: ${formatValue(info.value, 50)}`); + lines.push(`${indent} state: ${info.state}`); + + if (info.observers.length > 0) { + lines.push(`${indent} observers:`); + for (const observer of info.observers) { + const info = Info.from(observer, options.debugNamePostProcessor ?? (name => name)) ?? Info.unknown(observer); + lines.push(formatObservableInfoWithObservers(info, indentLevel + 1, alreadyListed, options)); } } @@ -57,7 +95,8 @@ class Info { 'autorun', undefined, state.stateStr, - Array.from(state.dependencies).map(dep => Info.from(dep, debugNamePostProcessor) || Info.unknown(dep)) + Array.from(state.dependencies), + [] ); } else if (obs instanceof Derived) { const state = obs.debugGetState(); @@ -67,7 +106,8 @@ class Info { 'derived', state.value, state.stateStr, - Array.from(state.dependencies).map(dep => Info.from(dep, debugNamePostProcessor) || Info.unknown(dep)) + Array.from(state.dependencies), + Array.from(obs.debugGetObservers()) ); } else if (obs instanceof ObservableValue) { const state = obs.debugGetState(); @@ -77,7 +117,8 @@ class Info { 'observableValue', state.value, 'upToDate', - [] + [], + Array.from(obs.debugGetObservers()) ); } else if (obs instanceof FromEventObservable) { const state = obs.debugGetState(); @@ -87,7 +128,8 @@ class Info { 'fromEvent', state.value, state.hasValue ? 'upToDate' : 'initial', - [] + [], + Array.from(obs.debugGetObservers()) ); } return undefined; @@ -100,6 +142,7 @@ class Info { 'unknown', undefined, 'unknown', + [], [] ); } @@ -110,6 +153,7 @@ class Info { public readonly type: string, public readonly value: any, public readonly state: string, - public readonly dependencies: Info[] + public readonly dependencies: (IObservable | IObserver)[], + public readonly observers: (IObservable | IObserver)[], ) { } } diff --git a/src/vs/base/common/observableInternal/map.ts b/src/vs/base/common/observableInternal/map.ts index 1db8c9ebb26..5cd028db280 100644 --- a/src/vs/base/common/observableInternal/map.ts +++ b/src/vs/base/common/observableInternal/map.ts @@ -51,7 +51,7 @@ export class ObservableMap implements Map { } } - forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void { + forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: unknown): void { this._data.forEach((value, key, _map) => { callbackfn.call(thisArg, value, key, this); }); diff --git a/src/vs/base/common/observableInternal/observables/baseObservable.ts b/src/vs/base/common/observableInternal/observables/baseObservable.ts index 1fe2181695e..4903e1a6e57 100644 --- a/src/vs/base/common/observableInternal/observables/baseObservable.ts +++ b/src/vs/base/common/observableInternal/observables/baseObservable.ts @@ -7,7 +7,7 @@ import { IObservableWithChange, IObserver, IReader, IObservable } from '../base. import { DisposableStore } from '../commonFacade/deps.js'; import { DebugLocation } from '../debugLocation.js'; import { DebugOwner, getFunctionName } from '../debugName.js'; -import { debugGetDependencyGraph } from '../logging/debugGetDependencyGraph.js'; +import { debugGetObservableGraph } from '../logging/debugGetDependencyGraph.js'; import { getLogger, logObservable } from '../logging/logging.js'; import type { keepObserved, recomputeInitiallyAndOnChange } from '../utils/utils.js'; import { derivedOpts } from './derived.js'; @@ -31,9 +31,9 @@ export function _setKeepObserved(keepObserved: typeof _keepObserved) { _keepObserved = keepObserved; } -let _debugGetDependencyGraph: typeof debugGetDependencyGraph; -export function _setDebugGetDependencyGraph(debugGetDependencyGraph: typeof _debugGetDependencyGraph) { - _debugGetDependencyGraph = debugGetDependencyGraph; +let _debugGetObservableGraph: typeof debugGetObservableGraph; +export function _setDebugGetObservableGraph(debugGetObservableGraph: typeof _debugGetObservableGraph) { + _debugGetObservableGraph = debugGetObservableGraph; } export abstract class ConvenientObservable implements IObservableWithChange { @@ -128,8 +128,21 @@ export abstract class ConvenientObservable implements IObservableWit return this.get(); } - debugGetDependencyGraph(): string { - return _debugGetDependencyGraph(this); + get debug(): DebugHelper { + return new DebugHelper(this); + } +} + +class DebugHelper { + constructor(public readonly observable: IObservableWithChange) { + } + + getDependencyGraph(): string { + return _debugGetObservableGraph(this.observable, { type: 'dependencies' }); + } + + getObserverGraph(): string { + return _debugGetObservableGraph(this.observable, { type: 'observers' }); } } diff --git a/src/vs/base/common/observableInternal/observables/derived.ts b/src/vs/base/common/observableInternal/observables/derived.ts index 74b631b2a4d..bb8f9ce5578 100644 --- a/src/vs/base/common/observableInternal/observables/derived.ts +++ b/src/vs/base/common/observableInternal/observables/derived.ts @@ -17,8 +17,8 @@ import { IDerivedReader, Derived, DerivedWithSetter } from './derivedImpl.js'; * * {@link computeFn} should start with a JS Doc using `@description` to name the derived. */ -export function derived(computeFn: (reader: IDerivedReader) => T): IObservableWithChange; -export function derived(owner: DebugOwner, computeFn: (reader: IDerivedReader) => T): IObservableWithChange; +export function derived(computeFn: (reader: IDerivedReader, debugLocation?: DebugLocation) => T): IObservableWithChange; +export function derived(owner: DebugOwner, computeFn: (reader: IDerivedReader) => T, debugLocation?: DebugLocation): IObservableWithChange; export function derived( computeFnOrOwner: ((reader: IDerivedReader) => T) | DebugOwner, computeFn?: ((reader: IDerivedReader) => T) | undefined, diff --git a/src/vs/base/common/observableInternal/utils/promise.ts b/src/vs/base/common/observableInternal/utils/promise.ts index e36c6be95e1..a6493858f6c 100644 --- a/src/vs/base/common/observableInternal/utils/promise.ts +++ b/src/vs/base/common/observableInternal/utils/promise.ts @@ -41,6 +41,10 @@ export class ObservablePromise { return new ObservablePromise(fn()); } + public static resolved(value: T): ObservablePromise { + return new ObservablePromise(Promise.resolve(value)); + } + private readonly _value = observableValue | undefined>(this, undefined); /** diff --git a/src/vs/base/common/observableInternal/utils/utils.ts b/src/vs/base/common/observableInternal/utils/utils.ts index ed35204c7e3..9d643835d29 100644 --- a/src/vs/base/common/observableInternal/utils/utils.ts +++ b/src/vs/base/common/observableInternal/utils/utils.ts @@ -5,7 +5,6 @@ import { autorun } from '../reactions/autorun.js'; import { IObservable, IObservableWithChange, IObserver, IReader, ITransaction } from '../base.js'; -import { transaction } from '../transaction.js'; import { observableValue } from '../observables/observableValue.js'; import { DebugOwner } from '../debugName.js'; import { DisposableStore, Event, IDisposable, toDisposable } from '../commonFacade/deps.js'; @@ -13,6 +12,7 @@ import { derived, derivedOpts } from '../observables/derived.js'; import { observableFromEvent } from '../observables/observableFromEvent.js'; import { observableSignal } from '../observables/observableSignal.js'; import { _setKeepObserved, _setRecomputeInitiallyAndOnChange } from '../observables/baseObservable.js'; +import { DebugLocation } from '../debugLocation.js'; export function observableFromPromise(promise: Promise): IObservable<{ value?: T }> { const observable = observableValue<{ value?: T }>('promiseValue', {}); @@ -31,42 +31,16 @@ export function signalFromObservable(owner: DebugOwner | undefined, observabl }); } -/** - * @deprecated Use `debouncedObservable` instead. - */ -export function debouncedObservableDeprecated(observable: IObservable, debounceMs: number, disposableStore: DisposableStore): IObservable { - const debouncedObservable = observableValue('debounced', undefined); - - let timeout: Timeout | undefined = undefined; - - disposableStore.add(autorun(reader => { - /** @description debounce */ - const value = observable.read(reader); - - if (timeout) { - clearTimeout(timeout); - } - timeout = setTimeout(() => { - transaction(tx => { - debouncedObservable.set(value, tx); - }); - }, debounceMs); - - })); - - return debouncedObservable; -} - /** * Creates an observable that debounces the input observable. */ -export function debouncedObservable(observable: IObservable, debounceMs: number): IObservable { +export function debouncedObservable(observable: IObservable, debounceMs: number | ((lastValue: T | undefined, newValue: T) => number), debugLocation = DebugLocation.ofCaller()): IObservable { let hasValue = false; let lastValue: T | undefined; let timeout: Timeout | undefined = undefined; - return observableFromEvent(cb => { + return observableFromEvent(undefined, cb => { const d = autorun(reader => { const value = observable.read(reader); @@ -77,10 +51,16 @@ export function debouncedObservable(observable: IObservable, debounceMs: n if (timeout) { clearTimeout(timeout); } + const debounceDuration = typeof debounceMs === 'number' ? debounceMs : debounceMs(lastValue, value); + if (debounceDuration === 0) { + lastValue = value; + cb(); + return; + } timeout = setTimeout(() => { lastValue = value; cb(); - }, debounceMs); + }, debounceDuration); } }); return { @@ -96,7 +76,48 @@ export function debouncedObservable(observable: IObservable, debounceMs: n } else { return observable.get(); } - }); + }, debugLocation); +} + +/** + * Creates an observable that debounces the input observable. + */ +export function debouncedObservable2(observable: IObservable, debounceMs: number | ((currentValue: T | undefined, newValue: T) => number), debugLocation = DebugLocation.ofCaller()): IObservable { + const s = observableSignal('handleTimeout'); + + let currentValue: T | undefined = undefined; + let timeout: Timeout | undefined = undefined; + + const d = derivedOpts({ + owner: undefined, + onLastObserverRemoved: () => { + currentValue = undefined; + } + }, reader => { + const val = observable.read(reader); + s.read(reader); + + if (val !== currentValue) { + const debounceDuration = typeof debounceMs === 'number' ? debounceMs : debounceMs(currentValue, val); + + if (debounceDuration === 0) { + currentValue = val; + return val; + } + + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(() => { + currentValue = val; + s.trigger(undefined); + }, debounceDuration); + } + + return currentValue!; + }, debugLocation); + + return d; } export function wasEventTriggeredRecently(event: Event, timeoutMs: number, disposableStore: DisposableStore): IObservable { @@ -225,7 +246,8 @@ export function mapObservableArrayCached(owner: DebugOwne m = new ArrayMap(map); } }, (reader) => { - m.setItems(items.read(reader)); + const i = items.read(reader); + m.setItems(i); return m.getItems(); }); return self; diff --git a/src/vs/base/common/paging.ts b/src/vs/base/common/paging.ts index 463852a8cd7..295600dac63 100644 --- a/src/vs/base/common/paging.ts +++ b/src/vs/base/common/paging.ts @@ -6,6 +6,7 @@ import { range } from './arrays.js'; import { CancellationToken, CancellationTokenSource } from './cancellation.js'; import { CancellationError } from './errors.js'; +import { Event, Emitter } from './event.js'; /** * A Pager is a stateless abstraction over a paged collection. @@ -17,6 +18,16 @@ export interface IPager { getPage(pageIndex: number, cancellationToken: CancellationToken): Promise; } +export interface IIterativePage { + readonly items: T[]; + readonly hasMore: boolean; +} + +export interface IIterativePager { + readonly firstPage: IIterativePage; + getNextPage(cancellationToken: CancellationToken): Promise>; +} + export interface IPageIterator { elements: T[]; total: number; @@ -46,7 +57,8 @@ function createPage(elements?: T[]): IPage { * A PagedModel is a stateful model over an abstracted paged collection. */ export interface IPagedModel { - length: number; + readonly length: number; + readonly onDidIncrementLength: Event; isResolved(index: number): boolean; get(index: number): T; resolve(index: number, cancellationToken: CancellationToken): Promise; @@ -69,6 +81,7 @@ export class PagedModel implements IPagedModel { private pages: IPage[] = []; get length(): number { return this.pager.total; } + readonly onDidIncrementLength = Event.None; constructor(arg: IPager | T[]) { this.pager = Array.isArray(arg) ? singlePagePager(arg) : arg; @@ -147,8 +160,9 @@ export class PagedModel implements IPagedModel { export class DelayedPagedModel implements IPagedModel { get length(): number { return this.model.length; } + get onDidIncrementLength() { return this.model.onDidIncrementLength; } - constructor(private model: IPagedModel, private timeout: number = 500) { } + constructor(private readonly model: IPagedModel, private timeout: number = 500) { } isResolved(index: number): boolean { return this.model.isResolved(index); @@ -265,6 +279,107 @@ export class PageIteratorPager implements IPager { } } +export class IterativePagedModel implements IPagedModel { + + private items: T[] = []; + private _hasNextPage = true; + private readonly _onDidIncrementLength = new Emitter(); + private loadingPromise: Promise | null = null; + + private readonly pager: IIterativePager; + + constructor(pager: IIterativePager) { + this.pager = pager; + this.items = [...pager.firstPage.items]; + this._hasNextPage = pager.firstPage.hasMore; + } + + get onDidIncrementLength(): Event { + return this._onDidIncrementLength.event; + } + + /** + * Returns actual length + 1 if there are more pages (sentinel approach) + */ + get length(): number { + return this.items.length + (this._hasNextPage ? 1 : 0); + } + + /** + * Sentinel item is never resolved - it triggers loading + */ + isResolved(index: number): boolean { + if (index === this.items.length && this._hasNextPage) { + return false; // This will trigger resolve() call + } + return index < this.items.length; + } + + get(index: number): T { + if (index < this.items.length) { + return this.items[index]; + } + throw new Error('Item not resolved yet'); + } + + /** + * When sentinel item is accessed, load next page + */ + async resolve(index: number, cancellationToken: CancellationToken): Promise { + if (cancellationToken.isCancellationRequested) { + return Promise.reject(new CancellationError()); + } + + // If trying to resolve the sentinel item, load next page + if (index === this.items.length && this._hasNextPage) { + await this.loadNextPage(cancellationToken); + } + + // After loading, the requested index should now be valid + if (index < this.items.length) { + return this.items[index]; + } + + throw new Error('Index out of bounds'); + } + + private async loadNextPage(cancellationToken: CancellationToken): Promise { + if (!this._hasNextPage) { + return; + } + + // If already loading, return the cached promise + if (this.loadingPromise) { + await this.loadingPromise; + return; + } + + const pagePromise = this.pager.getNextPage(cancellationToken); + + this.loadingPromise = pagePromise + .then(page => { + this.items.push(...page.items); + this._hasNextPage = page.hasMore; + + // Clear the loading promise before firing the event + // so that event handlers can trigger loading the next page if needed + this.loadingPromise = null; + + // Fire length update event + this._onDidIncrementLength.fire(this.length); + }, err => { + this.loadingPromise = null; + throw err; + }); + + await this.loadingPromise; + } + + dispose(): void { + this._onDidIncrementLength.dispose(); + } +} + /** * Similar to array.map, `mapPager` lets you map the elements of an * abstract paged collection to another type. diff --git a/src/vs/base/common/policy.ts b/src/vs/base/common/policy.ts index 1e97392d5e2..8141b0f9b5d 100644 --- a/src/vs/base/common/policy.ts +++ b/src/vs/base/common/policy.ts @@ -3,9 +3,57 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import { localize } from '../../nls.js'; import { IDefaultAccount } from './defaultAccount.js'; +/** + * System-wide policy file path for Linux systems. + */ +export const LINUX_SYSTEM_POLICY_FILE_PATH = '/etc/vscode/policy.json'; + export type PolicyName = string; +export type LocalizedValue = { + key: string; + value: string; +}; + +export enum PolicyCategory { + Extensions = 'Extensions', + IntegratedTerminal = 'IntegratedTerminal', + InteractiveSession = 'InteractiveSession', + Telemetry = 'Telemetry', + Update = 'Update', +} + +export const PolicyCategoryData: { + [key in PolicyCategory]: { name: LocalizedValue } +} = { + [PolicyCategory.Extensions]: { + name: { + key: 'extensionsConfigurationTitle', value: localize('extensionsConfigurationTitle', "Extensions"), + } + }, + [PolicyCategory.IntegratedTerminal]: { + name: { + key: 'terminalIntegratedConfigurationTitle', value: localize('terminalIntegratedConfigurationTitle', "Integrated Terminal"), + } + }, + [PolicyCategory.InteractiveSession]: { + name: { + key: 'interactiveSessionConfigurationTitle', value: localize('interactiveSessionConfigurationTitle', "Chat"), + } + }, + [PolicyCategory.Telemetry]: { + name: { + key: 'telemetryConfigurationTitle', value: localize('telemetryConfigurationTitle', "Telemetry"), + } + }, + [PolicyCategory.Update]: { + name: { + key: 'updateConfigurationTitle', value: localize('updateConfigurationTitle', "Update"), + } + } +}; export interface IPolicy { @@ -14,15 +62,27 @@ export interface IPolicy { */ readonly name: PolicyName; + /** + * The policy category. + */ + readonly category: PolicyCategory; + /** * The Code version in which this policy was introduced. */ readonly minimumVersion: `${number}.${number}`; /** - * The policy description (optional). + * Localization info for the policy. + * + * IMPORTANT: the key values for these must be unique to avoid collisions, as during the export time the module information is not available. */ - readonly description?: string; + readonly localization: { + /** The localization key or key value pair. If only a key is provided, the default value will fallback to the parent configuration's description property. */ + description: LocalizedValue; + /** List of localization key or key value pair. If only a key is provided, the default value will fallback to the parent configuration's enumDescriptions property. */ + enumDescriptions?: LocalizedValue[]; + }; /** * The value that an ACCOUNT-based feature will use when its corresponding policy is active. diff --git a/src/vs/base/common/product.ts b/src/vs/base/common/product.ts index 2b552bdde7c..9529eb95910 100644 --- a/src/vs/base/common/product.ts +++ b/src/vs/base/common/product.ts @@ -212,6 +212,7 @@ export interface IProductConfiguration { readonly id: string; readonly enterpriseProviderId: string; readonly enterpriseProviderConfig: string; + readonly enterpriseProviderUriSetting: string; readonly scopes: string[]; }; readonly tokenEntitlementUrl: string; diff --git a/src/vs/base/common/resourceTree.ts b/src/vs/base/common/resourceTree.ts index c1a1c951bb2..5328c30b448 100644 --- a/src/vs/base/common/resourceTree.ts +++ b/src/vs/base/common/resourceTree.ts @@ -75,7 +75,7 @@ function collect(node: IResourceNode, result: T[]): T[] { return result; } -export class ResourceTree, C> { +export class ResourceTree, C> { readonly root: Node; diff --git a/src/vs/base/common/skipList.ts b/src/vs/base/common/skipList.ts deleted file mode 100644 index 295adb603fe..00000000000 --- a/src/vs/base/common/skipList.ts +++ /dev/null @@ -1,206 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - - -class Node { - readonly forward: Node[]; - constructor(readonly level: number, readonly key: K, public value: V) { - this.forward = []; - } -} - -const NIL: undefined = undefined; - -interface Comparator { - (a: K, b: K): number; -} - -export class SkipList implements Map { - - readonly [Symbol.toStringTag] = 'SkipList'; - - private _maxLevel: number; - private _level: number = 0; - private _header: Node; - private _size: number = 0; - - /** - * - * @param capacity Capacity at which the list performs best - */ - constructor( - readonly comparator: (a: K, b: K) => number, - capacity: number = 2 ** 16 - ) { - this._maxLevel = Math.max(1, Math.log2(capacity) | 0); - // eslint-disable-next-line local/code-no-any-casts - this._header = new Node(this._maxLevel, NIL, NIL); - } - - get size(): number { - return this._size; - } - - clear(): void { - // eslint-disable-next-line local/code-no-any-casts - this._header = new Node(this._maxLevel, NIL, NIL); - this._size = 0; - } - - has(key: K): boolean { - return Boolean(SkipList._search(this, key, this.comparator)); - } - - get(key: K): V | undefined { - return SkipList._search(this, key, this.comparator)?.value; - } - - set(key: K, value: V): this { - if (SkipList._insert(this, key, value, this.comparator)) { - this._size += 1; - } - return this; - } - - delete(key: K): boolean { - const didDelete = SkipList._delete(this, key, this.comparator); - if (didDelete) { - this._size -= 1; - } - return didDelete; - } - - // --- iteration - - forEach(callbackfn: (value: V, key: K, map: Map) => void, thisArg?: any): void { - let node = this._header.forward[0]; - while (node) { - callbackfn.call(thisArg, node.value, node.key, this); - node = node.forward[0]; - } - } - - [Symbol.iterator](): IterableIterator<[K, V]> { - return this.entries(); - } - - *entries(): IterableIterator<[K, V]> { - let node = this._header.forward[0]; - while (node) { - yield [node.key, node.value]; - node = node.forward[0]; - } - } - - *keys(): IterableIterator { - let node = this._header.forward[0]; - while (node) { - yield node.key; - node = node.forward[0]; - } - } - - *values(): IterableIterator { - let node = this._header.forward[0]; - while (node) { - yield node.value; - node = node.forward[0]; - } - } - - toString(): string { - // debug string... - let result = '[SkipList]:'; - let node = this._header.forward[0]; - while (node) { - result += `node(${node.key}, ${node.value}, lvl:${node.level})`; - node = node.forward[0]; - } - return result; - } - - // from https://www.epaperpress.com/sortsearch/download/skiplist.pdf - - private static _search(list: SkipList, searchKey: K, comparator: Comparator) { - let x = list._header; - for (let i = list._level - 1; i >= 0; i--) { - while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { - x = x.forward[i]; - } - } - x = x.forward[0]; - if (x && comparator(x.key, searchKey) === 0) { - return x; - } - return undefined; - } - - private static _insert(list: SkipList, searchKey: K, value: V, comparator: Comparator) { - const update: Node[] = []; - let x = list._header; - for (let i = list._level - 1; i >= 0; i--) { - while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { - x = x.forward[i]; - } - update[i] = x; - } - x = x.forward[0]; - if (x && comparator(x.key, searchKey) === 0) { - // update - x.value = value; - return false; - } else { - // insert - const lvl = SkipList._randomLevel(list); - if (lvl > list._level) { - for (let i = list._level; i < lvl; i++) { - update[i] = list._header; - } - list._level = lvl; - } - x = new Node(lvl, searchKey, value); - for (let i = 0; i < lvl; i++) { - x.forward[i] = update[i].forward[i]; - update[i].forward[i] = x; - } - return true; - } - } - - private static _randomLevel(list: SkipList, p: number = 0.5): number { - let lvl = 1; - while (Math.random() < p && lvl < list._maxLevel) { - lvl += 1; - } - return lvl; - } - - private static _delete(list: SkipList, searchKey: K, comparator: Comparator) { - const update: Node[] = []; - let x = list._header; - for (let i = list._level - 1; i >= 0; i--) { - while (x.forward[i] && comparator(x.forward[i].key, searchKey) < 0) { - x = x.forward[i]; - } - update[i] = x; - } - x = x.forward[0]; - if (!x || comparator(x.key, searchKey) !== 0) { - // not found - return false; - } - for (let i = 0; i < list._level; i++) { - if (update[i].forward[i] !== x) { - break; - } - update[i].forward[i] = x.forward[i]; - } - while (list._level > 0 && list._header.forward[list._level - 1] === NIL) { - list._level -= 1; - } - return true; - } - -} diff --git a/src/vs/base/common/strings.ts b/src/vs/base/common/strings.ts index aae729560f8..c341d98e26a 100644 --- a/src/vs/base/common/strings.ts +++ b/src/vs/base/common/strings.ts @@ -23,6 +23,7 @@ const _formatRegexp = /{(\d+)}/g; * @param value string to which formatting is applied * @param args replacements for {n}-entries */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function format(value: string, ...args: any[]): string { if (args.length === 0) { return value; @@ -322,7 +323,7 @@ export function getIndentationLength(str: string): number { * Function that works identically to String.prototype.replace, except, the * replace function is allowed to be async and return a Promise. */ -export function replaceAsync(str: string, search: RegExp, replacer: (match: string, ...args: any[]) => Promise): Promise { +export function replaceAsync(str: string, search: RegExp, replacer: (match: string, ...args: unknown[]) => Promise): Promise { const parts: (string | Promise)[] = []; let last = 0; @@ -438,13 +439,19 @@ export function equalsIgnoreCase(a: string, b: string): boolean { return a.length === b.length && compareSubstringIgnoreCase(a, b) === 0; } -export function startsWithIgnoreCase(str: string, candidate: string): boolean { - const candidateLength = candidate.length; - if (candidate.length > str.length) { - return false; - } +export function equals(a: string | undefined, b: string | undefined, ignoreCase?: boolean): boolean { + return a === b || (!!ignoreCase && a !== undefined && b !== undefined && equalsIgnoreCase(a, b)); +} - return compareSubstringIgnoreCase(str, candidate, 0, candidateLength) === 0; +export function startsWithIgnoreCase(str: string, candidate: string): boolean { + const len = candidate.length; + return len <= str.length && compareSubstringIgnoreCase(str, candidate, 0, len) === 0; +} + +export function endsWithIgnoreCase(str: string, candidate: string): boolean { + const len = str.length; + const start = len - candidate.length; + return start >= 0 && compareSubstringIgnoreCase(str, candidate, start, len) === 0; } /** @@ -1232,7 +1239,7 @@ export class AmbiguousCharacters { const data = this.ambiguousCharacterData.value; let filteredLocales = locales.filter( - (l) => !l.startsWith('_') && l in data + (l) => !l.startsWith('_') && Object.hasOwn(data, l) ); if (filteredLocales.length === 0) { filteredLocales = ['_default']; diff --git a/src/vs/base/common/ternarySearchTree.ts b/src/vs/base/common/ternarySearchTree.ts index fef1f8e1cf0..d184ed1765e 100644 --- a/src/vs/base/common/ternarySearchTree.ts +++ b/src/vs/base/common/ternarySearchTree.ts @@ -258,7 +258,7 @@ abstract class Undef { } static unwrap(value: V | typeof Undef.Val): V | undefined { - return value === Undef.Val ? undefined : value as V; + return value === Undef.Val ? undefined : value; } } @@ -781,7 +781,7 @@ export class TernarySearchTree { // for debug/testing _isBalanced(): boolean { - const nodeIsBalanced = (node: TernarySearchTreeNode | undefined): boolean => { + const nodeIsBalanced = (node: TernarySearchTreeNode | undefined): boolean => { if (!node) { return true; } diff --git a/src/vs/base/common/themables.ts b/src/vs/base/common/themables.ts index 6b2551bebb2..dcc1369e593 100644 --- a/src/vs/base/common/themables.ts +++ b/src/vs/base/common/themables.ts @@ -101,4 +101,17 @@ export namespace ThemeIcon { return ti1.id === ti2.id && ti1.color?.id === ti2.color?.id; } + /** + * Returns whether specified icon is defined and has 'file' ID. + */ + export function isFile(icon: ThemeIcon | undefined): boolean { + return icon?.id === Codicon.file.id; + } + + /** + * Returns whether specified icon is defined and has 'folder' ID. + */ + export function isFolder(icon: ThemeIcon | undefined): boolean { + return icon?.id === Codicon.folder.id; + } } diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index cef83d93e3a..811c46599f0 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -326,6 +326,23 @@ export type Mutable = { -readonly [P in keyof T]: T[P] }; +/** + * A type that adds readonly to all properties of T, recursively. + */ +export type DeepImmutable = T extends (infer U)[] + ? ReadonlyArray> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends Map + ? ReadonlyMap> + : T extends Set + ? ReadonlySet> + : T extends object + ? { + readonly [K in keyof T]: DeepImmutable; + } + : T; + /** * A single object or an array of the objects. */ @@ -351,3 +368,36 @@ export type DeepPartial = { * Represents a type that is a partial version of a given type `T`, except a subset. */ export type PartialExcept = Partial> & Pick; + + +type KeysOfUnionType = T extends T ? keyof T : never; +type FilterType = T extends TTest ? T : never; +type MakeOptionalAndTrue = { [K in keyof T]?: true }; + +/** + * Type guard that checks if an object has specific keys and narrows the type accordingly. + * + * @param x - The object to check + * @param key - An object with boolean values indicating which keys to check for + * @returns true if all specified keys exist in the object, false otherwise + * + * @example + * ```typescript + * type A = { a: string }; + * type B = { b: number }; + * const obj: A | B = getObject(); + * + * if (hasKey(obj, { a: true })) { + * // obj is now narrowed to type A + * console.log(obj.a); + * } + * ``` + */ +export function hasKey>(x: T, key: TKeys): x is FilterType & keyof TKeys]: unknown }> { + for (const k in key) { + if (!(k in x)) { + return false; + } + } + return true; +} diff --git a/src/vs/base/common/uriIpc.ts b/src/vs/base/common/uriIpc.ts index 2022176c1f3..67bf4c3428c 100644 --- a/src/vs/base/common/uriIpc.ts +++ b/src/vs/base/common/uriIpc.ts @@ -30,8 +30,7 @@ export interface IRawURITransformer { } function toJSON(uri: URI): UriComponents { - // eslint-disable-next-line local/code-no-any-casts - return uri.toJSON(); + return uri.toJSON(); } export class URITransformer implements IURITransformer { diff --git a/src/vs/base/common/validation.ts b/src/vs/base/common/validation.ts new file mode 100644 index 00000000000..e94e451a00b --- /dev/null +++ b/src/vs/base/common/validation.ts @@ -0,0 +1,396 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { mapFilter } from './arrays.js'; +import { IJSONSchema } from './jsonSchema.js'; + +export interface IValidator { + validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError }; + + getJSONSchema(): IJSONSchema; +} + +export abstract class ValidatorBase implements IValidator { + abstract validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError }; + + abstract getJSONSchema(): IJSONSchema; + + validateOrThrow(content: unknown): T { + const result = this.validate(content); + if (result.error) { + throw new Error(result.error.message); + } + return result.content; + } +} + +export type ValidatorType = T extends IValidator ? U : never; + +export interface ValidationError { + message: string; +} + +type TypeOfMap = { + string: string; + number: number; + boolean: boolean; + object: object; + null: null; +}; + +class TypeofValidator extends ValidatorBase { + constructor(private readonly type: TKey) { + super(); + } + + validate(content: unknown): { content: TypeOfMap[TKey]; error: undefined } | { content: undefined; error: ValidationError } { + if (typeof content !== this.type) { + return { content: undefined, error: { message: `Expected ${this.type}, but got ${typeof content}` } }; + } + + return { content: content as TypeOfMap[TKey], error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return { type: this.type }; + } +} + +const vStringValidator = new TypeofValidator('string'); +export function vString(): ValidatorBase { return vStringValidator; } + +const vNumberValidator = new TypeofValidator('number'); +export function vNumber(): ValidatorBase { return vNumberValidator; } + +const vBooleanValidator = new TypeofValidator('boolean'); +export function vBoolean(): ValidatorBase { return vBooleanValidator; } + +const vObjAnyValidator = new TypeofValidator('object'); +export function vObjAny(): ValidatorBase { return vObjAnyValidator; } + + +class UncheckedValidator extends ValidatorBase { + validate(content: unknown): { content: T; error: undefined } { + return { content: content as T, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return {}; + } +} + +export function vUnchecked(): ValidatorBase { + return new UncheckedValidator(); +} + +class UndefinedValidator extends ValidatorBase { + validate(content: unknown): { content: undefined; error: undefined } | { content: undefined; error: ValidationError } { + if (content !== undefined) { + return { content: undefined, error: { message: `Expected undefined, but got ${typeof content}` } }; + } + + return { content: undefined, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return {}; + } +} + +export function vUndefined(): ValidatorBase { + return new UndefinedValidator(); +} + +export function vUnknown(): ValidatorBase { + return vUnchecked(); +} + +export type ObjectProperties = Record; + +export class Optional> { + constructor(public readonly validator: T) { } +} + +export function vOptionalProp(validator: IValidator): Optional> { + return new Optional(validator); +} + +type ExtractOptionalKeys = { + [K in keyof T]: T[K] extends Optional> ? K : never; +}[keyof T]; + +type ExtractRequiredKeys = { + [K in keyof T]: T[K] extends Optional> ? never : K; +}[keyof T]; + +export type vObjType | Optional>>> = { + [K in ExtractRequiredKeys]: T[K] extends IValidator ? U : never; +} & { + [K in ExtractOptionalKeys]?: T[K] extends Optional> ? U : never; +}; + +class ObjValidator | Optional>>> extends ValidatorBase> { + constructor(private readonly properties: T) { + super(); + } + + validate(content: unknown): { content: vObjType; error: undefined } | { content: undefined; error: ValidationError } { + if (typeof content !== 'object' || content === null) { + return { content: undefined, error: { message: 'Expected object' } }; + } + + // eslint-disable-next-line local/code-no-dangerous-type-assertions + const result: vObjType = {} as vObjType; + + for (const key in this.properties) { + const prop = this.properties[key]; + // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any + const fieldValue = (content as any)[key]; + + const isOptional = prop instanceof Optional; + const validator: IValidator = isOptional ? prop.validator : prop; + + if (isOptional && fieldValue === undefined) { + // Optional field not provided, skip validation + continue; + } + + const { content: value, error } = validator.validate(fieldValue); + if (error) { + return { content: undefined, error: { message: `Error in property '${key}': ${error.message}` } }; + } + + // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any + (result as any)[key] = value; + } + + return { content: result, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + const requiredFields: string[] = []; + const schemaProperties: Record = {}; + + for (const [key, prop] of Object.entries(this.properties)) { + const isOptional = prop instanceof Optional; + const validator: IValidator = isOptional ? prop.validator : prop; + schemaProperties[key] = validator.getJSONSchema(); + if (!isOptional) { + requiredFields.push(key); + } + } + + const schema: IJSONSchema = { + type: 'object', + properties: schemaProperties, + ...(requiredFields.length > 0 ? { required: requiredFields } : {}) + }; + + return schema; + } +} + +export function vObj | Optional>>>(properties: T): ValidatorBase> { + return new ObjValidator(properties); +} + +class ArrayValidator extends ValidatorBase { + constructor(private readonly validator: IValidator) { + super(); + } + + validate(content: unknown): { content: T[]; error: undefined } | { content: undefined; error: ValidationError } { + if (!Array.isArray(content)) { + return { content: undefined, error: { message: 'Expected array' } }; + } + + const result: T[] = []; + for (let i = 0; i < content.length; i++) { + const { content: value, error } = this.validator.validate(content[i]); + if (error) { + return { content: undefined, error: { message: `Error in element ${i}: ${error.message}` } }; + } + + result.push(value); + } + + return { content: result, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return { + type: 'array', + items: this.validator.getJSONSchema(), + }; + } +} + +export function vArray(validator: IValidator): ValidatorBase { + return new ArrayValidator(validator); +} + +type vTupleType[]> = { [K in keyof T]: ValidatorType }; + +class TupleValidator[]> extends ValidatorBase> { + constructor(private readonly validators: T) { + super(); + } + + validate(content: unknown): { content: vTupleType; error: undefined } | { content: undefined; error: ValidationError } { + if (!Array.isArray(content)) { + return { content: undefined, error: { message: 'Expected array' } }; + } + + if (content.length !== this.validators.length) { + return { content: undefined, error: { message: `Expected tuple of length ${this.validators.length}, but got ${content.length}` } }; + } + + const result = [] as vTupleType; + for (let i = 0; i < this.validators.length; i++) { + const validator = this.validators[i]; + const { content: value, error } = validator.validate(content[i]); + if (error) { + return { content: undefined, error: { message: `Error in element ${i}: ${error.message}` } }; + } + result.push(value); + } + + return { content: result, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return { + type: 'array', + items: this.validators.map(validator => validator.getJSONSchema()), + }; + } +} + +export function vTuple[]>(...validators: T): ValidatorBase> { + return new TupleValidator(validators); +} + +class UnionValidator[]> extends ValidatorBase> { + constructor(private readonly validators: T) { + super(); + } + + validate(content: unknown): { content: ValidatorType; error: undefined } | { content: undefined; error: ValidationError } { + let lastError: ValidationError | undefined; + for (const validator of this.validators) { + const { content: value, error } = validator.validate(content); + if (!error) { + // eslint-disable-next-line local/code-no-any-casts, @typescript-eslint/no-explicit-any + return { content: value as any, error: undefined }; + } + + lastError = error; + } + + return { content: undefined, error: lastError! }; + } + + getJSONSchema(): IJSONSchema { + return { + oneOf: mapFilter(this.validators, validator => { + if (validator instanceof UndefinedValidator) { + return undefined; + } + return validator.getJSONSchema(); + }), + }; + } +} + +export function vUnion[]>(...validators: T): ValidatorBase> { + return new UnionValidator(validators); +} + +class EnumValidator extends ValidatorBase { + constructor(private readonly values: T) { + super(); + } + + validate(content: unknown): { content: T[number]; error: undefined } | { content: undefined; error: ValidationError } { + if (this.values.indexOf(content as string) === -1) { + return { content: undefined, error: { message: `Expected one of: ${this.values.join(', ')}` } }; + } + + return { content: content as T[number], error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return { + enum: this.values, + }; + } +} + +export function vEnum(...values: T): ValidatorBase { + return new EnumValidator(values); +} + +class LiteralValidator extends ValidatorBase { + constructor(private readonly value: T) { + super(); + } + + validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } { + if (content !== this.value) { + return { content: undefined, error: { message: `Expected: ${this.value}` } }; + } + + return { content: content as T, error: undefined }; + } + + getJSONSchema(): IJSONSchema { + return { + const: this.value, + }; + } +} + +export function vLiteral(value: T): ValidatorBase { + return new LiteralValidator(value); +} + +class LazyValidator extends ValidatorBase { + constructor(private readonly fn: () => IValidator) { + super(); + } + + validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } { + return this.fn().validate(content); + } + + getJSONSchema(): IJSONSchema { + return this.fn().getJSONSchema(); + } +} + +export function vLazy(fn: () => IValidator): ValidatorBase { + return new LazyValidator(fn); +} + +class UseRefSchemaValidator extends ValidatorBase { + constructor( + private readonly _ref: string, + private readonly _validator: IValidator + ) { + super(); + } + + validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } { + return this._validator.validate(content); + } + + getJSONSchema(): IJSONSchema { + return { $ref: this._ref }; + } +} + +export function vWithJsonSchemaRef(ref: string, validator: IValidator): ValidatorBase { + return new UseRefSchemaValidator(ref, validator); +} diff --git a/src/vs/base/common/yaml.ts b/src/vs/base/common/yaml.ts index cbbb5247b6c..6f2e801d696 100644 --- a/src/vs/base/common/yaml.ts +++ b/src/vs/base/common/yaml.ts @@ -746,13 +746,24 @@ class YamlParser { const nextIndent = this.lexer.getIndentation(); if (nextIndent > currentIndent) { - // Nested content - determine if it's an object or array + // Nested content - determine if it's an object, array, or just a scalar value this.lexer.skipWhitespace(); if (this.lexer.getCurrentChar() === '-') { value = this.parseBlockArray(nextIndent); } else { - value = this.parseBlockObject(nextIndent); + // Check if this looks like an object property (has a colon) + const currentLine = this.lexer.getCurrentLineText(); + const currentPos = this.lexer.getCurrentCharNumber(); + const remainingLine = currentLine.substring(currentPos); + + if (remainingLine.includes(':') && !remainingLine.trim().startsWith('#')) { + // It's a nested object + value = this.parseBlockObject(nextIndent); + } else { + // It's just a scalar value on the next line + value = this.parseValue(); + } } } else if (!fromCurrentPosition && nextIndent === currentIndent) { // Same indentation level - check if it's an array item diff --git a/src/vs/base/node/id.ts b/src/vs/base/node/id.ts index c74fcf4ae61..b37534ac0bc 100644 --- a/src/vs/base/node/id.ts +++ b/src/vs/base/node/id.ts @@ -78,7 +78,7 @@ export const virtualMachineHint: { value(): number } = new class { }; let machineId: Promise; -export async function getMachineId(errorLogger: (error: any) => void): Promise { +export async function getMachineId(errorLogger: (error: Error) => void): Promise { if (!machineId) { machineId = (async () => { const id = await getMacMachineId(errorLogger); @@ -90,7 +90,7 @@ export async function getMachineId(errorLogger: (error: any) => void): Promise void): Promise { +async function getMacMachineId(errorLogger: (error: Error) => void): Promise { try { const crypto = await import('crypto'); const macAddress = getMac(); @@ -102,7 +102,7 @@ async function getMacMachineId(errorLogger: (error: any) => void): Promise void): Promise { +export async function getSqmMachineId(errorLogger: (error: Error) => void): Promise { if (isWindows) { const Registry = await import('@vscode/windows-registry'); try { @@ -115,7 +115,7 @@ export async function getSqmMachineId(errorLogger: (error: any) => void): Promis return ''; } -export async function getDevDeviceId(errorLogger: (error: any) => void): Promise { +export async function getDevDeviceId(errorLogger: (error: Error) => void): Promise { try { const deviceIdPackage = await import('@vscode/deviceid'); const id = await deviceIdPackage.getDeviceId(); diff --git a/src/vs/base/node/osDisplayProtocolInfo.ts b/src/vs/base/node/osDisplayProtocolInfo.ts index 2dbc302e02a..41ed6b7eb0a 100644 --- a/src/vs/base/node/osDisplayProtocolInfo.ts +++ b/src/vs/base/node/osDisplayProtocolInfo.ts @@ -18,7 +18,7 @@ const enum DisplayProtocolType { Unknown = 'unknown' } -export async function getDisplayProtocol(errorLogger: (error: any) => void): Promise { +export async function getDisplayProtocol(errorLogger: (error: string | Error) => void): Promise { const xdgSessionType = env[XDG_SESSION_TYPE]; if (xdgSessionType) { diff --git a/src/vs/base/node/osReleaseInfo.ts b/src/vs/base/node/osReleaseInfo.ts index 8c34493531f..890bc254e16 100644 --- a/src/vs/base/node/osReleaseInfo.ts +++ b/src/vs/base/node/osReleaseInfo.ts @@ -13,7 +13,7 @@ type ReleaseInfo = { version_id?: string; }; -export async function getOSReleaseInfo(errorLogger: (error: any) => void): Promise { +export async function getOSReleaseInfo(errorLogger: (error: string | Error) => void): Promise { if (Platform.isMacintosh || Platform.isWindows) { return; } diff --git a/src/vs/base/node/pfs.ts b/src/vs/base/node/pfs.ts index e13b27372fc..55251cf572a 100644 --- a/src/vs/base/node/pfs.ts +++ b/src/vs/base/node/pfs.ts @@ -107,9 +107,9 @@ async function readdir(path: string, options?: { withFileTypes: true }): Promise try { return await doReaddir(path, options); } catch (error) { - // TODO@bpasero workaround for #252361 that should be removed - // once the upstream issue in node.js is resolved. Adds a trailing - // dot to a root drive letter path (G:\ => G:\.) as a workaround. + // Workaround for #252361 that should be removed once the upstream issue + // in node.js is resolved. Adds a trailing dot to a root drive letter path + // (G:\ => G:\.) as a workaround. if (error.code === 'ENOENT' && isWindows && isRootOrDriveLetter(path)) { try { return await doReaddir(`${path}.`, options); diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index ca1b94e5590..ed474e121e1 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -21,7 +21,7 @@ export type ErrorCallback = (error?: any) => void; export type ProgressCallback = (progress: T) => void; -export function getWindowsShell(env = processCommon.env as Platform.IProcessEnvironment): string { +export function getWindowsShell(env = processCommon.env): string { return env['comspec'] || 'cmd.exe'; } @@ -83,7 +83,7 @@ async function fileExistsDefault(path: string): Promise { return false; } -export async function findExecutable(command: string, cwd?: string, paths?: string[], env: Platform.IProcessEnvironment = processCommon.env as Platform.IProcessEnvironment, fileExists: (path: string) => Promise = fileExistsDefault): Promise { +export async function findExecutable(command: string, cwd?: string, paths?: string[], env: Platform.IProcessEnvironment = processCommon.env, fileExists: (path: string) => Promise = fileExistsDefault): Promise { // If we have an absolute path then we take it. if (path.isAbsolute(command)) { return await fileExists(command) ? command : undefined; diff --git a/src/vs/base/parts/ipc/common/ipc.ts b/src/vs/base/parts/ipc/common/ipc.ts index 1bdee44e9af..59a4f9f1d99 100644 --- a/src/vs/base/parts/ipc/common/ipc.ts +++ b/src/vs/base/parts/ipc/common/ipc.ts @@ -334,7 +334,7 @@ export class ChannelServer implements IChannelServer(); - constructor(private protocol: IMessagePassingProtocol, private ctx: TContext, private logger: IIPCLogger | null = null, private timeoutDelay: number = 1000) { + constructor(private protocol: IMessagePassingProtocol, private ctx: TContext, private logger: IIPCLogger | null = null, private timeoutDelay = 1000) { this.protocolListener = this.protocol.onMessage(msg => this.onRawMessage(msg)); this.sendResponse({ type: ResponseType.Initialize }); } @@ -532,11 +532,11 @@ export interface IIPCLogger { export class ChannelClient implements IChannelClient, IDisposable { - private isDisposed: boolean = false; + private isDisposed = false; private state: State = State.Uninitialized; private activeRequests = new Set(); private handlers = new Map(); - private lastRequestId: number = 0; + private lastRequestId = 0; private protocolListener: IDisposable | null; private logger: IIPCLogger | null; @@ -995,7 +995,7 @@ export class IPCClient implements IChannelClient, IChannelSer } getChannel(channelName: string): T { - return this.channelClient.getChannel(channelName) as T; + return this.channelClient.getChannel(channelName); } registerChannel(channelName: string, channel: IServerChannel): void { diff --git a/src/vs/base/parts/ipc/electron-main/ipcMain.ts b/src/vs/base/parts/ipc/electron-main/ipcMain.ts index 0f8985406a6..ace40529015 100644 --- a/src/vs/base/parts/ipc/electron-main/ipcMain.ts +++ b/src/vs/base/parts/ipc/electron-main/ipcMain.ts @@ -104,7 +104,7 @@ class ValidatedIpcMain implements Event.NodeEventEmitter { } private validateEvent(channel: string, event: electron.IpcMainEvent | electron.IpcMainInvokeEvent): boolean { - if (!channel || !channel.startsWith('vscode:')) { + if (!channel?.startsWith('vscode:')) { onUnexpectedError(`Refused to handle ipcMain event for channel '${channel}' because the channel is unknown.`); return false; // unexpected channel } diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts index e375c62d979..e58f678f986 100644 --- a/src/vs/base/parts/ipc/node/ipc.net.ts +++ b/src/vs/base/parts/ipc/node/ipc.net.ts @@ -104,7 +104,7 @@ export class NodeSocket implements ISocket { SocketDiagnostics.traceSocketEvent(this.socket, this.debugLabel, type, data); } - constructor(socket: Socket, debugLabel: string = '') { + constructor(socket: Socket, debugLabel = '') { this.debugLabel = debugLabel; this.socket = socket; this.traceSocketEvent(SocketDiagnosticsEventType.Created, { type: 'NodeSocket' }); @@ -295,7 +295,7 @@ export class WebSocketNodeSocket extends Disposable implements ISocket, ISocketT private readonly _incomingData: ChunkStream; private readonly _onData = this._register(new Emitter()); private readonly _onClose = this._register(new Emitter()); - private _isEnded: boolean = false; + private _isEnded = false; private readonly _state = { state: ReadState.PeekHeader, @@ -837,7 +837,7 @@ function unmask(buffer: VSBuffer, mask: number): void { // Read this before there's any chance it is overwritten // Related to https://github.com/microsoft/vscode/issues/30624 -export const XDG_RUNTIME_DIR = process.env['XDG_RUNTIME_DIR']; +export const XDG_RUNTIME_DIR = process.env['XDG_RUNTIME_DIR']; const safeIpcPathLengths: { [platform: number]: number } = { [Platform.Linux]: 107, diff --git a/src/vs/base/parts/request/test/electron-main/request.test.ts b/src/vs/base/parts/request/test/electron-main/request.test.ts index 0eea7d9a2fb..e653570c5fc 100644 --- a/src/vs/base/parts/request/test/electron-main/request.test.ts +++ b/src/vs/base/parts/request/test/electron-main/request.test.ts @@ -10,6 +10,7 @@ import { CancellationToken, CancellationTokenSource } from '../../../../common/c import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../test/common/utils.js'; import { request } from '../../common/requestImpl.js'; import { streamToBuffer } from '../../../../common/buffer.js'; +import { runWithFakedTimers } from '../../../../test/common/timeTravelScheduler.js'; suite('Request', () => { @@ -83,32 +84,36 @@ suite('Request', () => { }); test('timeout', async () => { - try { - await request({ - type: 'GET', - url: `http://127.0.0.1:${port}/noreply`, - timeout: 123, - }, CancellationToken.None); - assert.fail('Should fail with timeout'); - } catch (err) { - assert.strictEqual(err.message, 'Fetch timeout: 123ms'); - } + return runWithFakedTimers({}, async () => { + try { + await request({ + type: 'GET', + url: `http://127.0.0.1:${port}/noreply`, + timeout: 123, + }, CancellationToken.None); + assert.fail('Should fail with timeout'); + } catch (err) { + assert.strictEqual(err.message, 'Fetch timeout: 123ms'); + } + }); }); test('cancel', async () => { - try { - const source = new CancellationTokenSource(); - const res = request({ - type: 'GET', - url: `http://127.0.0.1:${port}/noreply`, - }, source.token); - await new Promise(resolve => setTimeout(resolve, 100)); - source.cancel(); - await res; - assert.fail('Should fail with cancellation'); - } catch (err) { - assert.strictEqual(err.message, 'Canceled'); - } + return runWithFakedTimers({}, async () => { + try { + const source = new CancellationTokenSource(); + const res = request({ + type: 'GET', + url: `http://127.0.0.1:${port}/noreply`, + }, source.token); + await new Promise(resolve => setTimeout(resolve, 100)); + source.cancel(); + await res; + assert.fail('Should fail with cancellation'); + } catch (err) { + assert.strictEqual(err.message, 'Canceled'); + } + }); }); ensureNoDisposablesAreLeakedInTestSuite(); diff --git a/src/vs/base/parts/sandbox/electron-browser/preload-aux.ts b/src/vs/base/parts/sandbox/electron-browser/preload-aux.ts index c8e238ed112..0299893e6f9 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload-aux.ts +++ b/src/vs/base/parts/sandbox/electron-browser/preload-aux.ts @@ -8,7 +8,7 @@ const { ipcRenderer, webFrame, contextBridge } = require('electron'); function validateIPC(channel: string): true | never { - if (!channel || !channel.startsWith('vscode:')) { + if (!channel?.startsWith('vscode:')) { throw new Error(`Unsupported event IPC channel '${channel}'`); } diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.ts b/src/vs/base/parts/sandbox/electron-browser/preload.ts index 74b908e7523..b3b9a17a6ff 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.ts +++ b/src/vs/base/parts/sandbox/electron-browser/preload.ts @@ -14,7 +14,7 @@ //#region Utilities function validateIPC(channel: string): true | never { - if (!channel || !channel.startsWith('vscode:')) { + if (!channel?.startsWith('vscode:')) { throw new Error(`Unsupported event IPC channel '${channel}'`); } diff --git a/src/vs/base/parts/storage/node/storage.ts b/src/vs/base/parts/storage/node/storage.ts index 1c685bb324a..edd322f692b 100644 --- a/src/vs/base/parts/storage/node/storage.ts +++ b/src/vs/base/parts/storage/node/storage.ts @@ -258,7 +258,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase { return integrity; } - private async connect(path: string, retryOnBusy: boolean = true): Promise { + private async connect(path: string, retryOnBusy = true): Promise { this.logger.trace(`[storage ${this.name}] open(${path}, retryOnBusy: ${retryOnBusy})`); try { diff --git a/src/vs/base/test/browser/highlightedLabel.test.ts b/src/vs/base/test/browser/highlightedLabel.test.ts index 27ca48e4906..66906743633 100644 --- a/src/vs/base/test/browser/highlightedLabel.test.ts +++ b/src/vs/base/test/browser/highlightedLabel.test.ts @@ -11,7 +11,7 @@ suite('HighlightedLabel', () => { let label: HighlightedLabel; setup(() => { - label = new HighlightedLabel(document.createElement('div'), { supportIcons: true }); + label = new HighlightedLabel(document.createElement('div')); }); test('empty label', function () { diff --git a/src/vs/base/test/browser/markdownRenderer.test.ts b/src/vs/base/test/browser/markdownRenderer.test.ts index 072d1871b29..5a02b84c7dc 100644 --- a/src/vs/base/test/browser/markdownRenderer.test.ts +++ b/src/vs/base/test/browser/markdownRenderer.test.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* eslint-disable no-restricted-syntax */ + import assert from 'assert'; import { fillInIncompleteTokens, renderMarkdown, renderAsPlaintext } from '../../browser/markdownRenderer.js'; import { IMarkdownString, MarkdownString } from '../../common/htmlContent.js'; @@ -220,6 +222,36 @@ suite('MarkdownRenderer', () => { }); }); + suite('Alerts', () => { + test('Should render alert with data-severity attribute and icon', () => { + const markdown = new MarkdownString('> [!NOTE]\n> This is a note alert', { supportAlertSyntax: true }); + const result = store.add(renderMarkdown(markdown)).element; + + const blockquote = result.querySelector('blockquote[data-severity="note"]'); + assert.ok(blockquote, 'Should have blockquote with data-severity="note"'); + assert.ok(result.innerHTML.includes('This is a note alert'), 'Should contain alert text'); + assert.ok(result.innerHTML.includes('codicon-info'), 'Should contain info icon'); + }); + + test('Should render regular blockquote when supportAlertSyntax is disabled', () => { + const markdown = new MarkdownString('> [!NOTE]\n> This should be a regular blockquote'); + const result = store.add(renderMarkdown(markdown)).element; + + const blockquote = result.querySelector('blockquote'); + assert.ok(blockquote, 'Should have blockquote'); + assert.strictEqual(blockquote?.getAttribute('data-severity'), null, 'Should not have data-severity attribute'); + assert.ok(result.innerHTML.includes('[!NOTE]'), 'Should contain literal [!NOTE] text'); + }); + + test('Should not transform blockquotes without alert syntax', () => { + const markdown = new MarkdownString('> This is a regular blockquote', { supportAlertSyntax: true }); + const result = store.add(renderMarkdown(markdown)).element; + + const blockquote = result.querySelector('blockquote'); + assert.strictEqual(blockquote?.getAttribute('data-severity'), null, 'Should not have data-severity attribute'); + }); + }); + test('npm Hover Run Script not working #90855', function () { const md: IMarkdownString = JSON.parse('{"value":"[Run Script](command:npm.runScriptFromHover?%7B%22documentUri%22%3A%7B%22%24mid%22%3A1%2C%22fsPath%22%3A%22c%3A%5C%5CUsers%5C%5Cjrieken%5C%5CCode%5C%5C_sample%5C%5Cfoo%5C%5Cpackage.json%22%2C%22_sep%22%3A1%2C%22external%22%3A%22file%3A%2F%2F%2Fc%253A%2FUsers%2Fjrieken%2FCode%2F_sample%2Ffoo%2Fpackage.json%22%2C%22path%22%3A%22%2Fc%3A%2FUsers%2Fjrieken%2FCode%2F_sample%2Ffoo%2Fpackage.json%22%2C%22scheme%22%3A%22file%22%7D%2C%22script%22%3A%22echo%22%7D \\"Run the script as a task\\")","supportThemeIcons":false,"isTrusted":true,"uris":{"__uri_e49443":{"$mid":1,"fsPath":"c:\\\\Users\\\\jrieken\\\\Code\\\\_sample\\\\foo\\\\package.json","_sep":1,"external":"file:///c%3A/Users/jrieken/Code/_sample/foo/package.json","path":"/c:/Users/jrieken/Code/_sample/foo/package.json","scheme":"file"},"command:npm.runScriptFromHover?%7B%22documentUri%22%3A%7B%22%24mid%22%3A1%2C%22fsPath%22%3A%22c%3A%5C%5CUsers%5C%5Cjrieken%5C%5CCode%5C%5C_sample%5C%5Cfoo%5C%5Cpackage.json%22%2C%22_sep%22%3A1%2C%22external%22%3A%22file%3A%2F%2F%2Fc%253A%2FUsers%2Fjrieken%2FCode%2F_sample%2Ffoo%2Fpackage.json%22%2C%22path%22%3A%22%2Fc%3A%2FUsers%2Fjrieken%2FCode%2F_sample%2Ffoo%2Fpackage.json%22%2C%22scheme%22%3A%22file%22%7D%2C%22script%22%3A%22echo%22%7D":{"$mid":1,"path":"npm.runScriptFromHover","scheme":"command","query":"{\\"documentUri\\":\\"__uri_e49443\\",\\"script\\":\\"echo\\"}"}}}'); @@ -267,14 +299,14 @@ suite('MarkdownRenderer', () => { }); test('Should support relative links if baseurl is set', () => { - const md = new MarkdownString(`[text](./foo) bar`, { + const md = new MarkdownString(`[text](./foo) bar `, { isTrusted: true, supportHtml: true, }); md.baseUri = URI.parse('https://example.com/path/'); const result = store.add(renderMarkdown(md)).element; - assert.strictEqual(result.innerHTML, `

text bar

`); + assert.strictEqual(result.innerHTML, `

text bar

`); }); suite('PlaintextMarkdownRender', () => { diff --git a/src/vs/base/test/browser/ui/splitview/splitview.test.ts b/src/vs/base/test/browser/ui/splitview/splitview.test.ts index 76d7639b04c..e470e11a3f1 100644 --- a/src/vs/base/test/browser/ui/splitview/splitview.test.ts +++ b/src/vs/base/test/browser/ui/splitview/splitview.test.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* eslint-disable no-restricted-syntax */ + import assert from 'assert'; import { Sash, SashState } from '../../../../browser/ui/sash/sash.js'; import { IView, LayoutPriority, Sizing, SplitView } from '../../../../browser/ui/splitview/splitview.js'; diff --git a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts index 4eb5e2b7e28..25840582aab 100644 --- a/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/asyncDataTree.test.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* eslint-disable no-restricted-syntax */ + import assert from 'assert'; import { IIdentityProvider, IListVirtualDelegate } from '../../../../browser/ui/list/list.js'; import { AsyncDataTree, CompressibleAsyncDataTree, ITreeCompressionDelegate } from '../../../../browser/ui/tree/asyncDataTree.js'; diff --git a/src/vs/base/test/browser/ui/tree/objectTree.test.ts b/src/vs/base/test/browser/ui/tree/objectTree.test.ts index aa11fbe6036..b3813240e60 100644 --- a/src/vs/base/test/browser/ui/tree/objectTree.test.ts +++ b/src/vs/base/test/browser/ui/tree/objectTree.test.ts @@ -3,6 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +/* eslint-disable no-restricted-syntax */ + import assert from 'assert'; import { IIdentityProvider, IListVirtualDelegate } from '../../../../browser/ui/list/list.js'; import { ICompressedTreeNode } from '../../../../browser/ui/tree/compressedObjectTreeModel.js'; diff --git a/src/vs/base/test/common/async.test.ts b/src/vs/base/test/common/async.test.ts index c0048417319..c011d89aa7c 100644 --- a/src/vs/base/test/common/async.test.ts +++ b/src/vs/base/test/common/async.test.ts @@ -5,7 +5,7 @@ import assert from 'assert'; import * as async from '../../common/async.js'; -import * as MicrotaskDelay from "../../common/symbols.js"; +import * as MicrotaskDelay from '../../common/symbols.js'; import { CancellationToken, CancellationTokenSource } from '../../common/cancellation.js'; import { isCancellationError } from '../../common/errors.js'; import { Event } from '../../common/event.js'; @@ -2181,6 +2181,137 @@ suite('Async', () => { { id: 3, name: 'third' } ]); }); + + test('tee - both iterators receive all values', async () => { + // TODO: Implementation bug - executors don't await start(), causing producers to finalize early + async function* sourceGenerator() { + yield 1; + yield 2; + yield 3; + yield 4; + yield 5; + } + + const [iter1, iter2] = async.AsyncIterableProducer.tee(sourceGenerator()); + + const result1: number[] = []; + const result2: number[] = []; + + // Consume both iterables concurrently + await Promise.all([ + (async () => { + for await (const item of iter1) { + result1.push(item); + } + })(), + (async () => { + for await (const item of iter2) { + result2.push(item); + } + })() + ]); + + assert.deepStrictEqual(result1, [1, 2, 3, 4, 5]); + assert.deepStrictEqual(result2, [1, 2, 3, 4, 5]); + }); + + test('tee - sequential consumption', async () => { + // TODO: Implementation bug - executors don't await start(), causing producers to finalize early + const source = new async.AsyncIterableProducer(emitter => { + emitter.emitMany([1, 2, 3]); + }); + + const [iter1, iter2] = async.AsyncIterableProducer.tee(source); + + // Consume first iterator completely + const result1: number[] = []; + for await (const item of iter1) { + result1.push(item); + } + + // Then consume second iterator + const result2: number[] = []; + for await (const item of iter2) { + result2.push(item); + } + + assert.deepStrictEqual(result1, [1, 2, 3]); + assert.deepStrictEqual(result2, [1, 2, 3]); + }); + + test.skip('tee - empty source', async () => { + // TODO: Implementation bug - executors don't await start(), causing producers to finalize early + const source = new async.AsyncIterableProducer(emitter => { + // Emit nothing + }); + + const [iter1, iter2] = async.AsyncIterableProducer.tee(source); + + const result1: number[] = []; + const result2: number[] = []; + + await Promise.all([ + (async () => { + for await (const item of iter1) { + result1.push(item); + } + })(), + (async () => { + for await (const item of iter2) { + result2.push(item); + } + })() + ]); + + assert.deepStrictEqual(result1, []); + assert.deepStrictEqual(result2, []); + }); + + test.skip('tee - handles errors in source', async () => { + // TODO: Implementation bug - executors don't await start(), causing producers to finalize early + const expectedError = new Error('source error'); + const source = new async.AsyncIterableProducer(async emitter => { + emitter.emitOne(1); + emitter.emitOne(2); + throw expectedError; + }); + + const [iter1, iter2] = async.AsyncIterableProducer.tee(source); + + let error1: Error | undefined; + let error2: Error | undefined; + const result1: number[] = []; + const result2: number[] = []; + + await Promise.all([ + (async () => { + try { + for await (const item of iter1) { + result1.push(item); + } + } catch (e) { + error1 = e as Error; + } + })(), + (async () => { + try { + for await (const item of iter2) { + result2.push(item); + } + } catch (e) { + error2 = e as Error; + } + })() + ]); + + // Both iterators should have received the same values before error + assert.deepStrictEqual(result1, [1, 2]); + assert.deepStrictEqual(result2, [1, 2]); + + // Both should have received the error + assert.strictEqual(error1, expectedError); + assert.strictEqual(error2, expectedError); + }); }); suite('AsyncReader', () => { @@ -2391,12 +2522,14 @@ suite('Async', () => { }); test('peekTimeout - timeout occurs', async () => { - const reader = new async.AsyncReader(createDelayedAsyncIterator([1, 2, 3], 50)); + return runWithFakedTimers({}, async () => { + const reader = new async.AsyncReader(createDelayedAsyncIterator([1, 2, 3], 50)); - const result = await reader.peekTimeout(10); - assert.strictEqual(result, undefined); + const result = await reader.peekTimeout(10); + assert.strictEqual(result, undefined); - await reader.consumeToEnd(); + await reader.consumeToEnd(); + }); }); test('peekTimeout - empty iterator', async () => { diff --git a/src/vs/base/test/common/buffer.test.ts b/src/vs/base/test/common/buffer.test.ts index f4d9c5a04e4..9109d4cdb1b 100644 --- a/src/vs/base/test/common/buffer.test.ts +++ b/src/vs/base/test/common/buffer.test.ts @@ -19,6 +19,20 @@ suite('Buffer', () => { assert.deepStrictEqual(buffer.toString(), 'hi'); }); + test('issue #251527 - VSBuffer#toString preserves BOM character in filenames', () => { + // BOM character (U+FEFF) is a zero-width character that was being stripped + // when deserializing messages in the IPC layer. This test verifies that + // the BOM character is preserved when using VSBuffer.toString(). + const bomChar = '\uFEFF'; + const filename = `${bomChar}c.txt`; + const buffer = VSBuffer.fromString(filename); + const result = buffer.toString(); + + // Verify the BOM character is preserved + assert.strictEqual(result, filename); + assert.strictEqual(result.charCodeAt(0), 0xFEFF); + }); + test('bufferToReadable / readableToBuffer', () => { const content = 'Hello World'; const readable = bufferToReadable(VSBuffer.fromString(content)); diff --git a/src/vs/base/test/common/collections.test.ts b/src/vs/base/test/common/collections.test.ts index fbf8f6e77b3..5bd2206d538 100644 --- a/src/vs/base/test/common/collections.test.ts +++ b/src/vs/base/test/common/collections.test.ts @@ -24,12 +24,12 @@ suite('Collections', () => { const grouped = collections.groupBy(source, x => x.key); // Group 1 - assert.strictEqual(grouped[group1].length, 2); + assert.strictEqual(grouped[group1]?.length, 2); assert.strictEqual(grouped[group1][0].value, value1); assert.strictEqual(grouped[group1][1].value, value2); // Group 2 - assert.strictEqual(grouped[group2].length, 1); + assert.strictEqual(grouped[group2]?.length, 1); assert.strictEqual(grouped[group2][0].value, value3); }); diff --git a/src/vs/base/test/common/envfile.test.ts b/src/vs/base/test/common/envfile.test.ts index 753a8c6b534..e8713e25856 100644 --- a/src/vs/base/test/common/envfile.test.ts +++ b/src/vs/base/test/common/envfile.test.ts @@ -93,14 +93,14 @@ suite('parseEnvFile', () => { assert.strictEqual(parsed.get('DOUBLE_QUOTES_SPACED'), ' double quotes '); assert.strictEqual(parsed.get('DOUBLE_QUOTES_INSIDE_SINGLE'), 'double "quotes" work inside single quotes'); assert.strictEqual(parsed.get('DOUBLE_QUOTES_WITH_NO_SPACE_BRACKET'), '{ port: $MONGOLAB_PORT}'); - assert.strictEqual(parsed.get('SINGLE_QUOTES_INSIDE_DOUBLE'), "single 'quotes' work inside double quotes"); + assert.strictEqual(parsed.get('SINGLE_QUOTES_INSIDE_DOUBLE'), `single 'quotes' work inside double quotes`); assert.strictEqual(parsed.get('BACKTICKS_INSIDE_SINGLE'), '`backticks` work inside single quotes'); assert.strictEqual(parsed.get('BACKTICKS_INSIDE_DOUBLE'), '`backticks` work inside double quotes'); assert.strictEqual(parsed.get('BACKTICKS'), 'backticks'); assert.strictEqual(parsed.get('BACKTICKS_SPACED'), ' backticks '); assert.strictEqual(parsed.get('DOUBLE_QUOTES_INSIDE_BACKTICKS'), 'double "quotes" work inside backticks'); - assert.strictEqual(parsed.get('SINGLE_QUOTES_INSIDE_BACKTICKS'), "single 'quotes' work inside backticks"); - assert.strictEqual(parsed.get('DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS'), "double \"quotes\" and single 'quotes' work inside backticks"); + assert.strictEqual(parsed.get('SINGLE_QUOTES_INSIDE_BACKTICKS'), `single 'quotes' work inside backticks`); + assert.strictEqual(parsed.get('DOUBLE_AND_SINGLE_QUOTES_INSIDE_BACKTICKS'), `double "quotes" and single 'quotes' work inside backticks`); assert.strictEqual(parsed.get('EXPAND_NEWLINES'), 'expand\nnew\nlines'); assert.strictEqual(parsed.get('DONT_EXPAND_UNQUOTED'), 'dontexpand\\nnewlines'); assert.strictEqual(parsed.get('DONT_EXPAND_SQUOTED'), 'dontexpand\\nnewlines'); diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts index 002bb687f41..f79fa81cdff 100644 --- a/src/vs/base/test/common/event.test.ts +++ b/src/vs/base/test/common/event.test.ts @@ -464,6 +464,111 @@ suite('Event', function () { }); }); + suite('Event.toPromise', () => { + class DisposableStoreWithSize extends DisposableStore { + public size = 0; + public override add(o: T): T { + this.size++; + return super.add(o); + } + + public override delete(o: T): void { + this.size--; + return super.delete(o); + } + } + test('resolves on first event', async () => { + const emitter = ds.add(new Emitter()); + const promise = Event.toPromise(emitter.event); + + emitter.fire(42); + const result = await promise; + + assert.strictEqual(result, 42); + }); + + test('disposes listener after resolution', async () => { + const emitter = ds.add(new Emitter()); + const promise = Event.toPromise(emitter.event); + + emitter.fire(1); + await promise; + + // Listener should be disposed, firing again should not affect anything + emitter.fire(2); + assert.ok(true); // No errors + }); + + test('adds to DisposableStore', async () => { + const emitter = ds.add(new Emitter()); + const store = ds.add(new DisposableStoreWithSize()); + const promise = Event.toPromise(emitter.event, store); + + assert.strictEqual(store.size, 1); + + emitter.fire(42); + await promise; + + // Should be removed from store after resolution + assert.strictEqual(store.size, 0); + }); + + test('adds to disposables array', async () => { + const emitter = ds.add(new Emitter()); + const disposables: IDisposable[] = []; + const promise = Event.toPromise(emitter.event, disposables); + + assert.strictEqual(disposables.length, 1); + + emitter.fire(42); + await promise; + + // Should be removed from array after resolution + assert.strictEqual(disposables.length, 0); + }); + + test('cancel removes from DisposableStore', () => { + const emitter = ds.add(new Emitter()); + const store = ds.add(new DisposableStoreWithSize()); + const promise = Event.toPromise(emitter.event, store); + + assert.strictEqual(store.size, 1); + + promise.cancel(); + + // Should be removed from store after cancellation + assert.strictEqual(store.size, 0); + }); + + test('cancel removes from disposables array', () => { + const emitter = ds.add(new Emitter()); + const disposables: IDisposable[] = []; + const promise = Event.toPromise(emitter.event, disposables); + + assert.strictEqual(disposables.length, 1); + + promise.cancel(); + + // Should be removed from array after cancellation + assert.strictEqual(disposables.length, 0); + }); + + test('cancel does not resolve promise', async () => { + const emitter = ds.add(new Emitter()); + const promise = Event.toPromise(emitter.event); + + promise.cancel(); + emitter.fire(42); + + // Promise should not resolve after cancellation + let resolved = false; + promise.then(() => resolved = true); + + await timeout(10); + assert.strictEqual(resolved, false); + }); + }); + test('Microtask Emitter', (done) => { let count = 0; assert.strictEqual(count, 0); diff --git a/src/vs/base/test/common/filters.perf.data.d.ts b/src/vs/base/test/common/filters.perf.data.d.ts index b2ef6866955..3393c4f5a02 100644 --- a/src/vs/base/test/common/filters.perf.data.d.ts +++ b/src/vs/base/test/common/filters.perf.data.d.ts @@ -2,4 +2,4 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -export const data: string[]; \ No newline at end of file +export declare const data: string[]; diff --git a/src/vs/base/test/common/filters.test.ts b/src/vs/base/test/common/filters.test.ts index 5d6643d2378..6aeaefd59fb 100644 --- a/src/vs/base/test/common/filters.test.ts +++ b/src/vs/base/test/common/filters.test.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; -import { anyScore, createMatches, fuzzyScore, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer, IFilter, IMatch, matchesCamelCase, matchesContiguousSubString, matchesPrefix, matchesStrictPrefix, matchesSubString, matchesWords, or } from '../../common/filters.js'; +import { anyScore, createMatches, fuzzyScore, fuzzyScoreGraceful, fuzzyScoreGracefulAggressive, FuzzyScorer, IFilter, IMatch, matchesBaseContiguousSubString, matchesCamelCase, matchesContiguousSubString, matchesPrefix, matchesStrictPrefix, matchesSubString, matchesWords, or } from '../../common/filters.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js'; function filterOk(filter: IFilter, word: string, wordToMatchAgainst: string, highlights?: { start: number; end: number }[]) { @@ -158,6 +158,30 @@ suite('Filters', () => { ]); }); + test('matchesBaseContiguousSubString', () => { + filterOk(matchesBaseContiguousSubString, 'cela', 'cancelAnimationFrame()', [ + { start: 3, end: 7 } + ]); + filterOk(matchesBaseContiguousSubString, 'cafe', 'café', [ + { start: 0, end: 4 } + ]); + filterOk(matchesBaseContiguousSubString, 'cafe', 'caféBar', [ + { start: 0, end: 4 } + ]); + filterOk(matchesBaseContiguousSubString, 'resume', 'résumé', [ + { start: 0, end: 6 } + ]); + filterOk(matchesBaseContiguousSubString, 'naïve', 'naïve', [ + { start: 0, end: 5 } + ]); + filterOk(matchesBaseContiguousSubString, 'naive', 'naïve', [ + { start: 0, end: 5 } + ]); + filterOk(matchesBaseContiguousSubString, 'aeou', 'àéöü', [ + { start: 0, end: 4 } + ]); + }); + test('matchesSubString', () => { filterOk(matchesSubString, 'cmm', 'cancelAnimationFrame()', [ { start: 0, end: 1 }, diff --git a/src/vs/base/test/common/glob.test.ts b/src/vs/base/test/common/glob.test.ts index 3658ec22419..3021b924988 100644 --- a/src/vs/base/test/common/glob.test.ts +++ b/src/vs/base/test/common/glob.test.ts @@ -64,14 +64,14 @@ suite('Glob', () => { // console.profileEnd(); // }); - function assertGlobMatch(pattern: string | glob.IRelativePattern, input: string) { - assert(glob.match(pattern, input), `${JSON.stringify(pattern)} should match ${input}`); - assert(glob.match(pattern, nativeSep(input)), `${pattern} should match ${nativeSep(input)}`); + function assertGlobMatch(pattern: string | glob.IRelativePattern, input: string, ignoreCase?: boolean) { + assert(glob.match(pattern, input, { ignoreCase }), `${JSON.stringify(pattern)} should match ${input}`); + assert(glob.match(pattern, nativeSep(input), { ignoreCase }), `${pattern} should match ${nativeSep(input)}`); } - function assertNoGlobMatch(pattern: string | glob.IRelativePattern, input: string) { - assert(!glob.match(pattern, input), `${pattern} should not match ${input}`); - assert(!glob.match(pattern, nativeSep(input)), `${pattern} should not match ${nativeSep(input)}`); + function assertNoGlobMatch(pattern: string | glob.IRelativePattern, input: string, ignoreCase?: boolean) { + assert(!glob.match(pattern, input, { ignoreCase }), `${pattern} should not match ${input}`); + assert(!glob.match(pattern, nativeSep(input), { ignoreCase }), `${pattern} should not match ${nativeSep(input)}`); } test('simple', () => { @@ -480,10 +480,10 @@ suite('Glob', () => { } }; - assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling)); - assert.strictEqual(glob.match(expression, 'test.js', () => false), null); - assert.strictEqual(glob.match(expression, 'test.js', name => name === 'te.ts'), null); - assert.strictEqual(glob.match(expression, 'test.js'), null); + assert.strictEqual('**/*.js', glob.parse(expression)('test.js', undefined, hasSibling)); + assert.strictEqual(glob.parse(expression)('test.js', undefined, () => false), null); + assert.strictEqual(glob.parse(expression)('test.js', undefined, name => name === 'te.ts'), null); + assert.strictEqual(glob.parse(expression)('test.js', undefined), null); expression = { '**/*.js': { @@ -491,7 +491,7 @@ suite('Glob', () => { } }; - assert.strictEqual(glob.match(expression, 'test.js', hasSibling), null); + assert.strictEqual(glob.parse(expression)('test.js', undefined, hasSibling), null); expression = { // eslint-disable-next-line local/code-no-any-casts @@ -499,11 +499,11 @@ suite('Glob', () => { } as any }; - assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling)); + assert.strictEqual('**/*.js', glob.parse(expression)('test.js', undefined, hasSibling)); expression = {}; - assert.strictEqual(glob.match(expression, 'test.js', hasSibling), null); + assert.strictEqual(glob.parse(expression)('test.js', undefined, hasSibling), null); }); test('expression support (multiple)', function () { @@ -519,11 +519,11 @@ suite('Glob', () => { '**/*.bananas': { bananas: true } as any }; - assert.strictEqual('**/*.js', glob.match(expression, 'test.js', hasSibling)); - assert.strictEqual('**/*.as', glob.match(expression, 'test.as', hasSibling)); - assert.strictEqual('**/*.bananas', glob.match(expression, 'test.bananas', hasSibling)); - assert.strictEqual('**/*.bananas', glob.match(expression, 'test.bananas')); - assert.strictEqual(glob.match(expression, 'test.foo', hasSibling), null); + assert.strictEqual('**/*.js', glob.parse(expression)('test.js', undefined, hasSibling)); + assert.strictEqual('**/*.as', glob.parse(expression)('test.as', undefined, hasSibling)); + assert.strictEqual('**/*.bananas', glob.parse(expression)('test.bananas', undefined, hasSibling)); + assert.strictEqual('**/*.bananas', glob.parse(expression)('test.bananas', undefined)); + assert.strictEqual(glob.parse(expression)('test.foo', undefined, hasSibling), null); }); test('brackets', () => { @@ -789,16 +789,16 @@ suite('Glob', () => { const siblings = ['foo.ts', 'foo.js', 'foo', 'bar']; const hasSibling = (name: string) => siblings.indexOf(name) !== -1; - assert.strictEqual(glob.match(expr, 'bar', hasSibling), '**/bar'); - assert.strictEqual(glob.match(expr, 'foo', hasSibling), null); - assert.strictEqual(glob.match(expr, 'foo/bar', hasSibling), '**/bar'); + assert.strictEqual(glob.parse(expr)('bar', undefined, hasSibling), '**/bar'); + assert.strictEqual(glob.parse(expr)('foo', undefined, hasSibling), null); + assert.strictEqual(glob.parse(expr)('foo/bar', undefined, hasSibling), '**/bar'); if (isWindows) { // backslash is a valid file name character on posix - assert.strictEqual(glob.match(expr, 'foo\\bar', hasSibling), '**/bar'); + assert.strictEqual(glob.parse(expr)('foo\\bar', undefined, hasSibling), '**/bar'); } - assert.strictEqual(glob.match(expr, 'foo/foo', hasSibling), null); - assert.strictEqual(glob.match(expr, 'foo.js', hasSibling), '**/*.js'); - assert.strictEqual(glob.match(expr, 'bar.js', hasSibling), null); + assert.strictEqual(glob.parse(expr)('foo/foo', undefined, hasSibling), null); + assert.strictEqual(glob.parse(expr)('foo.js', undefined, hasSibling), '**/*.js'); + assert.strictEqual(glob.parse(expr)('bar.js', undefined, hasSibling), null); }); test('expression with multipe basename globs', function () { @@ -1171,5 +1171,30 @@ suite('Glob', () => { assert.ok(glob.isEmptyPattern(glob.parse({ '**/*.js': false }))); }); + test('caseInsensitiveMatch', () => { + assertNoGlobMatch('PATH/FOO.js', 'path/foo.js'); + assertGlobMatch('PATH/FOO.js', 'path/foo.js', true); + // T1 + assertNoGlobMatch('**/*.JS', 'bar/foo.js'); + assertGlobMatch('**/*.JS', 'bar/foo.js', true); + // T2 + assertNoGlobMatch('**/package', 'bar/Package'); + assertGlobMatch('**/package', 'bar/Package', true); + // T3 + assertNoGlobMatch('{**/*.JS,**/*.TS}', 'bar/foo.ts'); + assertNoGlobMatch('{**/*.JS,**/*.TS}', 'bar/foo.js'); + assertGlobMatch('{**/*.JS,**/*.TS}', 'bar/foo.ts', true); + assertGlobMatch('{**/*.JS,**/*.TS}', 'bar/foo.js', true); + // T4 + assertNoGlobMatch('**/FOO/Bar', 'bar/foo/bar'); + assertGlobMatch('**/FOO/Bar', 'bar/foo/bar', true); + // T5 + assertNoGlobMatch('FOO/Bar', 'foo/bar'); + assertGlobMatch('FOO/Bar', 'foo/bar', true); + // Other + assertNoGlobMatch('some/*/Random/*/Path.FILE', 'some/very/random/unusual/path.file'); + assertGlobMatch('some/*/Random/*/Path.FILE', 'some/very/random/unusual/path.file', true); + }); + ensureNoDisposablesAreLeakedInTestSuite(); }); diff --git a/src/vs/base/test/common/iterativePaging.test.ts b/src/vs/base/test/common/iterativePaging.test.ts new file mode 100644 index 00000000000..395b928a99a --- /dev/null +++ b/src/vs/base/test/common/iterativePaging.test.ts @@ -0,0 +1,300 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert from 'assert'; +import { CancellationToken, CancellationTokenSource } from '../../common/cancellation.js'; +import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js'; +import { IterativePagedModel, IIterativePager, IIterativePage } from '../../common/paging.js'; + +function createTestPager(pageSize: number, maxPages: number): IIterativePager { + let currentPage = 0; + + const createPage = (page: number): IIterativePage => { + const start = page * pageSize; + const items: number[] = []; + for (let i = 0; i < pageSize; i++) { + items.push(start + i); + } + const hasMore = page + 1 < maxPages; + return { items, hasMore }; + }; + + return { + firstPage: createPage(currentPage++), + getNextPage: async (cancellationToken: CancellationToken): Promise> => { + if (currentPage >= maxPages) { + return { items: [], hasMore: false }; + } + return createPage(currentPage++); + } + }; +} + +suite('IterativePagedModel', () => { + + const store = ensureNoDisposablesAreLeakedInTestSuite(); + + test('initial state', () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Initially first page is loaded, so length should be 10 + 1 sentinel + assert.strictEqual(model.length, 11); + assert.strictEqual(model.isResolved(0), true); + assert.strictEqual(model.isResolved(9), true); + assert.strictEqual(model.isResolved(10), false); // sentinel + }); + + test('load first page via sentinel access', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Access an item in the first page (already loaded) + const item = await model.resolve(0, CancellationToken.None); + + assert.strictEqual(item, 0); + assert.strictEqual(model.length, 11); // 10 items + 1 sentinel + assert.strictEqual(model.isResolved(0), true); + assert.strictEqual(model.isResolved(9), true); + assert.strictEqual(model.isResolved(10), false); // sentinel + }); + + test('load multiple pages', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // First page already loaded + assert.strictEqual(model.length, 11); + + // Load second page by accessing its sentinel + await model.resolve(10, CancellationToken.None); + assert.strictEqual(model.length, 21); // 20 items + 1 sentinel + assert.strictEqual(model.get(10), 10); // First item of second page + + // Load third (final) page + await model.resolve(20, CancellationToken.None); + assert.strictEqual(model.length, 30); // 30 items, no sentinel (no more pages) + }); + + test('onDidIncrementLength event fires correctly', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + const lengths: number[] = []; + + store.add(model.onDidIncrementLength((length: number) => lengths.push(length))); + + // Load second page + await model.resolve(10, CancellationToken.None); + + assert.strictEqual(lengths.length, 1); + assert.strictEqual(lengths[0], 21); // 20 items + 1 sentinel + + // Load third page + await model.resolve(20, CancellationToken.None); + + assert.strictEqual(lengths.length, 2); + assert.strictEqual(lengths[1], 30); // 30 items, no sentinel + }); + + test('accessing regular items does not trigger loading', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + const initialLength = model.length; + + // Access items within the loaded range + assert.strictEqual(model.get(5), 5); + assert.strictEqual(model.isResolved(5), true); + + // Length should not change + assert.strictEqual(model.length, initialLength); + }); + + test('reaching end of data removes sentinel', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Load all pages + await model.resolve(10, CancellationToken.None); // Page 2 + await model.resolve(20, CancellationToken.None); // Page 3 (final) + + // After loading all data, there should be no more pages + assert.strictEqual(model.length, 30); // Exactly 30 items, no sentinel + + // Accessing resolved items should work + assert.strictEqual(model.isResolved(29), true); + assert.strictEqual(model.isResolved(30), false); + }); + + test('concurrent access to sentinel only loads once', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Access sentinel concurrently + const [item1, item2, item3] = await Promise.all([ + model.resolve(10, CancellationToken.None), + model.resolve(10, CancellationToken.None), + model.resolve(10, CancellationToken.None) + ]); + + // All should get the same item + assert.strictEqual(item1, 10); + assert.strictEqual(item2, 10); + assert.strictEqual(item3, 10); + assert.strictEqual(model.length, 21); // 20 items + 1 sentinel + }); + + test('empty pager with no items', () => { + const emptyPager: IIterativePager = { + firstPage: { items: [], hasMore: false }, + getNextPage: async () => ({ items: [], hasMore: false }) + }; + const model = store.add(new IterativePagedModel(emptyPager)); + + assert.strictEqual(model.length, 0); + assert.strictEqual(model.isResolved(0), false); + }); + + test('single page pager with no more pages', () => { + const singlePagePager: IIterativePager = { + firstPage: { items: [1, 2, 3], hasMore: false }, + getNextPage: async () => ({ items: [], hasMore: false }) + }; + const model = store.add(new IterativePagedModel(singlePagePager)); + + assert.strictEqual(model.length, 3); // No sentinel + assert.strictEqual(model.isResolved(0), true); + assert.strictEqual(model.isResolved(2), true); + assert.strictEqual(model.isResolved(3), false); + assert.strictEqual(model.get(0), 1); + assert.strictEqual(model.get(2), 3); + }); + + test('accessing item beyond loaded range throws', () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Try to access item beyond current length + assert.throws(() => model.get(15), /Item not resolved yet/); + }); + + test('resolving item beyond all pages throws', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Load all pages + await model.resolve(10, CancellationToken.None); + await model.resolve(20, CancellationToken.None); + + // Try to resolve beyond the last item + await assert.rejects( + async () => model.resolve(30, CancellationToken.None), + /Index out of bounds/ + ); + }); + + test('cancelled token during initial resolve', async () => { + const pager = createTestPager(10, 3); + const model = store.add(new IterativePagedModel(pager)); + + const cts = new CancellationTokenSource(); + cts.cancel(); + + await assert.rejects( + async () => model.resolve(0, cts.token), + /Canceled/ + ); + }); + + test('event fires for each page load', async () => { + const pager = createTestPager(5, 4); + const model = store.add(new IterativePagedModel(pager)); + const lengths: number[] = []; + + store.add(model.onDidIncrementLength((length: number) => lengths.push(length))); + + // Initially has first page (5 items + 1 sentinel = 6) + assert.strictEqual(model.length, 6); + + // Load page 2 + await model.resolve(5, CancellationToken.None); + assert.deepStrictEqual(lengths, [11]); // 10 items + 1 sentinel + + // Load page 3 + await model.resolve(10, CancellationToken.None); + assert.deepStrictEqual(lengths, [11, 16]); // 15 items + 1 sentinel + + // Load page 4 (final) + await model.resolve(15, CancellationToken.None); + assert.deepStrictEqual(lengths, [11, 16, 20]); // 20 items, no sentinel + }); + + test('sequential page loads work correctly', async () => { + const pager = createTestPager(5, 3); + const model = store.add(new IterativePagedModel(pager)); + + // Load pages sequentially + for (let page = 1; page < 3; page++) { + const sentinelIndex = page * 5; + await model.resolve(sentinelIndex, CancellationToken.None); + } + + // Verify all items are accessible + assert.strictEqual(model.length, 15); // 3 pages * 5 items, no sentinel + for (let i = 0; i < 15; i++) { + assert.strictEqual(model.get(i), i); + assert.strictEqual(model.isResolved(i), true); + } + }); + + test('accessing items after loading all pages', async () => { + const pager = createTestPager(10, 2); + const model = store.add(new IterativePagedModel(pager)); + + // Load second page + await model.resolve(10, CancellationToken.None); + + // No sentinel after loading all pages + assert.strictEqual(model.length, 20); + assert.strictEqual(model.isResolved(19), true); + assert.strictEqual(model.isResolved(20), false); + + // All items should be accessible + for (let i = 0; i < 20; i++) { + assert.strictEqual(model.get(i), i); + } + }); + + test('pager with varying page sizes', async () => { + let pageNum = 0; + const varyingPager: IIterativePager = { + firstPage: { items: ['a', 'b', 'c'], hasMore: true }, + getNextPage: async (): Promise> => { + pageNum++; + if (pageNum === 1) { + return { items: ['d', 'e'], hasMore: true }; + } else if (pageNum === 2) { + return { items: ['f', 'g', 'h', 'i'], hasMore: false }; + } + return { items: [], hasMore: false }; + } + }; + + const model = store.add(new IterativePagedModel(varyingPager)); + + assert.strictEqual(model.length, 4); // 3 items + 1 sentinel + + // Load second page (2 items) + await model.resolve(3, CancellationToken.None); + assert.strictEqual(model.length, 6); // 5 items + 1 sentinel + assert.strictEqual(model.get(3), 'd'); + + // Load third page (4 items) + await model.resolve(5, CancellationToken.None); + assert.strictEqual(model.length, 9); // 9 items, no sentinel + assert.strictEqual(model.get(5), 'f'); + assert.strictEqual(model.get(8), 'i'); + }); +}); diff --git a/src/vs/base/test/common/jsonParse.test.ts b/src/vs/base/test/common/jsonParse.test.ts index 83e520fad22..4fab789adee 100644 --- a/src/vs/base/test/common/jsonParse.test.ts +++ b/src/vs/base/test/common/jsonParse.test.ts @@ -12,127 +12,127 @@ suite('JSON Parse', () => { test('Line comment', () => { const content: string = [ - "{", - " \"prop\": 10 // a comment", - "}", + '{', + ' "prop": 10 // a comment', + '}', ].join('\n'); const expected = [ - "{", - " \"prop\": 10 ", - "}", + '{', + ' "prop": 10 ', + '}', ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Line comment - EOF', () => { const content: string = [ - "{", - "}", - "// a comment" + '{', + '}', + '// a comment' ].join('\n'); const expected = [ - "{", - "}", - "" + '{', + '}', + '' ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Line comment - \\r\\n', () => { const content: string = [ - "{", - " \"prop\": 10 // a comment", - "}", + '{', + ' "prop": 10 // a comment', + '}', ].join('\r\n'); const expected = [ - "{", - " \"prop\": 10 ", - "}", + '{', + ' "prop": 10 ', + '}', ].join('\r\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Line comment - EOF - \\r\\n', () => { const content: string = [ - "{", - "}", - "// a comment" + '{', + '}', + '// a comment' ].join('\r\n'); const expected = [ - "{", - "}", - "" + '{', + '}', + '' ].join('\r\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Block comment - single line', () => { const content: string = [ - "{", - " /* before */\"prop\": 10/* after */", - "}", + '{', + ' /* before */"prop": 10/* after */', + '}', ].join('\n'); const expected = [ - "{", - " \"prop\": 10", - "}", + '{', + ' "prop": 10', + '}', ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Block comment - multi line', () => { const content: string = [ - "{", - " /**", - " * Some comment", - " */", - " \"prop\": 10", - "}", + '{', + ' /**', + ' * Some comment', + ' */', + ' "prop": 10', + '}', ].join('\n'); const expected = [ - "{", - " ", - " \"prop\": 10", - "}", + '{', + ' ', + ' "prop": 10', + '}', ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('Block comment - shortest match', () => { - const content = "/* abc */ */"; - const expected = " */"; + const content = '/* abc */ */'; + const expected = ' */'; assert.strictEqual(stripComments(content), expected); }); test('No strings - double quote', () => { const content: string = [ - "{", - " \"/* */\": 10", - "}" + '{', + ' "/* */": 10', + '}' ].join('\n'); const expected: string = [ - "{", - " \"/* */\": 10", - "}" + '{', + ' "/* */": 10', + '}' ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); test('No strings - single quote', () => { const content: string = [ - "{", - " '/* */': 10", - "}" + '{', + ` '/* */': 10`, + '}' ].join('\n'); const expected: string = [ - "{", - " '/* */': 10", - "}" + '{', + ` '/* */': 10`, + '}' ].join('\n'); assert.strictEqual(stripComments(content), expected); }); test('Trailing comma in object', () => { const content: string = [ - "{", + '{', ` "a": 10,`, - "}" + '}' ].join('\n'); const expected: string = [ - "{", + '{', ` "a": 10`, - "}" + '}' ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); @@ -148,16 +148,16 @@ suite('JSON Parse', () => { test('Trailing comma', () => { const content: string = [ - "{", - " \"propA\": 10, // a comment", - " \"propB\": false, // a trailing comma", - "}", + '{', + ' "propA": 10, // a comment', + ' "propB": false, // a trailing comma', + '}', ].join('\n'); const expected = [ - "{", - " \"propA\": 10,", - " \"propB\": false", - "}", + '{', + ' "propA": 10,', + ' "propB": false', + '}', ].join('\n'); assert.deepEqual(parse(content), JSON.parse(expected)); }); @@ -186,9 +186,9 @@ suite('JSON Parse', () => { } `; assert.deepEqual(parse(content), { - "enable-crash-reporter": true, - "crash-reporter-id": "aaaaab31-7453-4506-97d0-93411b2c21c7", - "locale": "en" + 'enable-crash-reporter': true, + 'crash-reporter-id': 'aaaaab31-7453-4506-97d0-93411b2c21c7', + 'locale': 'en' }); }); }); diff --git a/src/vs/base/test/common/jsonSchema.test.ts b/src/vs/base/test/common/jsonSchema.test.ts index da678c56675..aad3607ad37 100644 --- a/src/vs/base/test/common/jsonSchema.test.ts +++ b/src/vs/base/test/common/jsonSchema.test.ts @@ -79,7 +79,7 @@ suite('JSON Schema', () => { } }, $defs: { - "_0": { + '_0': { type: 'object', properties: { c: { @@ -155,7 +155,7 @@ suite('JSON Schema', () => { } }, $defs: { - "_0": { + '_0': { type: 'object', properties: { b: { @@ -270,44 +270,44 @@ suite('JSON Schema', () => { }; const expected: IJSONSchema = { - "type": "object", - "properties": { - "a": { - "type": "object", - "oneOf": [ + 'type': 'object', + 'properties': { + 'a': { + 'type': 'object', + 'oneOf': [ { - "allOf": [ + 'allOf': [ { - "$ref": "#/$defs/_0" + '$ref': '#/$defs/_0' }, { - "$ref": "#/$defs/_1" + '$ref': '#/$defs/_1' } ] }, { - "allOf": [ + 'allOf': [ { - "$ref": "#/$defs/_0" + '$ref': '#/$defs/_0' }, { - "properties": { - "river": { - "type": "string" + 'properties': { + 'river': { + 'type': 'string' } } } ] }, { - "allOf": [ + 'allOf': [ { - "$ref": "#/$defs/_0" + '$ref': '#/$defs/_0' }, { - "properties": { - "mountain": { - "type": "string" + 'properties': { + 'mountain': { + 'type': 'string' } } } @@ -315,30 +315,30 @@ suite('JSON Schema', () => { } ] }, - "b": { - "type": "object", - "properties": { - "street": { - "$ref": "#/$defs/_1" + 'b': { + 'type': 'object', + 'properties': { + 'street': { + '$ref': '#/$defs/_1' } } } }, - "$defs": { - "_0": { - "properties": { - "name": { - "type": "string" + '$defs': { + '_0': { + 'properties': { + 'name': { + 'type': 'string' }, - "description": { - "type": "string" + 'description': { + 'type': 'string' } } }, - "_1": { - "properties": { - "street": { - "type": "string" + '_1': { + 'properties': { + 'street': { + 'type': 'string' } } } @@ -415,7 +415,7 @@ suite('JSON Schema', () => { } }, $defs: { - "_0": { + '_0': { type: 'object', properties: { b: { @@ -428,7 +428,7 @@ suite('JSON Schema', () => { } } }, - "_1": { + '_1': { type: 'object', properties: { d: { @@ -536,13 +536,13 @@ suite('JSON Schema', () => { } }, $defs: { - "_0": { + '_0': { type: 'array', items: { $ref: '#/$defs/_2' } }, - "_1": { + '_1': { type: 'object', properties: { b: { @@ -550,7 +550,7 @@ suite('JSON Schema', () => { } } }, - "_2": { + '_2': { type: 'object', properties: { c: { diff --git a/src/vs/base/test/common/normalization.test.ts b/src/vs/base/test/common/normalization.test.ts index 8ef33d54cc4..651f2b4f6ac 100644 --- a/src/vs/base/test/common/normalization.test.ts +++ b/src/vs/base/test/common/normalization.test.ts @@ -4,64 +4,86 @@ *--------------------------------------------------------------------------------------------*/ import assert from 'assert'; -import { removeAccents } from '../../common/normalization.js'; +import { tryNormalizeToBase } from '../../common/normalization.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js'; suite('Normalization', () => { ensureNoDisposablesAreLeakedInTestSuite(); - test('removeAccents', function () { - assert.strictEqual(removeAccents('joào'), 'joao'); - assert.strictEqual(removeAccents('joáo'), 'joao'); - assert.strictEqual(removeAccents('joâo'), 'joao'); - assert.strictEqual(removeAccents('joäo'), 'joao'); - // assert.strictEqual(strings.removeAccents('joæo'), 'joao'); // not an accent - assert.strictEqual(removeAccents('joão'), 'joao'); - assert.strictEqual(removeAccents('joåo'), 'joao'); - assert.strictEqual(removeAccents('joåo'), 'joao'); - assert.strictEqual(removeAccents('joāo'), 'joao'); + test('tryNormalizeToBase', function () { + assert.strictEqual(tryNormalizeToBase('joào'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joáo'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joâo'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joäo'), 'joao'); + // assert.strictEqual(strings.tryNormalizeToBase('joæo'), 'joao'); // not an accent + assert.strictEqual(tryNormalizeToBase('joão'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joåo'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joåo'), 'joao'); + assert.strictEqual(tryNormalizeToBase('joāo'), 'joao'); - assert.strictEqual(removeAccents('fôo'), 'foo'); - assert.strictEqual(removeAccents('föo'), 'foo'); - assert.strictEqual(removeAccents('fòo'), 'foo'); - assert.strictEqual(removeAccents('fóo'), 'foo'); - // assert.strictEqual(strings.removeAccents('fœo'), 'foo'); - // assert.strictEqual(strings.removeAccents('føo'), 'foo'); - assert.strictEqual(removeAccents('fōo'), 'foo'); - assert.strictEqual(removeAccents('fõo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('fôo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('föo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('fòo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('fóo'), 'foo'); + // assert.strictEqual(strings.tryNormalizeToBase('fœo'), 'foo'); + // assert.strictEqual(strings.tryNormalizeToBase('føo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('fōo'), 'foo'); + assert.strictEqual(tryNormalizeToBase('fõo'), 'foo'); - assert.strictEqual(removeAccents('andrè'), 'andre'); - assert.strictEqual(removeAccents('andré'), 'andre'); - assert.strictEqual(removeAccents('andrê'), 'andre'); - assert.strictEqual(removeAccents('andrë'), 'andre'); - assert.strictEqual(removeAccents('andrē'), 'andre'); - assert.strictEqual(removeAccents('andrė'), 'andre'); - assert.strictEqual(removeAccents('andrę'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrè'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andré'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrê'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrë'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrē'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrė'), 'andre'); + assert.strictEqual(tryNormalizeToBase('andrę'), 'andre'); - assert.strictEqual(removeAccents('hvîc'), 'hvic'); - assert.strictEqual(removeAccents('hvïc'), 'hvic'); - assert.strictEqual(removeAccents('hvíc'), 'hvic'); - assert.strictEqual(removeAccents('hvīc'), 'hvic'); - assert.strictEqual(removeAccents('hvįc'), 'hvic'); - assert.strictEqual(removeAccents('hvìc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvîc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvïc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvíc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvīc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvįc'), 'hvic'); + assert.strictEqual(tryNormalizeToBase('hvìc'), 'hvic'); - assert.strictEqual(removeAccents('ûdo'), 'udo'); - assert.strictEqual(removeAccents('üdo'), 'udo'); - assert.strictEqual(removeAccents('ùdo'), 'udo'); - assert.strictEqual(removeAccents('údo'), 'udo'); - assert.strictEqual(removeAccents('ūdo'), 'udo'); + assert.strictEqual(tryNormalizeToBase('ûdo'), 'udo'); + assert.strictEqual(tryNormalizeToBase('üdo'), 'udo'); + assert.strictEqual(tryNormalizeToBase('ùdo'), 'udo'); + assert.strictEqual(tryNormalizeToBase('údo'), 'udo'); + assert.strictEqual(tryNormalizeToBase('ūdo'), 'udo'); - assert.strictEqual(removeAccents('heÿ'), 'hey'); + assert.strictEqual(tryNormalizeToBase('heÿ'), 'hey'); - // assert.strictEqual(strings.removeAccents('gruß'), 'grus'); - assert.strictEqual(removeAccents('gruś'), 'grus'); - assert.strictEqual(removeAccents('gruš'), 'grus'); + // assert.strictEqual(strings.tryNormalizeToBase('gruß'), 'grus'); + assert.strictEqual(tryNormalizeToBase('gruś'), 'grus'); + assert.strictEqual(tryNormalizeToBase('gruš'), 'grus'); - assert.strictEqual(removeAccents('çool'), 'cool'); - assert.strictEqual(removeAccents('ćool'), 'cool'); - assert.strictEqual(removeAccents('čool'), 'cool'); + assert.strictEqual(tryNormalizeToBase('çool'), 'cool'); + assert.strictEqual(tryNormalizeToBase('ćool'), 'cool'); + assert.strictEqual(tryNormalizeToBase('čool'), 'cool'); - assert.strictEqual(removeAccents('ñice'), 'nice'); - assert.strictEqual(removeAccents('ńice'), 'nice'); + assert.strictEqual(tryNormalizeToBase('ñice'), 'nice'); + assert.strictEqual(tryNormalizeToBase('ńice'), 'nice'); + + // Different cases + assert.strictEqual(tryNormalizeToBase('CAFÉ'), 'cafe'); + assert.strictEqual(tryNormalizeToBase('Café'), 'cafe'); + assert.strictEqual(tryNormalizeToBase('café'), 'cafe'); + assert.strictEqual(tryNormalizeToBase('JOÃO'), 'joao'); + assert.strictEqual(tryNormalizeToBase('João'), 'joao'); + + // Mixed cases with accents + assert.strictEqual(tryNormalizeToBase('CaFé'), 'cafe'); + assert.strictEqual(tryNormalizeToBase('JoÃo'), 'joao'); + assert.strictEqual(tryNormalizeToBase('AnDrÉ'), 'andre'); + + // Precomposed accents + assert.strictEqual(tryNormalizeToBase('\u00E9'), 'e'); + assert.strictEqual(tryNormalizeToBase('\u00E0'), 'a'); + assert.strictEqual(tryNormalizeToBase('caf\u00E9'), 'cafe'); + + // Base + combining accents - lower only + assert.strictEqual(tryNormalizeToBase('\u0065\u0301'), '\u0065\u0301'); + assert.strictEqual(tryNormalizeToBase('Ã\u0061\u0300'), 'ã\u0061\u0300'); + assert.strictEqual(tryNormalizeToBase('CaF\u0065\u0301'), 'caf\u0065\u0301'); }); }); diff --git a/src/vs/base/test/common/oauth.test.ts b/src/vs/base/test/common/oauth.test.ts index 57a6ad3b16a..91aa59d159f 100644 --- a/src/vs/base/test/common/oauth.test.ts +++ b/src/vs/base/test/common/oauth.test.ts @@ -1319,6 +1319,99 @@ suite('OAuth', () => { assert.strictEqual(headers['X-Test-Header'], 'test-value'); assert.strictEqual(headers['X-Custom-Header'], 'value'); }); + + test('should handle fetchImpl throwing network error and continue to next URL', async () => { + const targetResource = 'https://example.com/api/v1'; + const expectedMetadata = { + resource: 'https://example.com/api/v1', + scopes_supported: ['read', 'write'] + }; + + // First call throws network error, second succeeds + fetchStub.onFirstCall().rejects(new Error('Network connection failed')); + + fetchStub.onSecondCall().resolves({ + status: 200, + json: async () => expectedMetadata, + text: async () => JSON.stringify(expectedMetadata) + }); + + const result = await fetchResourceMetadata( + targetResource, + undefined, + { fetch: fetchStub } + ); + + assert.deepStrictEqual(result, expectedMetadata); + assert.strictEqual(fetchStub.callCount, 2); + // First attempt with path should have thrown error + assert.strictEqual(fetchStub.firstCall.args[0], 'https://example.com/.well-known/oauth-protected-resource/api/v1'); + // Second attempt at root should succeed + assert.strictEqual(fetchStub.secondCall.args[0], 'https://example.com/.well-known/oauth-protected-resource'); + }); + + test('should throw AggregateError when fetchImpl throws on all URLs', async () => { + const targetResource = 'https://example.com/api/v1'; + + // Both calls throw network errors + fetchStub.rejects(new Error('Network connection failed')); + + await assert.rejects( + async () => fetchResourceMetadata(targetResource, undefined, { fetch: fetchStub }), + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 2, 'Should contain 2 errors'); + assert.ok(/Network connection failed/.test(error.errors[0].message), 'First error should mention network failure'); + assert.ok(/Network connection failed/.test(error.errors[1].message), 'Second error should mention network failure'); + return true; + } + ); + + assert.strictEqual(fetchStub.callCount, 2); + }); + + test('should handle mix of fetch error and non-200 response', async () => { + const targetResource = 'https://example.com/api/v1'; + + // First call throws network error + fetchStub.onFirstCall().rejects(new Error('Connection timeout')); + + // Second call returns 404 + fetchStub.onSecondCall().resolves({ + status: 404, + text: async () => 'Not Found', + statusText: 'Not Found' + }); + + await assert.rejects( + async () => fetchResourceMetadata(targetResource, undefined, { fetch: fetchStub }), + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 2, 'Should contain 2 errors'); + assert.ok(/Connection timeout/.test(error.errors[0].message), 'First error should be network error'); + assert.ok(/Failed to fetch resource metadata.*404/.test(error.errors[1].message), 'Second error should be 404'); + return true; + } + ); + + assert.strictEqual(fetchStub.callCount, 2); + }); + + test('should handle fetchImpl throwing error with explicit resourceMetadataUrl', async () => { + const targetResource = 'https://example.com/api'; + const resourceMetadataUrl = 'https://example.com/.well-known/oauth-protected-resource'; + + fetchStub.rejects(new Error('DNS resolution failed')); + + await assert.rejects( + async () => fetchResourceMetadata(targetResource, resourceMetadataUrl, { fetch: fetchStub }), + /DNS resolution failed/ + ); + + // Should only try once when explicit URL is provided + assert.strictEqual(fetchStub.callCount, 1); + assert.strictEqual(fetchStub.firstCall.args[0], resourceMetadataUrl); + }); }); suite('fetchAuthorizationServerMetadata', () => { @@ -1507,7 +1600,7 @@ suite('OAuth', () => { assert.strictEqual(headers['Authorization'], 'Bearer token123'); assert.strictEqual(headers['Accept'], 'application/json'); }); - test('should throw error when all discovery endpoints fail', async () => { + test('should throw AggregateError when all discovery endpoints fail', async () => { const authorizationServer = 'https://auth.example.com/tenant'; fetchStub.resolves({ @@ -1519,13 +1612,91 @@ suite('OAuth', () => { await assert.rejects( async () => fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }), - /Failed to fetch authorization server metadata: 404 Not Found/ + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 3, 'Should contain 3 errors (one for each URL)'); + assert.strictEqual(error.message, 'Failed to fetch authorization server metadata from all attempted URLs'); + // Verify each error includes the URL it attempted + assert.ok(/oauth-authorization-server.*404/.test(error.errors[0].message), 'First error should mention OAuth discovery and 404'); + assert.ok(/openid-configuration.*404/.test(error.errors[1].message), 'Second error should mention OpenID path insertion and 404'); + assert.ok(/openid-configuration.*404/.test(error.errors[2].message), 'Third error should mention OpenID path addition and 404'); + return true; + } ); // Should have tried all three endpoints assert.strictEqual(fetchStub.callCount, 3); }); + test('should throw single error (not AggregateError) when only one URL is tried and fails', async () => { + const authorizationServer = 'https://auth.example.com'; + + // First attempt succeeds on second try, so only one error is collected for first URL + fetchStub.onFirstCall().resolves({ + status: 500, + text: async () => 'Internal Server Error', + statusText: 'Internal Server Error', + json: async () => { throw new Error('Not JSON'); } + }); + + const expectedMetadata: IAuthorizationServerMetadata = { + issuer: 'https://auth.example.com/', + response_types_supported: ['code'] + }; + + fetchStub.onSecondCall().resolves({ + status: 200, + json: async () => expectedMetadata, + text: async () => JSON.stringify(expectedMetadata), + statusText: 'OK' + }); + + // Should succeed on second attempt + const result = await fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }); + assert.deepStrictEqual(result, expectedMetadata); + assert.strictEqual(fetchStub.callCount, 2); + }); + + test('should throw AggregateError when multiple URLs fail with mixed error types', async () => { + const authorizationServer = 'https://auth.example.com/tenant'; + + // First call: network error + fetchStub.onFirstCall().rejects(new Error('Connection timeout')); + + // Second call: 404 + fetchStub.onSecondCall().resolves({ + status: 404, + text: async () => 'Not Found', + statusText: 'Not Found', + json: async () => { throw new Error('Not JSON'); } + }); + + // Third call: 500 + fetchStub.onThirdCall().resolves({ + status: 500, + text: async () => 'Internal Server Error', + statusText: 'Internal Server Error', + json: async () => { throw new Error('Not JSON'); } + }); + + await assert.rejects( + async () => fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }), + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 3, 'Should contain 3 errors'); + // First error is network error + assert.ok(/Connection timeout/.test(error.errors[0].message), 'First error should be network error'); + // Second error is 404 + assert.ok(/404.*Not Found/.test(error.errors[1].message), 'Second error should be 404'); + // Third error is 500 + assert.ok(/500.*Internal Server Error/.test(error.errors[2].message), 'Third error should be 500'); + return true; + } + ); + + assert.strictEqual(fetchStub.callCount, 3); + }); + test('should handle invalid JSON response', async () => { const authorizationServer = 'https://auth.example.com'; @@ -1583,15 +1754,83 @@ suite('OAuth', () => { assert.strictEqual(globalFetchStub.callCount, 1); }); - test('should handle network fetch failure', async () => { + test('should handle network fetch failure and continue to next endpoint', async () => { + const authorizationServer = 'https://auth.example.com'; + const expectedMetadata: IAuthorizationServerMetadata = { + issuer: 'https://auth.example.com/', + response_types_supported: ['code'] + }; + + // First call throws network error, second succeeds + fetchStub.onFirstCall().rejects(new Error('Network error')); + fetchStub.onSecondCall().resolves({ + status: 200, + json: async () => expectedMetadata, + text: async () => JSON.stringify(expectedMetadata), + statusText: 'OK' + }); + + const result = await fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }); + + assert.deepStrictEqual(result, expectedMetadata); + // Should have tried two endpoints + assert.strictEqual(fetchStub.callCount, 2); + }); + + test('should throw error when network fails on all endpoints', async () => { const authorizationServer = 'https://auth.example.com'; fetchStub.rejects(new Error('Network error')); await assert.rejects( async () => fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }), - /Network error/ + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 3, 'Should contain 3 errors'); + assert.strictEqual(error.message, 'Failed to fetch authorization server metadata from all attempted URLs'); + // All errors should be network errors + assert.ok(/Network error/.test(error.errors[0].message), 'First error should be network error'); + assert.ok(/Network error/.test(error.errors[1].message), 'Second error should be network error'); + assert.ok(/Network error/.test(error.errors[2].message), 'Third error should be network error'); + return true; + } ); + + // Should have tried all three endpoints + assert.strictEqual(fetchStub.callCount, 3); + }); + + test('should handle mix of network error and non-200 response', async () => { + const authorizationServer = 'https://auth.example.com/tenant'; + const expectedMetadata: IAuthorizationServerMetadata = { + issuer: 'https://auth.example.com/tenant', + response_types_supported: ['code'] + }; + + // First call throws network error + fetchStub.onFirstCall().rejects(new Error('Connection timeout')); + + // Second call returns 404 + fetchStub.onSecondCall().resolves({ + status: 404, + text: async () => 'Not Found', + statusText: 'Not Found', + json: async () => { throw new Error('Not JSON'); } + }); + + // Third call succeeds + fetchStub.onThirdCall().resolves({ + status: 200, + json: async () => expectedMetadata, + text: async () => JSON.stringify(expectedMetadata), + statusText: 'OK' + }); + + const result = await fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }); + + assert.deepStrictEqual(result, expectedMetadata); + // Should have tried all three endpoints + assert.strictEqual(fetchStub.callCount, 3); }); test('should handle response.text() failure in error case', async () => { @@ -1606,7 +1845,15 @@ suite('OAuth', () => { await assert.rejects( async () => fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }), - /Failed to fetch authorization server metadata: 500 Internal Server Error/ + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 3, 'Should contain 3 errors'); + // All errors should include status code and statusText (fallback when text() fails) + for (const err of error.errors) { + assert.ok(/500 Internal Server Error/.test(err.message), `Error should mention 500 and statusText: ${err.message}`); + } + return true; + } ); }); @@ -1685,7 +1932,15 @@ suite('OAuth', () => { await assert.rejects( async () => fetchAuthorizationServerMetadata(authorizationServer, { fetch: fetchStub }), - /Failed to fetch authorization server metadata/ + (error: any) => { + assert.ok(error instanceof AggregateError, 'Should be an AggregateError'); + assert.strictEqual(error.errors.length, 3, 'Should contain 3 errors'); + // All errors should indicate failed to fetch with status code + for (const err of error.errors) { + assert.ok(/Failed to fetch authorization server metadata from/.test(err.message), `Error should mention failed fetch: ${err.message}`); + } + return true; + } ); // Should try all three endpoints diff --git a/src/vs/base/test/common/observables/debug.test.ts b/src/vs/base/test/common/observables/debug.test.ts index d3bebb9126e..c046999ef59 100644 --- a/src/vs/base/test/common/observables/debug.test.ts +++ b/src/vs/base/test/common/observables/debug.test.ts @@ -7,7 +7,7 @@ import assert from 'assert'; import { observableValue, derived, autorun } from '../../../common/observable.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from '../utils.js'; // eslint-disable-next-line local/code-no-deep-import-of-internal -import { debugGetDependencyGraph } from '../../../common/observableInternal/logging/debugGetDependencyGraph.js'; +import { debugGetObservableGraph } from '../../../common/observableInternal/logging/debugGetDependencyGraph.js'; suite('debug', () => { const ds = ensureNoDisposablesAreLeakedInTestSuite(); @@ -50,8 +50,8 @@ suite('debug', () => { let idx = 0; assert.deepStrictEqual( - debugGetDependencyGraph(myComputed3, { debugNamePostProcessor: name => `name${++idx}` }), - "* derived name1:\n value: 0\n state: upToDate\n dependencies:\n\t\t* derived name2:\n\t\t value: 0\n\t\t state: upToDate\n\t\t dependencies:\n\t\t\t\t* derived name3:\n\t\t\t\t value: 0\n\t\t\t\t state: upToDate\n\t\t\t\t dependencies:\n\t\t\t\t\t\t* observableValue name4:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t\t\t* observableValue name5:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t* observableValue name6 (already listed)\n\t\t\t\t* observableValue name7 (already listed)\n\t\t* observableValue name8 (already listed)\n\t\t* observableValue name9 (already listed)", + debugGetObservableGraph(myComputed3, { type: 'dependencies', debugNamePostProcessor: name => `name${++idx}` }), + '* derived name1:\n value: 0\n state: upToDate\n dependencies:\n\t\t* derived name2:\n\t\t value: 0\n\t\t state: upToDate\n\t\t dependencies:\n\t\t\t\t* derived name3:\n\t\t\t\t value: 0\n\t\t\t\t state: upToDate\n\t\t\t\t dependencies:\n\t\t\t\t\t\t* observableValue name4:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t\t\t* observableValue name5:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t* observableValue name6 (already listed)\n\t\t\t\t* observableValue name7 (already listed)\n\t\t* observableValue name8 (already listed)\n\t\t* observableValue name9 (already listed)', ); }); }); diff --git a/src/vs/base/test/common/observables/observable.test.ts b/src/vs/base/test/common/observables/observable.test.ts index 3cd85109708..c1814dfe7b1 100644 --- a/src/vs/base/test/common/observables/observable.test.ts +++ b/src/vs/base/test/common/observables/observable.test.ts @@ -97,22 +97,22 @@ suite('observables', () => { })); // autorun runs immediately assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: 0 + 0 = 0", - "myAutorun(myDerived: 0)", + 'myDerived.recompute: 0 + 0 = 0', + 'myAutorun(myDerived: 0)', ]); observable1.set(1, undefined); // and on changes... assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: 1 + 0 = 1", - "myAutorun(myDerived: 1)", + 'myDerived.recompute: 1 + 0 = 1', + 'myAutorun(myDerived: 1)', ]); observable2.set(1, undefined); // ... of any dependency. assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: 1 + 1 = 2", - "myAutorun(myDerived: 2)", + 'myDerived.recompute: 1 + 1 = 2', + 'myAutorun(myDerived: 2)', ]); // Now we change multiple observables in a transaction to batch process the effects. @@ -127,8 +127,8 @@ suite('observables', () => { // deriveds are only recomputed on demand. // (Note that you cannot see the intermediate value when `obs1 == 5` and `obs2 == 1`) assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: 5 + 5 = 10", - "myAutorun(myDerived: 10)", + 'myDerived.recompute: 5 + 5 = 10', + 'myAutorun(myDerived: 10)', ]); transaction((tx) => { @@ -139,7 +139,7 @@ suite('observables', () => { assert.deepStrictEqual(log.getAndClearEntries(), []); }); // Now the autorun didn't run again, because its dependency changed from 10 to 10 (= no change). - assert.deepStrictEqual(log.getAndClearEntries(), (["myDerived.recompute: 6 + 4 = 10"])); + assert.deepStrictEqual(log.getAndClearEntries(), (['myDerived.recompute: 6 + 4 = 10'])); }); test('read during transaction', () => { @@ -162,8 +162,8 @@ suite('observables', () => { })); // autorun runs immediately assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: 0 + 0 = 0", - "myAutorun(myDerived: 0)", + 'myDerived.recompute: 0 + 0 = 0', + 'myAutorun(myDerived: 0)', ]); transaction((tx) => { @@ -171,7 +171,7 @@ suite('observables', () => { assert.deepStrictEqual(log.getAndClearEntries(), []); myDerived.get(); // This forces a (sync) recomputation of the current value! - assert.deepStrictEqual(log.getAndClearEntries(), (["myDerived.recompute: -10 + 0 = -10"])); + assert.deepStrictEqual(log.getAndClearEntries(), (['myDerived.recompute: -10 + 0 = -10'])); // This means, that even in transactions you can assume that all values you can read with `get` and `read` are up-to-date. // Read these values just might cause additional (potentially unneeded) recomputations. @@ -180,8 +180,8 @@ suite('observables', () => { }); // This autorun runs again, because its dependency changed from 0 to -10 and then back to 0. assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.recompute: -10 + 10 = 0", - "myAutorun(myDerived: 0)", + 'myDerived.recompute: -10 + 10 = 0', + 'myAutorun(myDerived: 0)', ]); }); @@ -268,35 +268,35 @@ suite('observables', () => { log.log(`value: ${computedSum.get()}`); // Those deriveds are recomputed on demand, i.e. when someone reads them. assert.deepStrictEqual(log.getAndClearEntries(), [ - "recompute1: 2 % 3 = 2", - "recompute2: 2 * 2 = 4", - "recompute3: 2 * 3 = 6", - "recompute4: 4 + 6 = 10", - "value: 10", + 'recompute1: 2 % 3 = 2', + 'recompute2: 2 * 2 = 4', + 'recompute3: 2 * 3 = 6', + 'recompute4: 4 + 6 = 10', + 'value: 10', ]); log.log(`value: ${computedSum.get()}`); // ... and then cached again - assert.deepStrictEqual(log.getAndClearEntries(), (["value: 10"])); + assert.deepStrictEqual(log.getAndClearEntries(), (['value: 10'])); disposable.dispose(); // Don't forget to dispose the keepAlive to prevent memory leaks! log.log(`value: ${computedSum.get()}`); // Which disables the cache again assert.deepStrictEqual(log.getAndClearEntries(), [ - "recompute1: 2 % 3 = 2", - "recompute2: 2 * 2 = 4", - "recompute3: 2 * 3 = 6", - "recompute4: 4 + 6 = 10", - "value: 10", + 'recompute1: 2 % 3 = 2', + 'recompute2: 2 * 2 = 4', + 'recompute3: 2 * 3 = 6', + 'recompute4: 4 + 6 = 10', + 'value: 10', ]); log.log(`value: ${computedSum.get()}`); assert.deepStrictEqual(log.getAndClearEntries(), [ - "recompute1: 2 % 3 = 2", - "recompute2: 2 * 2 = 4", - "recompute3: 2 * 3 = 6", - "recompute4: 4 + 6 = 10", - "value: 10", + 'recompute1: 2 % 3 = 2', + 'recompute2: 2 * 2 = 4', + 'recompute3: 2 * 3 = 6', + 'recompute4: 4 + 6 = 10', + 'value: 10', ]); // Why don't we just always keep the cache alive? @@ -395,38 +395,38 @@ suite('observables', () => { log.log(`myAutorun.run(myComputed3: ${myComputed3.read(reader)})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed1.recompute(myObservable1: 0 + myObservable2: 0 = 0)", - "myComputed2.recompute(myComputed1: 0 + myObservable1: 0 + myObservable2: 0 = 0)", - "myComputed3.recompute(myComputed2: 0 + myObservable1: 0 + myObservable2: 0 = 0)", - "myAutorun.run(myComputed3: 0)", + 'myComputed1.recompute(myObservable1: 0 + myObservable2: 0 = 0)', + 'myComputed2.recompute(myComputed1: 0 + myObservable1: 0 + myObservable2: 0 = 0)', + 'myComputed3.recompute(myComputed2: 0 + myObservable1: 0 + myObservable2: 0 = 0)', + 'myAutorun.run(myComputed3: 0)', ]); myObservable1.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed1.recompute(myObservable1: 1 + myObservable2: 0 = 1)", - "myComputed2.recompute(myComputed1: 1 + myObservable1: 1 + myObservable2: 0 = 2)", - "myComputed3.recompute(myComputed2: 2 + myObservable1: 1 + myObservable2: 0 = 3)", - "myAutorun.run(myComputed3: 3)", + 'myComputed1.recompute(myObservable1: 1 + myObservable2: 0 = 1)', + 'myComputed2.recompute(myComputed1: 1 + myObservable1: 1 + myObservable2: 0 = 2)', + 'myComputed3.recompute(myComputed2: 2 + myObservable1: 1 + myObservable2: 0 = 3)', + 'myAutorun.run(myComputed3: 3)', ]); transaction((tx) => { myObservable1.set(2, tx); myComputed2.get(); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed1.recompute(myObservable1: 2 + myObservable2: 0 = 2)", - "myComputed2.recompute(myComputed1: 2 + myObservable1: 2 + myObservable2: 0 = 4)", + 'myComputed1.recompute(myObservable1: 2 + myObservable2: 0 = 2)', + 'myComputed2.recompute(myComputed1: 2 + myObservable1: 2 + myObservable2: 0 = 4)', ]); myObservable1.set(3, tx); myComputed2.get(); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed1.recompute(myObservable1: 3 + myObservable2: 0 = 3)", - "myComputed2.recompute(myComputed1: 3 + myObservable1: 3 + myObservable2: 0 = 6)", + 'myComputed1.recompute(myObservable1: 3 + myObservable2: 0 = 3)', + 'myComputed2.recompute(myComputed1: 3 + myObservable1: 3 + myObservable2: 0 = 6)', ]); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed3.recompute(myComputed2: 6 + myObservable1: 3 + myObservable2: 0 = 9)", - "myAutorun.run(myComputed3: 9)", + 'myComputed3.recompute(myComputed2: 6 + myObservable1: 3 + myObservable2: 0 = 9)', + 'myAutorun.run(myComputed3: 9)', ]); }); @@ -482,22 +482,22 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "subscribed handler 0", - "compute value undefined", - "autorun, value: undefined", + 'subscribed handler 0', + 'compute value undefined', + 'autorun, value: undefined', ]); setValue(1); assert.deepStrictEqual(log.getAndClearEntries(), [ - "compute value 1", - "autorun, value: 1" + 'compute value 1', + 'autorun, value: 1' ]); autorunDisposable.dispose(); assert.deepStrictEqual(log.getAndClearEntries(), [ - "unsubscribed handler 0" + 'unsubscribed handler 0' ]); }); @@ -593,26 +593,26 @@ suite('observables', () => { log.log(`myAutorun: ${value}`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed.recompute", - "myObs1.firstObserverAdded", - "myObs1.get", - "myAutorun: 0", + 'myComputed.recompute', + 'myObs1.firstObserverAdded', + 'myObs1.get', + 'myAutorun: 0', ]); transaction(tx => { myObs1.set(1, tx); - assert.deepStrictEqual(log.getAndClearEntries(), (["myObs1.set (value 1)"])); + assert.deepStrictEqual(log.getAndClearEntries(), (['myObs1.set (value 1)'])); shouldReadObservable.set(false, tx); assert.deepStrictEqual(log.getAndClearEntries(), ([])); myComputed.get(); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myComputed.recompute", - "myObs1.lastObserverRemoved", + 'myComputed.recompute', + 'myObs1.lastObserverRemoved', ]); }); - assert.deepStrictEqual(log.getAndClearEntries(), (["myAutorun: 1"])); + assert.deepStrictEqual(log.getAndClearEntries(), (['myAutorun: 1'])); }); test('avoid recomputation of deriveds that are no longer read', () => { @@ -640,41 +640,41 @@ suite('observables', () => { } })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObsShouldRead.firstObserverAdded", - "myObsShouldRead.get", - "myObs1.firstObserverAdded", - "myObs1.get", - "myComputed1(myObs1: 0): Computed 0", - "myAutorun(shouldRead: true, myComputed1: 0): run", + 'myObsShouldRead.firstObserverAdded', + 'myObsShouldRead.get', + 'myObs1.firstObserverAdded', + 'myObs1.get', + 'myComputed1(myObs1: 0): Computed 0', + 'myAutorun(shouldRead: true, myComputed1: 0): run', ]); transaction(tx => { myObsShouldRead.set(false, tx); myObs1.set(1, tx); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObsShouldRead.set (value false)", - "myObs1.set (value 1)", + 'myObsShouldRead.set (value false)', + 'myObs1.set (value 1)', ]); }); // myComputed1 should not be recomputed here, even though its dependency myObs1 changed! assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObsShouldRead.get", - "myAutorun(shouldRead: false): run", - "myObs1.lastObserverRemoved", + 'myObsShouldRead.get', + 'myAutorun(shouldRead: false): run', + 'myObs1.lastObserverRemoved', ]); transaction(tx => { myObsShouldRead.set(true, tx); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObsShouldRead.set (value true)", + 'myObsShouldRead.set (value true)', ]); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObsShouldRead.get", - "myObs1.firstObserverAdded", - "myObs1.get", - "myComputed1(myObs1: 1): Computed 1", - "myAutorun(shouldRead: true, myComputed1: 1): run", + 'myObsShouldRead.get', + 'myObs1.firstObserverAdded', + 'myObs1.get', + 'myComputed1(myObs1: 1): Computed 1', + 'myAutorun(shouldRead: true, myComputed1: 1): run', ]); }); @@ -715,8 +715,8 @@ suite('observables', () => { log.log(`myAutorun.run(myDerived: ${myDerived.read(reader)})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.read(myObservable: 0)", - "myAutorun.run(myDerived: 0)" + 'myDerived.read(myObservable: 0)', + 'myAutorun.run(myDerived: 0)' ]); transaction((tx) => { @@ -727,7 +727,7 @@ suite('observables', () => { assert.deepStrictEqual(log.getAndClearEntries(), []); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.read(myObservable: 0)" + 'myDerived.read(myObservable: 0)' ]); }); @@ -746,8 +746,8 @@ suite('observables', () => { log.log(`myAutorun.run(myDerived: ${myDerived.read(reader)})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.read(myObservable: 0)", - "myAutorun.run(myDerived: 0)" + 'myDerived.read(myObservable: 0)', + 'myAutorun.run(myDerived: 0)' ]); transaction((tx) => { @@ -756,15 +756,15 @@ suite('observables', () => { myDerived.get(); // This marks the auto-run as changed assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.read(myObservable: 2)" + 'myDerived.read(myObservable: 2)' ]); myObservable.set(0, tx); assert.deepStrictEqual(log.getAndClearEntries(), []); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.read(myObservable: 0)", - "myAutorun.run(myDerived: 0)" + 'myDerived.read(myObservable: 0)', + 'myAutorun.run(myDerived: 0)' ]); }); }); @@ -780,28 +780,28 @@ suite('observables', () => { /** @description autorun */ if (observable1.read(reader) >= 2) { assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable1.set (value 2)", - "myObservable1.get", + 'myObservable1.set (value 2)', + 'myObservable1.get', ]); myObservable2.read(reader); // First time this observable is read assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable2.firstObserverAdded", - "myObservable2.get", + 'myObservable2.firstObserverAdded', + 'myObservable2.get', ]); d.dispose(); // Disposing removes all observers assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable1.lastObserverRemoved", - "myObservable2.lastObserverRemoved", + 'myObservable1.lastObserverRemoved', + 'myObservable2.lastObserverRemoved', ]); myObservable3.read(reader); // This does not subscribe the observable, because the autorun is disposed assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable3.get", + 'myObservable3.get', ]); } }); @@ -882,28 +882,28 @@ suite('observables', () => { log.log(`myAutorun(myComputed: ${value})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.firstObserverAdded", - "myObservable.get", - "myComputed(myObservable: 0): start computing", - "myComputed(myObservable: 0): finished computing", - "myAutorun(myComputed: 0)" + 'myObservable.firstObserverAdded', + 'myObservable.get', + 'myComputed(myObservable: 0): start computing', + 'myComputed(myObservable: 0): finished computing', + 'myAutorun(myComputed: 0)' ]); myObservable.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 1)", - "myObservable.get", - "myComputed(myObservable: 1): start computing", - "myObservable.set (value 2)", - "myComputed(myObservable: 1): finished computing", - "myObservable.get", - "myComputed(myObservable: 2): start computing", - "myObservable.set (value 3)", - "myComputed(myObservable: 2): finished computing", - "myObservable.get", - "myComputed(myObservable: 3): start computing", - "myComputed(myObservable: 3): finished computing", - "myAutorun(myComputed: 3)", + 'myObservable.set (value 1)', + 'myObservable.get', + 'myComputed(myObservable: 1): start computing', + 'myObservable.set (value 2)', + 'myComputed(myObservable: 1): finished computing', + 'myObservable.get', + 'myComputed(myObservable: 2): start computing', + 'myObservable.set (value 3)', + 'myComputed(myObservable: 2): finished computing', + 'myObservable.get', + 'myComputed(myObservable: 3): start computing', + 'myComputed(myObservable: 3): finished computing', + 'myAutorun(myComputed: 3)', ]); }); @@ -921,30 +921,30 @@ suite('observables', () => { log.log(`myAutorun(myObservable: ${value}): end`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.firstObserverAdded", - "myObservable.get", - "myAutorun(myObservable: 0): start", - "myAutorun(myObservable: 0): end", + 'myObservable.firstObserverAdded', + 'myObservable.get', + 'myAutorun(myObservable: 0): start', + 'myAutorun(myObservable: 0): end', ]); myObservable.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 1)", - "myObservable.get", - "myAutorun(myObservable: 1): start", - "myObservable.set (value 2)", - "myAutorun(myObservable: 1): end", - "myObservable.get", - "myAutorun(myObservable: 2): start", - "myObservable.set (value 3)", - "myAutorun(myObservable: 2): end", - "myObservable.get", - "myAutorun(myObservable: 3): start", - "myObservable.set (value 4)", - "myAutorun(myObservable: 3): end", - "myObservable.get", - "myAutorun(myObservable: 4): start", - "myAutorun(myObservable: 4): end", + 'myObservable.set (value 1)', + 'myObservable.get', + 'myAutorun(myObservable: 1): start', + 'myObservable.set (value 2)', + 'myAutorun(myObservable: 1): end', + 'myObservable.get', + 'myAutorun(myObservable: 2): start', + 'myObservable.set (value 3)', + 'myAutorun(myObservable: 2): end', + 'myObservable.get', + 'myAutorun(myObservable: 3): start', + 'myObservable.set (value 4)', + 'myAutorun(myObservable: 3): end', + 'myObservable.get', + 'myAutorun(myObservable: 4): start', + 'myAutorun(myObservable: 4): end', ]); }); @@ -972,36 +972,36 @@ suite('observables', () => { log.log(`myAutorun(myDerived2: ${value})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.firstObserverAdded", - "myObservable.get", - "myDerived1(myObservable: 0): start computing", - "myDerived2(myDerived1: 0): start computing", - "myAutorun(myDerived2: 0)", + 'myObservable.firstObserverAdded', + 'myObservable.get', + 'myDerived1(myObservable: 0): start computing', + 'myDerived2(myDerived1: 0): start computing', + 'myAutorun(myDerived2: 0)', ]); transaction(tx => { myObservable.set(1, tx); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 1)", + 'myObservable.set (value 1)', ]); myDerived2.get(); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.get", - "myDerived1(myObservable: 1): start computing", - "myDerived2(myDerived1: 1): start computing", + 'myObservable.get', + 'myDerived1(myObservable: 1): start computing', + 'myDerived2(myDerived1: 1): start computing', ]); myObservable.set(2, tx); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 2)", + 'myObservable.set (value 2)', ]); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.get", - "myDerived1(myObservable: 2): start computing", - "myDerived2(myDerived1: 2): start computing", - "myAutorun(myDerived2: 2)", + 'myObservable.get', + 'myDerived1(myObservable: 2): start computing', + 'myDerived2(myDerived1: 2): start computing', + 'myAutorun(myDerived2: 2)', ]); }); @@ -1031,30 +1031,30 @@ suite('observables', () => { log.log(`myAutorun(myDerived3: ${val})`); })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable1.firstObserverAdded", - "myObservable1.get", - "myObservable2.firstObserverAdded", - "myObservable2.get", - "myDerived2.computed(myObservable2: 0)", - "myDerived3.computed(myDerived1: 0, myDerived2: 0)", - "myAutorun(myDerived3: 0 + 0)", + 'myObservable1.firstObserverAdded', + 'myObservable1.get', + 'myObservable2.firstObserverAdded', + 'myObservable2.get', + 'myDerived2.computed(myObservable2: 0)', + 'myDerived3.computed(myDerived1: 0, myDerived2: 0)', + 'myAutorun(myDerived3: 0 + 0)', ]); transaction(tx => { myObservable1.set(1, tx); // Mark myDerived 3 as stale assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable1.set (value 1)", + 'myObservable1.set (value 1)', ]); myObservable2.set(10, tx); // This is a non-change. myDerived3 should not be marked as possibly-depedency-changed! assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable2.set (value 10)", + 'myObservable2.set (value 10)', ]); }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable1.get", - "myObservable2.get", - "myDerived2.computed(myObservable2: 10)", + 'myObservable1.get', + 'myObservable2.get', + 'myDerived2.computed(myObservable2: 10)', 'myDerived3.computed(myDerived1: 1, myDerived2: 0)', 'myAutorun(myDerived3: 1 + 0)', ]); @@ -1146,11 +1146,11 @@ suite('observables', () => { i++; emitter.fire(2); - assert.deepStrictEqual(log.getAndClearEntries(), ["event fired 2"]); + assert.deepStrictEqual(log.getAndClearEntries(), ['event fired 2']); i++; emitter.fire(3); - assert.deepStrictEqual(log.getAndClearEntries(), ["event fired 3"]); + assert.deepStrictEqual(log.getAndClearEntries(), ['event fired 3']); d.dispose(); }); @@ -1347,17 +1347,17 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.firstObserverAdded", - "myObservable.get", - "error: foobar" + 'myObservable.firstObserverAdded', + 'myObservable.get', + 'error: foobar' ]); myObservable.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 1)", - "myObservable.get", - "error: foobar", + 'myObservable.set (value 1)', + 'myObservable.get', + 'error: foobar', ]); d.dispose(); @@ -1380,24 +1380,24 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.firstObserverAdded", - "myObservable.get", + 'myObservable.firstObserverAdded', + 'myObservable.get', ]); myObservable.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 1)", - "myObservable.get", - "error: foobar", + 'myObservable.set (value 1)', + 'myObservable.get', + 'error: foobar', ]); myObservable.set(2, undefined); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myObservable.set (value 2)", - "myObservable.get", - "error: foobar", + 'myObservable.set (value 2)', + 'myObservable.get', + 'error: foobar', ]); d.dispose(); @@ -1436,15 +1436,15 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), [ - "myDerived.computed start", - "myObservable.firstObserverAdded", - "myObservable.get", - "myObservable.set (value 1)", - "myDerived.computed end", - "myDerived.computed start", - "myObservable.get", - "myDerived.computed end", - "recomputeInitiallyAndOnChange, myDerived: 1", + 'myDerived.computed start', + 'myObservable.firstObserverAdded', + 'myObservable.get', + 'myObservable.set (value 1)', + 'myDerived.computed end', + 'myDerived.computed start', + 'myObservable.get', + 'myDerived.computed end', + 'recomputeInitiallyAndOnChange, myDerived: 1', ]); myDerived.get(); @@ -1521,12 +1521,12 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "autorun start", - "d1.computed start", - "d2.computed start", - "Error: Cyclic deriveds are not supported yet!", - "d1.computed end", - "autorun end" + 'autorun start', + 'd1.computed start', + 'd2.computed start', + 'Error: Cyclic deriveds are not supported yet!', + 'd1.computed end', + 'autorun end' ])); disp.dispose(); @@ -1573,9 +1573,9 @@ suite('observables', () => { })); assert.deepStrictEqual(log.getAndClearEntries(), [ - "createInitial", + 'createInitial', 'update {"changes":[],"myObservable1":5,"myObservable2":9}', - "update -> 14", + 'update -> 14', 'autorun {"changes":[],"sum":14}', ]); @@ -1585,9 +1585,9 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "update {\"changes\":[{\"key\":\"myObservable1\",\"change\":1},{\"key\":\"myObservable2\",\"change\":3}],\"myObservable1\":6,\"myObservable2\":12}", - "update -> 18", - "autorun {\"changes\":[{\"key\":\"sum\",\"change\":4}],\"sum\":18}" + 'update {"changes":[{"key":"myObservable1","change":1},{"key":"myObservable2","change":3}],"myObservable1":6,"myObservable2":12}', + 'update -> 18', + 'autorun {"changes":[{"key":"sum","change":4}],"sum":18}' ])); transaction(tx => { @@ -1598,18 +1598,18 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "update {\"changes\":[{\"key\":\"myObservable1\",\"change\":1}],\"myObservable1\":7,\"myObservable2\":12}", - "update -> 19", - "sum.get() 19", - "update {\"changes\":[{\"key\":\"myObservable2\",\"change\":3}],\"myObservable1\":7,\"myObservable2\":15}", - "update -> 22", - "autorun {\"changes\":[{\"key\":\"sum\",\"change\":1}],\"sum\":22}" + 'update {"changes":[{"key":"myObservable1","change":1}],"myObservable1":7,"myObservable2":12}', + 'update -> 19', + 'sum.get() 19', + 'update {"changes":[{"key":"myObservable2","change":3}],"myObservable1":7,"myObservable2":15}', + 'update -> 22', + 'autorun {"changes":[{"key":"sum","change":1}],"sum":22}' ])); store.dispose(); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "disposeFinal 22" + 'disposeFinal 22' ])); }); }); @@ -1633,22 +1633,22 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed 0", - "a: 0" + 'computed 0', + 'a: 0' ])); observable1.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed1: 0 disposed", - "computed 1", - "a: 1" + 'computed1: 0 disposed', + 'computed 1', + 'a: 1' ])); a.dispose(); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed1: 1 disposed" + 'computed1: 1 disposed' ])); }); @@ -1670,22 +1670,22 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed 0", - "a: 0" + 'computed 0', + 'a: 0' ])); observable1.set(1, undefined); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed 1", - "computed1: 0 disposed", - "a: 1" + 'computed 1', + 'computed1: 0 disposed', + 'a: 1' ])); a.dispose(); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "computed1: 1 disposed" + 'computed1: 1 disposed' ])); }); }); @@ -1724,7 +1724,7 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "runOnChange [\"signal1: foo, signal2Derived: bar (derived)\"]" + 'runOnChange ["signal1: foo, signal2Derived: bar (derived)"]' ])); @@ -1733,7 +1733,7 @@ suite('observables', () => { }); assert.deepStrictEqual(log.getAndClearEntries(), ([ - "runOnChange [\"signal2Derived: baz (derived)\"]" + 'runOnChange ["signal2Derived: baz (derived)"]' ])); disp.dispose(); diff --git a/src/vs/base/test/common/skipList.test.ts b/src/vs/base/test/common/skipList.test.ts deleted file mode 100644 index d827e70c087..00000000000 --- a/src/vs/base/test/common/skipList.test.ts +++ /dev/null @@ -1,233 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import assert from 'assert'; -import { binarySearch } from '../../common/arrays.js'; -import { SkipList } from '../../common/skipList.js'; -import { StopWatch } from '../../common/stopwatch.js'; -import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js'; - - -suite('SkipList', function () { - - ensureNoDisposablesAreLeakedInTestSuite(); - - function assertValues(list: SkipList, expected: V[]) { - assert.strictEqual(list.size, expected.length); - assert.deepStrictEqual([...list.values()], expected); - - const valuesFromEntries = [...list.entries()].map(entry => entry[1]); - assert.deepStrictEqual(valuesFromEntries, expected); - - const valuesFromIter = [...list].map(entry => entry[1]); - assert.deepStrictEqual(valuesFromIter, expected); - - let i = 0; - list.forEach((value, _key, map) => { - assert.ok(map === list); - assert.deepStrictEqual(value, expected[i++]); - }); - } - - function assertKeys(list: SkipList, expected: K[]) { - assert.strictEqual(list.size, expected.length); - assert.deepStrictEqual([...list.keys()], expected); - - const keysFromEntries = [...list.entries()].map(entry => entry[0]); - assert.deepStrictEqual(keysFromEntries, expected); - - const keysFromIter = [...list].map(entry => entry[0]); - assert.deepStrictEqual(keysFromIter, expected); - - let i = 0; - list.forEach((_value, key, map) => { - assert.ok(map === list); - assert.deepStrictEqual(key, expected[i++]); - }); - } - - test('set/get/delete', function () { - const list = new SkipList((a, b) => a - b); - - assert.strictEqual(list.get(3), undefined); - list.set(3, 1); - assert.strictEqual(list.get(3), 1); - assertValues(list, [1]); - - list.set(3, 3); - assertValues(list, [3]); - - list.set(1, 1); - list.set(4, 4); - assert.strictEqual(list.get(3), 3); - assert.strictEqual(list.get(1), 1); - assert.strictEqual(list.get(4), 4); - assertValues(list, [1, 3, 4]); - - assert.strictEqual(list.delete(17), false); - - assert.strictEqual(list.delete(1), true); - assert.strictEqual(list.get(1), undefined); - assert.strictEqual(list.get(3), 3); - assert.strictEqual(list.get(4), 4); - - assertValues(list, [3, 4]); - }); - - test('Figure 3', function () { - const list = new SkipList((a, b) => a - b); - list.set(3, true); - list.set(6, true); - list.set(7, true); - list.set(9, true); - list.set(12, true); - list.set(19, true); - list.set(21, true); - list.set(25, true); - - assertKeys(list, [3, 6, 7, 9, 12, 19, 21, 25]); - - list.set(17, true); - assert.deepStrictEqual(list.size, 9); - assertKeys(list, [3, 6, 7, 9, 12, 17, 19, 21, 25]); - }); - - test('clear ( CPU pegged after some builds #194853)', function () { - const list = new SkipList((a, b) => a - b); - list.set(1, true); - list.set(2, true); - list.set(3, true); - assert.strictEqual(list.size, 3); - list.clear(); - assert.strictEqual(list.size, 0); - assert.strictEqual(list.get(1), undefined); - assert.strictEqual(list.get(2), undefined); - assert.strictEqual(list.get(3), undefined); - }); - - test('capacity max', function () { - const list = new SkipList((a, b) => a - b, 10); - list.set(1, true); - list.set(2, true); - list.set(3, true); - list.set(4, true); - list.set(5, true); - list.set(6, true); - list.set(7, true); - list.set(8, true); - list.set(9, true); - list.set(10, true); - list.set(11, true); - list.set(12, true); - - assertKeys(list, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); - }); - - const cmp = (a: number, b: number): number => { - if (a < b) { - return -1; - } else if (a > b) { - return 1; - } else { - return 0; - } - }; - - function insertArraySorted(array: number[], element: number) { - let idx = binarySearch(array, element, cmp); - if (idx >= 0) { - array[idx] = element; - } else { - idx = ~idx; - // array = array.slice(0, idx).concat(element, array.slice(idx)); - array.splice(idx, 0, element); - } - return array; - } - - function delArraySorted(array: number[], element: number) { - const idx = binarySearch(array, element, cmp); - if (idx >= 0) { - // array = array.slice(0, idx).concat(array.slice(idx)); - array.splice(idx, 1); - } - return array; - } - - - test.skip('perf', function () { - - // data - const max = 2 ** 16; - const values = new Set(); - for (let i = 0; i < max; i++) { - const value = Math.floor(Math.random() * max); - values.add(value); - } - console.log(values.size); - - // init - const list = new SkipList(cmp, max); - let sw = new StopWatch(); - values.forEach(value => list.set(value, true)); - sw.stop(); - console.log(`[LIST] ${list.size} elements after ${sw.elapsed()}ms`); - let array: number[] = []; - sw = new StopWatch(); - values.forEach(value => array = insertArraySorted(array, value)); - sw.stop(); - console.log(`[ARRAY] ${array.length} elements after ${sw.elapsed()}ms`); - - // get - sw = new StopWatch(); - const someValues = [...values].slice(0, values.size / 4); - someValues.forEach(key => { - const value = list.get(key); // find - console.assert(value, '[LIST] must have ' + key); - list.get(-key); // miss - }); - sw.stop(); - console.log(`[LIST] retrieve ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`); - sw = new StopWatch(); - someValues.forEach(key => { - const idx = binarySearch(array, key, cmp); // find - console.assert(idx >= 0, '[ARRAY] must have ' + key); - binarySearch(array, -key, cmp); // miss - }); - sw.stop(); - console.log(`[ARRAY] retrieve ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`); - - - // insert - sw = new StopWatch(); - someValues.forEach(key => { - list.set(-key, false); - }); - sw.stop(); - console.log(`[LIST] insert ${sw.elapsed()}ms (${(sw.elapsed() / someValues.length).toPrecision(4)}ms/op)`); - sw = new StopWatch(); - someValues.forEach(key => { - array = insertArraySorted(array, -key); - }); - sw.stop(); - console.log(`[ARRAY] insert ${sw.elapsed()}ms (${(sw.elapsed() / someValues.length).toPrecision(4)}ms/op)`); - - // delete - sw = new StopWatch(); - someValues.forEach(key => { - list.delete(key); // find - list.delete(-key); // miss - }); - sw.stop(); - console.log(`[LIST] delete ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`); - sw = new StopWatch(); - someValues.forEach(key => { - array = delArraySorted(array, key); // find - array = delArraySorted(array, -key); // miss - }); - sw.stop(); - console.log(`[ARRAY] delete ${sw.elapsed()}ms (${(sw.elapsed() / (someValues.length * 2)).toPrecision(4)}ms/op)`); - }); -}); diff --git a/src/vs/base/test/common/strings.test.ts b/src/vs/base/test/common/strings.test.ts index 8b7656f4758..cfdf7836392 100644 --- a/src/vs/base/test/common/strings.test.ts +++ b/src/vs/base/test/common/strings.test.ts @@ -19,7 +19,20 @@ suite('Strings', () => { assert(strings.equalsIgnoreCase('ÖL', 'Öl')); }); - test('beginsWithIgnoreCase', () => { + test('equals', () => { + assert(!strings.equals(undefined, 'abc')); + assert(!strings.equals('abc', undefined)); + assert(strings.equals(undefined, undefined)); + assert(strings.equals('', '')); + assert(strings.equals('a', 'a')); + assert(!strings.equals('abc', 'Abc')); + assert(strings.equals('abc', 'ABC', true)); + assert(!strings.equals('Höhenmeter', 'HÖhenmeter')); + assert(!strings.equals('ÖL', 'Öl')); + assert(strings.equals('ÖL', 'Öl', true)); + }); + + test('startsWithIgnoreCase', () => { assert(strings.startsWithIgnoreCase('', '')); assert(!strings.startsWithIgnoreCase('', '1')); assert(strings.startsWithIgnoreCase('1', '')); @@ -45,6 +58,34 @@ suite('Strings', () => { assert(!strings.startsWithIgnoreCase('alles klar', 'ö')); }); + test('endsWithIgnoreCase', () => { + assert(strings.endsWithIgnoreCase('', '')); + assert(!strings.endsWithIgnoreCase('', '1')); + assert(strings.endsWithIgnoreCase('1', '')); + + assert(!strings.endsWithIgnoreCase('abcd', 'abcde')); + + assert(strings.endsWithIgnoreCase('a', 'a')); + assert(strings.endsWithIgnoreCase('abc', 'Abc')); + assert(strings.endsWithIgnoreCase('abc', 'ABC')); + assert(strings.endsWithIgnoreCase('Höhenmeter', 'HÖhenmeter')); + assert(strings.endsWithIgnoreCase('ÖL', 'Öl')); + + assert(strings.endsWithIgnoreCase('alles klar', 'r')); + assert(strings.endsWithIgnoreCase('alles klar', 'R')); + assert(strings.endsWithIgnoreCase('alles klar', 's klar')); + assert(strings.endsWithIgnoreCase('alles klar', 'S klar')); + assert(strings.endsWithIgnoreCase('alles klar', 'S KLAR')); + assert(strings.endsWithIgnoreCase('alles klar', 'alles klar')); + assert(strings.endsWithIgnoreCase('alles klar', 'ALLES KLAR')); + + assert(!strings.endsWithIgnoreCase('alles klar', 'S KLAR ')); + assert(!strings.endsWithIgnoreCase('alles klar', ' S KLAR')); + assert(!strings.endsWithIgnoreCase('alles klar', 'S KLARö')); + assert(!strings.endsWithIgnoreCase('alles klar', ' ')); + assert(!strings.endsWithIgnoreCase('alles klar', 'ö')); + }); + test('compareIgnoreCase', () => { function assertCompareIgnoreCase(a: string, b: string, recurse = true): void { diff --git a/src/vs/base/test/common/timeTravelScheduler.ts b/src/vs/base/test/common/timeTravelScheduler.ts index f706b997622..72f8d8985ce 100644 --- a/src/vs/base/test/common/timeTravelScheduler.ts +++ b/src/vs/base/test/common/timeTravelScheduler.ts @@ -38,15 +38,19 @@ const scheduledTaskComparator = tieBreakComparators( export class TimeTravelScheduler implements Scheduler { private taskCounter = 0; - private _now: TimeOffset = 0; + private _nowMs: TimeOffset = 0; private readonly queue: PriorityQueue = new SimplePriorityQueue([], scheduledTaskComparator); private readonly taskScheduledEmitter = new Emitter<{ task: ScheduledTask }>(); public readonly onTaskScheduled = this.taskScheduledEmitter.event; + constructor(startTimeMs: number) { + this._nowMs = startTimeMs; + } + schedule(task: ScheduledTask): IDisposable { - if (task.time < this._now) { - throw new Error(`Scheduled time (${task.time}) must be equal to or greater than the current time (${this._now}).`); + if (task.time < this._nowMs) { + throw new Error(`Scheduled time (${task.time}) must be equal to or greater than the current time (${this._nowMs}).`); } const extendedTask: ExtendedScheduledTask = { ...task, id: this.taskCounter++ }; this.queue.add(extendedTask); @@ -55,7 +59,7 @@ export class TimeTravelScheduler implements Scheduler { } get now(): TimeOffset { - return this._now; + return this._nowMs; } get hasScheduledTasks(): boolean { @@ -69,7 +73,7 @@ export class TimeTravelScheduler implements Scheduler { runNext(): ScheduledTask | undefined { const task = this.queue.removeMin(); if (task) { - this._now = task.time; + this._nowMs = task.time; task.run(); } @@ -164,26 +168,30 @@ export class AsyncSchedulerProcessor extends Disposable { } -export async function runWithFakedTimers(options: { useFakeTimers?: boolean; useSetImmediate?: boolean; maxTaskCount?: number }, fn: () => Promise): Promise { +export async function runWithFakedTimers(options: { startTime?: number; useFakeTimers?: boolean; useSetImmediate?: boolean; maxTaskCount?: number }, fn: () => Promise): Promise { const useFakeTimers = options.useFakeTimers === undefined ? true : options.useFakeTimers; if (!useFakeTimers) { return fn(); } - const scheduler = new TimeTravelScheduler(); + const scheduler = new TimeTravelScheduler(options.startTime ?? 0); const schedulerProcessor = new AsyncSchedulerProcessor(scheduler, { useSetImmediate: options.useSetImmediate, maxTaskCount: options.maxTaskCount }); const globalInstallDisposable = scheduler.installGlobally(); + let didThrow = true; let result: T; try { result = await fn(); + didThrow = false; } finally { globalInstallDisposable.dispose(); try { - // We process the remaining scheduled tasks. - // The global override is no longer active, so during this, no more tasks will be scheduled. - await schedulerProcessor.waitForEmptyQueue(); + if (!didThrow) { + // We process the remaining scheduled tasks. + // The global override is no longer active, so during this, no more tasks will be scheduled. + await schedulerProcessor.waitForEmptyQueue(); + } } finally { schedulerProcessor.dispose(); } diff --git a/src/vs/base/test/common/types.test.ts b/src/vs/base/test/common/types.test.ts index 50139125802..f0812718722 100644 --- a/src/vs/base/test/common/types.test.ts +++ b/src/vs/base/test/common/types.test.ts @@ -905,4 +905,98 @@ suite('Types', () => { assert.throws(() => types.validateConstraints(['2'], [types.isNumber])); assert.throws(() => types.validateConstraints([1, 'test', true], [Number, String, Number])); }); + + suite('hasKey', () => { + test('should return true when object has specified key', () => { + type A = { a: string }; + type B = { b: number }; + const obj: A | B = { a: 'test' }; + + assert(types.hasKey(obj, { a: true })); + // After this check, TypeScript knows obj is type A + assert.strictEqual(obj.a, 'test'); + }); + + test('should return false when object does not have specified key', () => { + type A = { a: string }; + type B = { b: number }; + const obj: A | B = { b: 42 }; + + // @ts-expect-error + assert(!types.hasKey(obj, { a: true })); + }); + + test('should work with multiple keys', () => { + type A = { a: string; b: number }; + type B = { c: boolean }; + const obj: A | B = { a: 'test', b: 42 }; + + assert(types.hasKey(obj, { a: true, b: true })); + // After this check, TypeScript knows obj is type A + assert.strictEqual(obj.a, 'test'); + assert.strictEqual(obj.b, 42); + }); + + test('should return false if any key is missing', () => { + type A = { a: string; b: number }; + type B = { a: string }; + const obj: A | B = { a: 'test' }; + + assert(!types.hasKey(obj, { a: true, b: true })); + }); + + test('should work with empty key object', () => { + type A = { a: string }; + type B = { b: number }; + const obj: A | B = { a: 'test' }; + + // Empty key object should return true (all zero keys exist) + assert(types.hasKey(obj, {})); + }); + + test('should work with complex union types', () => { + type TypeA = { kind: 'a'; value: string }; + type TypeB = { kind: 'b'; count: number }; + type TypeC = { kind: 'c'; items: string[] }; + + const objA: TypeA | TypeB | TypeC = { kind: 'a', value: 'hello' }; + const objB: TypeA | TypeB | TypeC = { kind: 'b', count: 5 }; + + assert(types.hasKey(objA, { value: true })); + // @ts-expect-error + assert(!types.hasKey(objA, { count: true })); + // @ts-expect-error + assert(!types.hasKey(objA, { items: true })); + + // @ts-expect-error + assert(!types.hasKey(objB, { value: true })); + // @ts-expect-error + assert(types.hasKey(objB, { count: true })); + // @ts-expect-error + assert(!types.hasKey(objB, { items: true })); + }); + + test('should handle objects with optional properties', () => { + type A = { a: string; b?: number }; + type B = { c: boolean }; + const obj1: A | B = { a: 'test', b: 42 }; + const obj2: A | B = { a: 'test' }; + + assert(types.hasKey(obj1, { a: true })); + assert(types.hasKey(obj1, { b: true })); + + assert(types.hasKey(obj2, { a: true })); + assert(!types.hasKey(obj2, { b: true })); + }); + + test('should work with nested objects', () => { + type A = { data: { nested: string } }; + type B = { value: number }; + const obj: A | B = { data: { nested: 'test' } }; + + assert(types.hasKey(obj, { data: true })); + // @ts-expect-error + assert(!types.hasKey(obj, { value: true })); + }); + }); }); diff --git a/src/vs/base/test/common/uri.test.ts b/src/vs/base/test/common/uri.test.ts index 323789a764e..e2f22d32ef8 100644 --- a/src/vs/base/test/common/uri.test.ts +++ b/src/vs/base/test/common/uri.test.ts @@ -472,8 +472,8 @@ suite('URI', () => { }), true); assert.strictEqual(URI.isUri(1), false); - assert.strictEqual(URI.isUri("1"), false); - assert.strictEqual(URI.isUri("http://sample.com"), false); + assert.strictEqual(URI.isUri('1'), false); + assert.strictEqual(URI.isUri('http://sample.com'), false); assert.strictEqual(URI.isUri(null), false); assert.strictEqual(URI.isUri(undefined), false); }); @@ -487,7 +487,7 @@ suite('URI', () => { assert.strictEqual(isUriComponents(1), false); assert.strictEqual(isUriComponents(true), false); - assert.strictEqual(isUriComponents("true"), false); + assert.strictEqual(isUriComponents('true'), false); assert.strictEqual(isUriComponents({}), false); assert.strictEqual(isUriComponents({ scheme: '' }), true); // valid components but INVALID uri assert.strictEqual(isUriComponents({ scheme: 'fo' }), true); @@ -635,4 +635,15 @@ suite('URI', () => { assert.strictEqual(URI.parse('http://user@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html').toString(), 'http://user@[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:80/index.html'); assert.strictEqual(URI.parse('http://us[er@[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html').toString(), 'http://us%5Ber@[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:80/index.html'); }); + + test('File paths containing apostrophes break URI parsing and cannot be opened #276075', function () { + if (isWindows) { + const filePath = 'C:\\Users\\Abd-al-Haseeb\'s_Dell\\Studio\\w3mage\\wp-content\\database.ht.sqlite'; + const uri = URI.file(filePath); + assert.strictEqual(uri.path, '/C:/Users/Abd-al-Haseeb\'s_Dell/Studio/w3mage/wp-content/database.ht.sqlite'); + assert.strictEqual(uri.fsPath, 'c:\\Users\\Abd-al-Haseeb\'s_Dell\\Studio\\w3mage\\wp-content\\database.ht.sqlite'); + } + }); + + }); diff --git a/src/vs/base/test/common/yaml.test.ts b/src/vs/base/test/common/yaml.test.ts index 2a778e22e6b..c6e3a53e7cc 100644 --- a/src/vs/base/test/common/yaml.test.ts +++ b/src/vs/base/test/common/yaml.test.ts @@ -6,6 +6,7 @@ import { deepStrictEqual, strictEqual, ok } from 'assert'; import { parse, ParseOptions, YamlParseError, Position, YamlNode } from '../../common/yaml.js'; import { ensureNoDisposablesAreLeakedInTestSuite } from './utils.js'; + function assertValidParse(input: string[], expected: YamlNode, expectedErrors: YamlParseError[], options?: ParseOptions): void { const errors: YamlParseError[] = []; const text = input.join('\n'); @@ -85,6 +86,36 @@ suite('YAML Parser', () => { }, []); }); + test('value on next line', () => { + assertValidParse( + [ + 'name:', + ' John Doe', + 'colors:', + ' [ Red, Green, Blue ]', + ], + { + type: 'object', start: pos(0, 0), end: pos(3, 22), properties: [ + { + key: { type: 'string', start: pos(0, 0), end: pos(0, 4), value: 'name' }, + value: { type: 'string', start: pos(1, 2), end: pos(1, 10), value: 'John Doe' } + }, + { + key: { type: 'string', start: pos(2, 0), end: pos(2, 6), value: 'colors' }, + value: { + type: 'array', start: pos(3, 2), end: pos(3, 22), items: [ + { type: 'string', start: pos(3, 4), end: pos(3, 7), value: 'Red' }, + { type: 'string', start: pos(3, 9), end: pos(3, 14), value: 'Green' }, + { type: 'string', start: pos(3, 16), end: pos(3, 20), value: 'Blue' } + ] + } + } + ] + }, + [] + ); + }); + test('multiple properties', () => { assertValidParse( [ @@ -759,7 +790,7 @@ suite('YAML Parser', () => { }, [ { - message: "Duplicate key 'key'", + message: 'Duplicate key \'key\'', code: 'duplicateKey', start: pos(1, 0), end: pos(1, 3) @@ -874,7 +905,7 @@ suite('YAML Parser', () => { test('empty object with only colons', () => { // Test object with empty values assertValidParse( - ["key1:", "key2:", "key3:"], + ['key1:', 'key2:', 'key3:'], { type: 'object', start: pos(0, 0), end: pos(2, 5), properties: [ { @@ -943,11 +974,11 @@ suite('YAML Parser', () => { // Test malformed arrays that might cause position advancement issues assertValidParse( [ - "key: [", - "", - "", - "", - "" + 'key: [', + '', + '', + '', + '' ], { type: 'object', start: pos(0, 0), end: pos(5, 0), properties: [ @@ -965,11 +996,11 @@ suite('YAML Parser', () => { // Test structures that might appear self-referential assertValidParse( [ - "a:", - " b:", - " a:", - " b:", - " value: test" + 'a:', + ' b:', + ' a:', + ' b:', + ' value: test' ], { type: 'object', start: pos(0, 0), end: pos(4, 19), properties: [ @@ -1014,7 +1045,7 @@ suite('YAML Parser', () => { test('array with empty lines', () => { // Test arrays spanning multiple lines with empty lines assertValidParse( - ["arr: [", "", "item1,", "", "item2", "", "]"], + ['arr: [', '', 'item1,', '', 'item2', '', ']'], { type: 'object', start: pos(0, 0), end: pos(6, 1), properties: [ { diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index f2abf379f08..533cb26ae8e 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -131,7 +131,7 @@ class ServerKeyedAESCrypto implements ISecretStorageCrypto { const keyData = new Uint8Array(AESConstants.KEY_LENGTH / 8); for (let i = 0; i < keyData.byteLength; i++) { - keyData[i] = clientKey[i]! ^ serverKey[i]!; + keyData[i] = clientKey[i] ^ serverKey[i]; } return mainWindow.crypto.subtle.importKey( @@ -223,6 +223,7 @@ export class LocalStorageSecretStorageProvider implements ISecretStorageProvider private loadAuthSessionFromElement(): Record { let authSessionInfo: (AuthenticationSessionInfo & { scopes: string[][] }) | undefined; + // eslint-disable-next-line no-restricted-syntax const authSessionElement = mainWindow.document.getElementById('vscode-workbench-auth-session'); const authSessionElementAttribute = authSessionElement ? authSessionElement.getAttribute('data-settings') : undefined; if (authSessionElementAttribute) { @@ -597,6 +598,7 @@ function readCookie(name: string): string | undefined { (function () { // Find config by checking for DOM + // eslint-disable-next-line no-restricted-syntax const configElement = mainWindow.document.getElementById('vscode-workbench-web-configuration'); const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined; if (!configElement || !configElementAttribute) { diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index fb06a689254..35ea469b72a 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -18,7 +18,7 @@ import { getPathLabel } from '../../base/common/labels.js'; import { Schemas } from '../../base/common/network.js'; import { basename, resolve } from '../../base/common/path.js'; import { mark } from '../../base/common/performance.js'; -import { IProcessEnvironment, isMacintosh, isWindows, OS } from '../../base/common/platform.js'; +import { IProcessEnvironment, isLinux, isMacintosh, isWindows, OS } from '../../base/common/platform.js'; import { cwd } from '../../base/common/process.js'; import { rtrim, trim } from '../../base/common/strings.js'; import { Promises as FSPromises } from '../../base/node/pfs.js'; @@ -73,6 +73,7 @@ import { SaveStrategy, StateService } from '../../platform/state/node/stateServi import { FileUserDataProvider } from '../../platform/userData/common/fileUserDataProvider.js'; import { addUNCHostToAllowlist, getUNCHost } from '../../base/node/unc.js'; import { ThemeMainService } from '../../platform/theme/electron-main/themeMainServiceImpl.js'; +import { LINUX_SYSTEM_POLICY_FILE_PATH } from '../../base/common/policy.js'; /** * The main VS Code entry point. @@ -204,6 +205,8 @@ class CodeMain { policyService = disposables.add(new NativePolicyService(logService, productService.win32RegValueName)); } else if (isMacintosh && productService.darwinBundleIdentifier) { policyService = disposables.add(new NativePolicyService(logService, productService.darwinBundleIdentifier)); + } else if (isLinux) { + policyService = disposables.add(new FilePolicyService(URI.file(LINUX_SYSTEM_POLICY_FILE_PATH), fileService, logService)); } else if (environmentMainService.policyFile) { policyService = disposables.add(new FilePolicyService(environmentMainService.policyFile, fileService, logService)); } else { @@ -313,11 +316,6 @@ class CodeMain { throw error; } - // Since we are the second instance, we do not want to show the dock - if (isMacintosh) { - app.dock?.hide(); - } - // there's a running instance, let's connect to it let client: NodeIPCClient; try { @@ -417,11 +415,6 @@ class CodeMain { throw new ExpectedError('Terminating...'); } - // dock might be hidden at this case due to a retry - if (isMacintosh) { - app.dock?.show(); - } - // Set the VSCODE_PID variable here when we are sure we are the first // instance to startup. Otherwise we would wrongly overwrite the PID process.env['VSCODE_PID'] = String(process.pid); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 89c66b9b404..5c52caf40c2 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -183,7 +183,7 @@ export async function main(argv: string[]): Promise { try { // Check for readonly status and chmod if so if we are told so - let targetMode: number = 0; + let targetMode = 0; let restoreMode = false; if (args['file-chmod']) { targetMode = statSync(target).mode; diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index da60ab85a19..e0a2115ade8 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -12,7 +12,7 @@ import { isSigPipeError, onUnexpectedError, setUnexpectedErrorHandler } from '.. import { Disposable } from '../../base/common/lifecycle.js'; import { Schemas } from '../../base/common/network.js'; import { isAbsolute, join } from '../../base/common/path.js'; -import { isWindows, isMacintosh } from '../../base/common/platform.js'; +import { isWindows, isMacintosh, isLinux } from '../../base/common/platform.js'; import { cwd } from '../../base/common/process.js'; import { URI } from '../../base/common/uri.js'; import { IConfigurationService } from '../../platform/configuration/common/configuration.js'; @@ -76,6 +76,7 @@ import { McpGalleryService } from '../../platform/mcp/common/mcpGalleryService.j import { AllowedMcpServersService } from '../../platform/mcp/common/allowedMcpServersService.js'; import { IMcpGalleryManifestService } from '../../platform/mcp/common/mcpGalleryManifest.js'; import { McpGalleryManifestService } from '../../platform/mcp/common/mcpGalleryManifestService.js'; +import { LINUX_SYSTEM_POLICY_FILE_PATH } from '../../base/common/policy.js'; class CliMain extends Disposable { @@ -182,6 +183,8 @@ class CliMain extends Disposable { policyService = this._register(new NativePolicyService(logService, productService.win32RegValueName)); } else if (isMacintosh && productService.darwinBundleIdentifier) { policyService = this._register(new NativePolicyService(logService, productService.darwinBundleIdentifier)); + } else if (isLinux) { + policyService = this._register(new FilePolicyService(URI.file(LINUX_SYSTEM_POLICY_FILE_PATH), fileService, logService)); } else if (environmentService.policyFile) { policyService = this._register(new FilePolicyService(environmentService.policyFile, fileService, logService)); } else { diff --git a/src/vs/editor/browser/config/elementSizeObserver.ts b/src/vs/editor/browser/config/elementSizeObserver.ts index f6c6ac5e926..c1f886e2c35 100644 --- a/src/vs/editor/browser/config/elementSizeObserver.ts +++ b/src/vs/editor/browser/config/elementSizeObserver.ts @@ -47,10 +47,10 @@ export class ElementSizeObserver extends Disposable { // Otherwise we will postpone to the next animation frame. // We'll use `observeContentRect` to store the content rect we received. - let observedDimenstion: IDimension | null = null; + let observedDimension: IDimension | null = null; const observeNow = () => { - if (observedDimenstion) { - this.observe({ width: observedDimenstion.width, height: observedDimenstion.height }); + if (observedDimension) { + this.observe({ width: observedDimension.width, height: observedDimension.height }); } else { this.observe(); } @@ -76,9 +76,9 @@ export class ElementSizeObserver extends Disposable { this._resizeObserver = new ResizeObserver((entries) => { if (entries && entries[0] && entries[0].contentRect) { - observedDimenstion = { width: entries[0].contentRect.width, height: entries[0].contentRect.height }; + observedDimension = { width: entries[0].contentRect.width, height: entries[0].contentRect.height }; } else { - observedDimenstion = null; + observedDimension = null; } shouldObserve = true; update(); diff --git a/src/vs/editor/browser/config/fontMeasurements.ts b/src/vs/editor/browser/config/fontMeasurements.ts index d9a5cb897d9..759add4ccc8 100644 --- a/src/vs/editor/browser/config/fontMeasurements.ts +++ b/src/vs/editor/browser/config/fontMeasurements.ts @@ -271,7 +271,7 @@ class FontMeasurementsCache { this._values[itemId] = value; } - public remove(item: BareFontInfo): void { + public remove(item: FontInfo): void { const itemId = item.getId(); delete this._keys[itemId]; delete this._values[itemId]; diff --git a/src/vs/editor/browser/config/migrateOptions.ts b/src/vs/editor/browser/config/migrateOptions.ts index 1d5584c88ab..5ecd03e14a0 100644 --- a/src/vs/editor/browser/config/migrateOptions.ts +++ b/src/vs/editor/browser/config/migrateOptions.ts @@ -251,3 +251,10 @@ registerEditorSettingMigration('inlineSuggest.edits.codeShifting', (value, read, write('inlineSuggest.edits.allowCodeShifting', value ? 'always' : 'never'); } }); + +// Migrate Hover +registerEditorSettingMigration('hover.enabled', (value, read, write) => { + if (typeof value === 'boolean') { + write('hover.enabled', value ? 'on' : 'off'); + } +}); diff --git a/src/vs/editor/browser/config/tabFocus.ts b/src/vs/editor/browser/config/tabFocus.ts index 6d821bc2725..4cf0b237248 100644 --- a/src/vs/editor/browser/config/tabFocus.ts +++ b/src/vs/editor/browser/config/tabFocus.ts @@ -4,10 +4,11 @@ *--------------------------------------------------------------------------------------------*/ import { Emitter, Event } from '../../../base/common/event.js'; +import { Disposable } from '../../../base/common/lifecycle.js'; -class TabFocusImpl { +class TabFocusImpl extends Disposable { private _tabFocus: boolean = false; - private readonly _onDidChangeTabFocus = new Emitter(); + private readonly _onDidChangeTabFocus = this._register(new Emitter()); public readonly onDidChangeTabFocus: Event = this._onDidChangeTabFocus.event; public getTabFocusMode(): boolean { diff --git a/src/vs/editor/browser/controller/editContext/native/nativeEditContext.ts b/src/vs/editor/browser/controller/editContext/native/nativeEditContext.ts index 5d10e6e9f8a..b417161930f 100644 --- a/src/vs/editor/browser/controller/editContext/native/nativeEditContext.ts +++ b/src/vs/editor/browser/controller/editContext/native/nativeEditContext.ts @@ -14,7 +14,7 @@ import { EditorOption } from '../../../../common/config/editorOptions.js'; import { EndOfLinePreference, IModelDeltaDecoration } from '../../../../common/model.js'; import { ViewConfigurationChangedEvent, ViewCursorStateChangedEvent, ViewDecorationsChangedEvent, ViewFlushedEvent, ViewLinesChangedEvent, ViewLinesDeletedEvent, ViewLinesInsertedEvent, ViewScrollChangedEvent, ViewZonesChangedEvent } from '../../../../common/viewEvents.js'; import { ViewContext } from '../../../../common/viewModel/viewContext.js'; -import { RestrictedRenderingContext, RenderingContext } from '../../../view/renderingContext.js'; +import { RestrictedRenderingContext, RenderingContext, HorizontalPosition } from '../../../view/renderingContext.js'; import { ViewController } from '../../../view/viewController.js'; import { ClipboardEventUtils, ClipboardStoredMetadata, getDataToCopy, InMemoryClipboardMetadataManager } from '../clipboardUtils.js'; import { AbstractEditContext } from '../editContext.js'; @@ -60,7 +60,7 @@ export class NativeEditContext extends AbstractEditContext { private _editContextPrimarySelection: Selection = new Selection(1, 1, 1, 1); // Overflow guard container - private _parent: HTMLElement | undefined; + private readonly _parent: HTMLElement; private _decorations: string[] = []; private _primarySelection: Selection = new Selection(1, 1, 1, 1); @@ -241,9 +241,13 @@ export class NativeEditContext extends AbstractEditContext { return this._primarySelection.getPosition(); } - public prepareRender(ctx: RenderingContext): void { + public override prepareRender(ctx: RenderingContext): void { this._screenReaderSupport.prepareRender(ctx); - this._updateSelectionAndControlBounds(ctx); + this._updateSelectionAndControlBoundsData(ctx); + } + + public override onDidRender(): void { + this._updateSelectionAndControlBoundsAfterRender(); } public render(ctx: RestrictedRenderingContext): void { @@ -483,26 +487,35 @@ export class NativeEditContext extends AbstractEditContext { this._decorations = this._context.viewModel.model.deltaDecorations(this._decorations, decorations); } - private _updateSelectionAndControlBounds(ctx: RenderingContext) { - if (!this._parent) { - return; + private _linesVisibleRanges: HorizontalPosition | null = null; + private _updateSelectionAndControlBoundsData(ctx: RenderingContext): void { + const viewSelection = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(this._primarySelection); + if (this._primarySelection.isEmpty()) { + const linesVisibleRanges = ctx.visibleRangeForPosition(viewSelection.getStartPosition()); + this._linesVisibleRanges = linesVisibleRanges; + } else { + this._linesVisibleRanges = null; } + } + + private _updateSelectionAndControlBoundsAfterRender() { const options = this._context.configuration.options; const contentLeft = options.get(EditorOption.layoutInfo).contentLeft; - const parentBounds = this._parent.getBoundingClientRect(); + const viewSelection = this._context.viewModel.coordinatesConverter.convertModelRangeToViewRange(this._primarySelection); const verticalOffsetStart = this._context.viewLayout.getVerticalOffsetForLineNumber(viewSelection.startLineNumber); - - const top = parentBounds.top + verticalOffsetStart - this._scrollTop; const verticalOffsetEnd = this._context.viewLayout.getVerticalOffsetAfterLineNumber(viewSelection.endLineNumber); + + // Make sure this doesn't force an extra layout (i.e. don't call it before rendering finished) + const parentBounds = this._parent.getBoundingClientRect(); + const top = parentBounds.top + verticalOffsetStart - this._scrollTop; const height = verticalOffsetEnd - verticalOffsetStart; let left = parentBounds.left + contentLeft - this._scrollLeft; let width: number; if (this._primarySelection.isEmpty()) { - const linesVisibleRanges = ctx.visibleRangeForPosition(viewSelection.getStartPosition()); - if (linesVisibleRanges) { - left += linesVisibleRanges.left; + if (this._linesVisibleRanges) { + left += this._linesVisibleRanges.left; } width = 0; } else { @@ -515,9 +528,6 @@ export class NativeEditContext extends AbstractEditContext { } private _updateCharacterBounds(e: CharacterBoundsUpdateEvent): void { - if (!this._parent) { - return; - } const options = this._context.configuration.options; const typicalHalfWidthCharacterWidth = options.get(EditorOption.fontInfo).typicalHalfwidthCharacterWidth; const contentLeft = options.get(EditorOption.layoutInfo).contentLeft; diff --git a/src/vs/editor/browser/controller/mouseHandler.ts b/src/vs/editor/browser/controller/mouseHandler.ts index efcb3419d24..9c9b398eb37 100644 --- a/src/vs/editor/browser/controller/mouseHandler.ts +++ b/src/vs/editor/browser/controller/mouseHandler.ts @@ -340,7 +340,7 @@ export class MouseHandler extends ViewEventHandler { this._mouseDownOperation.start(t.type, e, pointerId); e.preventDefault(); } - } else if (targetIsWidget && this.viewHelper.shouldSuppressMouseDownOnWidget(t.detail)) { + } else if (targetIsWidget && this.viewHelper.shouldSuppressMouseDownOnWidget(t.detail)) { focus(); e.preventDefault(); } diff --git a/src/vs/editor/browser/controller/mouseTarget.ts b/src/vs/editor/browser/controller/mouseTarget.ts index 2d8f3f28d5e..8256f6b487c 100644 --- a/src/vs/editor/browser/controller/mouseTarget.ts +++ b/src/vs/editor/browser/controller/mouseTarget.ts @@ -448,7 +448,7 @@ class HitTestRequest extends BareHitTestRequest { } public override toString(): string { - return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), relativePos(${this.relativePos.x},${this.relativePos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? (this.target).outerHTML : null}`; + return `pos(${this.pos.x},${this.pos.y}), editorPos(${this.editorPos.x},${this.editorPos.y}), relativePos(${this.relativePos.x},${this.relativePos.y}), mouseVerticalOffset: ${this.mouseVerticalOffset}, mouseContentHorizontalOffset: ${this.mouseContentHorizontalOffset}\n\ttarget: ${this.target ? this.target.outerHTML : null}`; } public get wouldBenefitFromHitTestTargetSwitch(): boolean { @@ -481,7 +481,8 @@ class HitTestRequest extends BareHitTestRequest { return MouseTarget.createMargin(type, this.target, this._getMouseColumn(position), position, range, detail); } public fulfillViewZone(type: MouseTargetType.GUTTER_VIEW_ZONE | MouseTargetType.CONTENT_VIEW_ZONE, position: Position, detail: IMouseTargetViewZoneData): IMouseTargetViewZone { - return MouseTarget.createViewZone(type, this.target, this._getMouseColumn(position), position, detail); + // Always return the usual mouse column for a view zone. + return MouseTarget.createViewZone(type, this.target, this._getMouseColumn(), position, detail); } public fulfillContentText(position: Position, range: EditorRange | null, detail: IMouseTargetContentTextData): IMouseTargetContentText { return MouseTarget.createContentText(this.target, this._getMouseColumn(position), position, range, detail); @@ -1027,7 +1028,7 @@ export class MouseTargetFactory { const parent2ClassName = parent2 && parent2.nodeType === parent2.ELEMENT_NODE ? (parent2).className : null; if (parent2ClassName === ViewLine.CLASS_NAME) { - return HitTestResult.createFromDOMInfo(ctx, startContainer, (startContainer).textContent!.length); + return HitTestResult.createFromDOMInfo(ctx, startContainer, (startContainer).textContent.length); } else { return new UnknownHitTestResult(startContainer); } diff --git a/src/vs/editor/browser/coreCommands.ts b/src/vs/editor/browser/coreCommands.ts index 186c83dfe5b..a1d6137f875 100644 --- a/src/vs/editor/browser/coreCommands.ts +++ b/src/vs/editor/browser/coreCommands.ts @@ -31,6 +31,7 @@ import { IViewModel } from '../common/viewModel.js'; import { ISelection } from '../common/core/selection.js'; import { getActiveElement, isEditableElement } from '../../base/browser/dom.js'; import { EnterOperation } from '../common/cursor/cursorTypeEditOperations.js'; +import { TextEditorSelectionSource } from '../../platform/editor/common/editor.js'; const CORE_WEIGHT = KeybindingWeight.EditorCore; @@ -604,13 +605,16 @@ export namespace CoreNavigationCommands { } private _runCursorMove(viewModel: IViewModel, source: string | null | undefined, args: CursorMove_.ParsedArguments): void { + // If noHistory is true, use PROGRAMMATIC source to prevent adding to navigation history + const effectiveSource = args.noHistory ? TextEditorSelectionSource.PROGRAMMATIC : source; + viewModel.model.pushStackElement(); viewModel.setCursorStates( - source, + effectiveSource, CursorChangeReason.Explicit, CursorMoveImpl._move(viewModel, viewModel.getCursorStates(), args) ); - viewModel.revealAllCursors(source, true); + viewModel.revealAllCursors(effectiveSource, true); } private static _move(viewModel: IViewModel, cursors: CursorState[], args: CursorMove_.ParsedArguments): PartialCursorState[] | null { @@ -1319,8 +1323,7 @@ export namespace CoreNavigationCommands { EditorScroll_.Unit.WrappedLine, EditorScroll_.Unit.Page, EditorScroll_.Unit.HalfPage, - EditorScroll_.Unit.Editor, - EditorScroll_.Unit.Column + EditorScroll_.Unit.Editor ]; const horizontalDirections = [EditorScroll_.Direction.Left, EditorScroll_.Direction.Right]; const verticalDirections = [EditorScroll_.Direction.Up, EditorScroll_.Direction.Down]; diff --git a/src/vs/editor/browser/dataTransfer.ts b/src/vs/editor/browser/dataTransfer.ts index 014c3cdac21..10f1b3e0b9a 100644 --- a/src/vs/editor/browser/dataTransfer.ts +++ b/src/vs/editor/browser/dataTransfer.ts @@ -29,7 +29,7 @@ export function toVSDataTransfer(dataTransfer: DataTransfer): VSDataTransfer { function createFileDataTransferItemFromFile(file: File): IDataTransferItem { const path = getPathForFile(file); - const uri = path ? URI.parse(path!) : undefined; + const uri = path ? URI.parse(path) : undefined; return createFileDataTransferItem(file.name, uri, async () => { return new Uint8Array(await file.arrayBuffer()); }); diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index c2cb0d3d596..502528a1a52 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -272,7 +272,7 @@ export interface IOverlayWidgetPosition { * When set, stacks with other overlay widgets with the same preference, * in an order determined by the ordinal value. */ - stackOridinal?: number; + stackOrdinal?: number; } /** * An overlay widgets renders on top of the text. @@ -825,6 +825,8 @@ export interface ICodeEditor extends editorCommon.IEditor { */ readonly onEndUpdate: Event; + readonly onDidChangeViewZones: Event; + /** * Saves current view state of the editor in a serializable object. */ @@ -1012,6 +1014,11 @@ export interface ICodeEditor extends editorCommon.IEditor { */ executeCommands(source: string | null | undefined, commands: (editorCommon.ICommand | null)[]): void; + /** + * Scroll vertically or horizontally as necessary and reveal the current cursors. + */ + revealAllCursors(revealHorizontal: boolean, minimalReveal?: boolean): void; + /** * @internal */ diff --git a/src/vs/editor/browser/editorExtensions.ts b/src/vs/editor/browser/editorExtensions.ts index e175a348e03..d5961dd4f1e 100644 --- a/src/vs/editor/browser/editorExtensions.ts +++ b/src/vs/editor/browser/editorExtensions.ts @@ -25,6 +25,7 @@ import { IDisposable } from '../../base/common/lifecycle.js'; import { KeyMod, KeyCode } from '../../base/common/keyCodes.js'; import { ILogService } from '../../platform/log/common/log.js'; import { getActiveElement } from '../../base/browser/dom.js'; +import { TriggerInlineEditCommandsRegistry } from './triggerInlineEditCommandsRegistry.js'; export type ServicesAccessor = InstantiationServicesAccessor; export type EditorContributionCtor = IConstructorSignature; @@ -98,6 +99,7 @@ export interface ICommandOptions { kbOpts?: ICommandKeybindingsOptions | ICommandKeybindingsOptions[]; metadata?: ICommandMetadata; menuOpts?: ICommandMenuOptions | ICommandMenuOptions[]; + canTriggerInlineEdits?: boolean; } export abstract class Command { public readonly id: string; @@ -105,6 +107,7 @@ export abstract class Command { private readonly _kbOpts: ICommandKeybindingsOptions | ICommandKeybindingsOptions[] | undefined; private readonly _menuOpts: ICommandMenuOptions | ICommandMenuOptions[] | undefined; public readonly metadata: ICommandMetadata | undefined; + public readonly canTriggerInlineEdits: boolean | undefined; constructor(opts: ICommandOptions) { this.id = opts.id; @@ -112,6 +115,7 @@ export abstract class Command { this._kbOpts = opts.kbOpts; this._menuOpts = opts.menuOpts; this.metadata = opts.metadata; + this.canTriggerInlineEdits = opts.canTriggerInlineEdits; } public register(): void { @@ -155,6 +159,10 @@ export abstract class Command { handler: (accessor, args) => this.runCommand(accessor, args), metadata: this.metadata }); + + if (this.canTriggerInlineEdits) { + TriggerInlineEditCommandsRegistry.registerCommand(this.id); + } } private _registerMenuItem(item: ICommandMenuOptions): void { diff --git a/src/vs/editor/browser/observableCodeEditor.ts b/src/vs/editor/browser/observableCodeEditor.ts index 5af51f2cf79..212ed57e7be 100644 --- a/src/vs/editor/browser/observableCodeEditor.ts +++ b/src/vs/editor/browser/observableCodeEditor.ts @@ -5,7 +5,7 @@ import { equalsIfDefined, itemsEquals } from '../../base/common/equals.js'; import { Disposable, DisposableStore, IDisposable, toDisposable } from '../../base/common/lifecycle.js'; -import { DebugLocation, IObservable, IObservableWithChange, ITransaction, TransactionImpl, autorun, autorunOpts, derived, derivedOpts, derivedWithSetter, observableFromEvent, observableSignal, observableValue, observableValueOpts } from '../../base/common/observable.js'; +import { DebugLocation, IObservable, IObservableWithChange, ITransaction, TransactionImpl, autorun, autorunOpts, derived, derivedOpts, derivedWithSetter, observableFromEvent, observableSignal, observableSignalFromEvent, observableValue, observableValueOpts } from '../../base/common/observable.js'; import { EditorOption, FindComputedEditorOptionValueById } from '../common/config/editorOptions.js'; import { LineRange } from '../common/core/ranges/lineRange.js'; import { OffsetRange } from '../common/core/ranges/offsetRange.js'; @@ -148,6 +148,9 @@ export class ObservableCodeEditor extends Disposable { this.layoutInfoVerticalScrollbarWidth = this.layoutInfo.map(l => l.verticalScrollbarWidth); this.contentWidth = observableFromEvent(this.editor.onDidContentSizeChange, () => this.editor.getContentWidth()); this.contentHeight = observableFromEvent(this.editor.onDidContentSizeChange, () => this.editor.getContentHeight()); + this._onDidChangeViewZones = observableSignalFromEvent(this, this.editor.onDidChangeViewZones); + this._onDidHiddenAreasChanged = observableSignalFromEvent(this, this.editor.onDidChangeHiddenAreas); + this._onDidLineHeightChanged = observableSignalFromEvent(this, this.editor.onDidChangeLineHeight); this._widgetCounter = 0; this.openedPeekWidgets = observableValue(this, 0); @@ -456,6 +459,37 @@ export class ObservableCodeEditor extends Disposable { }); } + private readonly _onDidChangeViewZones; + private readonly _onDidHiddenAreasChanged; + private readonly _onDidLineHeightChanged; + + /** + * Get the vertical position (top offset) for the line's bottom w.r.t. to the first line. + */ + observeTopForLineNumber(lineNumber: number): IObservable { + return derived(reader => { + this.layoutInfo.read(reader); + this._onDidChangeViewZones.read(reader); + this._onDidHiddenAreasChanged.read(reader); + this._onDidLineHeightChanged.read(reader); + this._versionId.read(reader); + return this.editor.getTopForLineNumber(lineNumber); + }); + } + + /** + * Get the vertical position (top offset) for the line's bottom w.r.t. to the first line. + */ + observeBottomForLineNumber(lineNumber: number): IObservable { + return derived(reader => { + this.layoutInfo.read(reader); + this._onDidChangeViewZones.read(reader); + this._onDidHiddenAreasChanged.read(reader); + this._onDidLineHeightChanged.read(reader); + this._versionId.read(reader); + return this.editor.getBottomForLineNumber(lineNumber); + }); + } } interface IObservableOverlayWidget { diff --git a/src/vs/editor/browser/services/contribution.ts b/src/vs/editor/browser/services/contribution.ts new file mode 100644 index 00000000000..e1a39059b0d --- /dev/null +++ b/src/vs/editor/browser/services/contribution.ts @@ -0,0 +1,10 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerSingleton, InstantiationType } from '../../../platform/instantiation/common/extensions.js'; +import { IEditorWorkerService } from '../../common/services/editorWorker.js'; +import { EditorWorkerService } from './editorWorkerService.js'; + +registerSingleton(IEditorWorkerService, EditorWorkerService, InstantiationType.Eager /* registers link detection and word based suggestions for any document */); diff --git a/src/vs/editor/browser/services/editorWorkerService.ts b/src/vs/editor/browser/services/editorWorkerService.ts index d8cd71a153f..0a221ebefaf 100644 --- a/src/vs/editor/browser/services/editorWorkerService.ts +++ b/src/vs/editor/browser/services/editorWorkerService.ts @@ -7,7 +7,8 @@ import { timeout } from '../../../base/common/async.js'; import { Disposable, IDisposable } from '../../../base/common/lifecycle.js'; import { URI } from '../../../base/common/uri.js'; import { logOnceWebWorkerWarning, IWebWorkerClient, Proxied } from '../../../base/common/worker/webWorker.js'; -import { createWebWorker, IWebWorkerDescriptor } from '../../../base/browser/webWorkerFactory.js'; +import { WebWorkerDescriptor } from '../../../platform/webWorker/browser/webWorkerDescriptor.js'; +import { IWebWorkerService } from '../../../platform/webWorker/browser/webWorkerService.js'; import { Position } from '../../common/core/position.js'; import { IRange, Range } from '../../common/core/range.js'; import { ITextModel } from '../../common/model.js'; @@ -35,6 +36,7 @@ import { WorkerTextModelSyncClient } from '../../common/services/textModelSync/t import { EditorWorkerHost } from '../../common/services/editorWorkerHost.js'; import { StringEdit } from '../../common/core/edits/stringEdit.js'; import { OffsetRange } from '../../common/core/ranges/offsetRange.js'; +import { FileAccess } from '../../../base/common/network.js'; /** * Stop the worker if it was not needed for 5 min. @@ -52,7 +54,7 @@ function canSyncModel(modelService: IModelService, resource: URI): boolean { return true; } -export abstract class EditorWorkerService extends Disposable implements IEditorWorkerService { +export class EditorWorkerService extends Disposable implements IEditorWorkerService { declare readonly _serviceBrand: undefined; @@ -61,16 +63,23 @@ export abstract class EditorWorkerService extends Disposable implements IEditorW private readonly _logService: ILogService; constructor( - workerDescriptor: IWebWorkerDescriptor, @IModelService modelService: IModelService, @ITextResourceConfigurationService configurationService: ITextResourceConfigurationService, @ILogService logService: ILogService, @ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService, @ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService, + @IWebWorkerService private readonly _webWorkerService: IWebWorkerService, ) { super(); this._modelService = modelService; - this._workerManager = this._register(new WorkerManager(workerDescriptor, this._modelService)); + + const workerDescriptor = new WebWorkerDescriptor({ + esmModuleLocation: () => FileAccess.asBrowserUri('vs/editor/common/services/editorWebWorkerMain.js'), + esmModuleLocationBundler: () => new URL('../../common/services/editorWebWorkerMain.ts?worker', import.meta.url), + label: 'editorWorkerService' + }); + + this._workerManager = this._register(new WorkerManager(workerDescriptor, this._modelService, this._webWorkerService)); this._logService = logService; // register default link-provider and default completions-provider @@ -326,15 +335,18 @@ class WordBasedCompletionItemProvider implements languages.CompletionItemProvide class WorkerManager extends Disposable { private readonly _modelService: IModelService; + private readonly _webWorkerService: IWebWorkerService; private _editorWorkerClient: EditorWorkerClient | null; private _lastWorkerUsedTime: number; constructor( - private readonly _workerDescriptor: IWebWorkerDescriptor, - @IModelService modelService: IModelService + private readonly _workerDescriptor: WebWorkerDescriptor, + @IModelService modelService: IModelService, + @IWebWorkerService webWorkerService: IWebWorkerService ) { super(); this._modelService = modelService; + this._webWorkerService = webWorkerService; this._editorWorkerClient = null; this._lastWorkerUsedTime = (new Date()).getTime(); @@ -386,7 +398,7 @@ class WorkerManager extends Disposable { public withWorker(): Promise { this._lastWorkerUsedTime = (new Date()).getTime(); if (!this._editorWorkerClient) { - this._editorWorkerClient = new EditorWorkerClient(this._workerDescriptor, false, this._modelService); + this._editorWorkerClient = new EditorWorkerClient(this._workerDescriptor, false, this._modelService, this._webWorkerService); } return Promise.resolve(this._editorWorkerClient); } @@ -421,18 +433,21 @@ export interface IEditorWorkerClient { export class EditorWorkerClient extends Disposable implements IEditorWorkerClient { private readonly _modelService: IModelService; + private readonly _webWorkerService: IWebWorkerService; private readonly _keepIdleModels: boolean; private _worker: IWebWorkerClient | null; private _modelManager: WorkerTextModelSyncClient | null; private _disposed = false; constructor( - private readonly _workerDescriptorOrWorker: IWebWorkerDescriptor | Worker | Promise, + private readonly _workerDescriptorOrWorker: WebWorkerDescriptor | Worker | Promise, keepIdleModels: boolean, @IModelService modelService: IModelService, + @IWebWorkerService webWorkerService: IWebWorkerService ) { super(); this._modelService = modelService; + this._webWorkerService = webWorkerService; this._keepIdleModels = keepIdleModels; this._worker = null; this._modelManager = null; @@ -446,7 +461,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien private _getOrCreateWorker(): IWebWorkerClient { if (!this._worker) { try { - this._worker = this._register(createWebWorker(this._workerDescriptorOrWorker)); + this._worker = this._register(this._webWorkerService.createWorkerClient(this._workerDescriptorOrWorker)); EditorWorkerHost.setChannel(this._worker, this._createEditorWorkerHost()); } catch (err) { logOnceWebWorkerWarning(err); diff --git a/src/vs/editor/browser/services/inlineCompletionsService.ts b/src/vs/editor/browser/services/inlineCompletionsService.ts index 260d617e7af..0f8fcc0cfdb 100644 --- a/src/vs/editor/browser/services/inlineCompletionsService.ts +++ b/src/vs/editor/browser/services/inlineCompletionsService.ts @@ -222,7 +222,7 @@ export class SnoozeInlineCompletion extends Action2 { ]; const picked = await quickInputService.pick(items, { - placeHolder: localize('snooze.placeholder', "Select snooze duration for Code completions and NES"), + placeHolder: localize('snooze.placeholder', "Select snooze duration for Inline Suggestions"), activeItem: items.find(item => item.value === lastSelectedDuration), }); diff --git a/src/vs/editor/browser/triggerInlineEditCommandsRegistry.ts b/src/vs/editor/browser/triggerInlineEditCommandsRegistry.ts new file mode 100644 index 00000000000..21cd1c5fe1d --- /dev/null +++ b/src/vs/editor/browser/triggerInlineEditCommandsRegistry.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Registry for commands that can trigger Inline Edits (NES) when invoked. + */ +export abstract class TriggerInlineEditCommandsRegistry { + + private static REGISTERED_COMMANDS = new Set(); + + public static getRegisteredCommands(): readonly string[] { + return [...TriggerInlineEditCommandsRegistry.REGISTERED_COMMANDS]; + } + + public static registerCommand(commandId: string): void { + TriggerInlineEditCommandsRegistry.REGISTERED_COMMANDS.add(commandId); + } +} diff --git a/src/vs/editor/browser/view/domLineBreaksComputer.ts b/src/vs/editor/browser/view/domLineBreaksComputer.ts index 6eed0a076be..881275f34af 100644 --- a/src/vs/editor/browser/view/domLineBreaksComputer.ts +++ b/src/vs/editor/browser/view/domLineBreaksComputer.ts @@ -130,7 +130,7 @@ function createLineBreaks(targetWindow: Window, requests: string[], fontInfo: Fo containerDomNode.innerHTML = trustedhtml as string; containerDomNode.style.position = 'absolute'; - containerDomNode.style.top = '10000'; + containerDomNode.style.top = '10000px'; if (wordBreak === 'keepAll') { // word-break: keep-all; overflow-wrap: anywhere containerDomNode.style.wordBreak = 'keep-all'; diff --git a/src/vs/editor/browser/view/renderingContext.ts b/src/vs/editor/browser/view/renderingContext.ts index fdb24034701..1ed624ecfe4 100644 --- a/src/vs/editor/browser/view/renderingContext.ts +++ b/src/vs/editor/browser/view/renderingContext.ts @@ -87,7 +87,7 @@ export class RenderingContext extends RestrictedRenderingContext { public linesVisibleRangesForRange(range: Range, includeNewLines: boolean): LineVisibleRanges[] | null { const domRanges = this._viewLines.linesVisibleRangesForRange(range, includeNewLines); if (!this._viewLinesGpu) { - return domRanges ?? null; + return domRanges; } const gpuRanges = this._viewLinesGpu.linesVisibleRangesForRange(range, includeNewLines); if (!domRanges) { diff --git a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts index 8d627025769..56143c6a32c 100644 --- a/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts +++ b/src/vs/editor/browser/viewParts/currentLineHighlight/currentLineHighlight.ts @@ -5,7 +5,7 @@ import './currentLineHighlight.css'; import { DynamicViewOverlay } from '../../view/dynamicViewOverlay.js'; -import { editorLineHighlight, editorLineHighlightBorder } from '../../../common/core/editorColorRegistry.js'; +import { editorLineHighlight, editorInactiveLineHighlight, editorLineHighlightBorder } from '../../../common/core/editorColorRegistry.js'; import { RenderingContext } from '../../view/renderingContext.js'; import { ViewContext } from '../../../common/viewModel/viewContext.js'; import * as viewEvents from '../../../common/viewEvents.js'; @@ -236,10 +236,20 @@ export class CurrentLineMarginHighlightOverlay extends AbstractLineHighlightOver registerThemingParticipant((theme, collector) => { const lineHighlight = theme.getColor(editorLineHighlight); + const inactiveLineHighlight = theme.getColor(editorInactiveLineHighlight); + + // Apply active line highlight when editor is focused if (lineHighlight) { - collector.addRule(`.monaco-editor .view-overlays .current-line { background-color: ${lineHighlight}; }`); - collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { background-color: ${lineHighlight}; border: none; }`); + collector.addRule(`.monaco-editor.focused .view-overlays .current-line { background-color: ${lineHighlight}; }`); + collector.addRule(`.monaco-editor.focused .margin-view-overlays .current-line-margin { background-color: ${lineHighlight}; border: none; }`); } + + // Apply inactive line highlight when editor is not focused + if (inactiveLineHighlight) { + collector.addRule(`.monaco-editor .view-overlays .current-line { background-color: ${inactiveLineHighlight}; }`); + collector.addRule(`.monaco-editor .margin-view-overlays .current-line-margin { background-color: ${inactiveLineHighlight}; border: none; }`); + } + if (!lineHighlight || lineHighlight.isTransparent() || theme.defines(editorLineHighlightBorder)) { const lineHighlightBorder = theme.getColor(editorLineHighlightBorder); if (lineHighlightBorder) { diff --git a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts index dd565eac9e4..875311054f8 100644 --- a/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts +++ b/src/vs/editor/browser/viewParts/glyphMargin/glyphMargin.ts @@ -94,8 +94,7 @@ export abstract class DedupOverlay extends DynamicViewOverlay { let prevClassName: string | null = null; let prevEndLineIndex = 0; - for (let i = 0, len = decorations.length; i < len; i++) { - const d = decorations[i]; + for (const d of decorations) { const className = d.className; const zIndex = d.zIndex; let startLineIndex = Math.max(d.startLineNumber, visibleStartLineNumber) - visibleStartLineNumber; @@ -110,8 +109,8 @@ export abstract class DedupOverlay extends DynamicViewOverlay { prevEndLineIndex = endLineIndex; } - for (let i = startLineIndex; i <= prevEndLineIndex; i++) { - output[i].add(new LineDecorationToRender(className, zIndex, d.tooltip)); + for (let lineIndex = startLineIndex; lineIndex <= prevEndLineIndex; lineIndex++) { + output[lineIndex].add(new LineDecorationToRender(className, zIndex, d.tooltip)); } } diff --git a/src/vs/editor/browser/viewParts/minimap/minimap.ts b/src/vs/editor/browser/viewParts/minimap/minimap.ts index 6fb1f36868b..ad53e1e16c1 100644 --- a/src/vs/editor/browser/viewParts/minimap/minimap.ts +++ b/src/vs/editor/browser/viewParts/minimap/minimap.ts @@ -1663,7 +1663,7 @@ class InnerMinimap extends Disposable { continue; } highlightedLines.set(line, true); - const y = layout.getYForLineNumber(startLineNumber, minimapLineHeight); + const y = layout.getYForLineNumber(line, minimapLineHeight); canvasContext.fillRect(MINIMAP_GUTTER_WIDTH, y, canvasContext.canvas.width, minimapLineHeight); } } diff --git a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts index a84da6b2b1d..d286e3b2074 100644 --- a/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts +++ b/src/vs/editor/browser/viewParts/overlayWidgets/overlayWidgets.ts @@ -124,7 +124,7 @@ export class ViewOverlayWidgets extends ViewPart { public setWidgetPosition(widget: IOverlayWidget, position: IOverlayWidgetPosition | null): boolean { const widgetData = this._widgets[widget.getId()]; const preference = position ? position.preference : null; - const stack = position?.stackOridinal; + const stack = position?.stackOrdinal; if (widgetData.preference === preference && widgetData.stack === stack) { this._updateMaxMinWidth(); return false; diff --git a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts index 11292eb56a1..2c9deddd77c 100644 --- a/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts +++ b/src/vs/editor/browser/viewParts/overviewRuler/overviewRuler.ts @@ -136,7 +136,7 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { private _renderOneLane(ctx: CanvasRenderingContext2D, colorZones: ColorZone[], id2Color: string[], width: number): void { - let currentColorId = 0; + let currentColorId = 0; // will never match a real color id which is > 0 let currentFrom = 0; let currentTo = 0; @@ -147,7 +147,9 @@ export class OverviewRuler extends ViewEventHandler implements IOverviewRuler { const zoneTo = zone.to; if (zoneColorId !== currentColorId) { - ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); + if (currentColorId !== 0) { + ctx.fillRect(0, currentFrom, width, currentTo - currentFrom); + } currentColorId = zoneColorId; ctx.fillStyle = id2Color[currentColorId]; diff --git a/src/vs/editor/browser/viewParts/rulers/rulers.ts b/src/vs/editor/browser/viewParts/rulers/rulers.ts index c0a46927d17..f34f20f43a9 100644 --- a/src/vs/editor/browser/viewParts/rulers/rulers.ts +++ b/src/vs/editor/browser/viewParts/rulers/rulers.ts @@ -66,13 +66,11 @@ export class Rulers extends ViewPart { } if (currentCount < desiredCount) { - const { tabSize } = this._context.viewModel.model.getOptions(); - const rulerWidth = tabSize; let addCount = desiredCount - currentCount; while (addCount > 0) { const node = createFastDomNode(document.createElement('div')); node.setClassName('view-ruler'); - node.setWidth(rulerWidth); + node.setWidth('1px'); this.domNode.appendChild(node); this._renderedRulers.push(node); addCount--; diff --git a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts index 71a9a7605c7..dc5dc300709 100644 --- a/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts +++ b/src/vs/editor/browser/viewParts/scrollDecoration/scrollDecoration.ts @@ -9,7 +9,7 @@ import { ViewPart } from '../../view/viewPart.js'; import { RenderingContext, RestrictedRenderingContext } from '../../view/renderingContext.js'; import { ViewContext } from '../../../common/viewModel/viewContext.js'; import * as viewEvents from '../../../common/viewEvents.js'; -import { EditorOption } from '../../../common/config/editorOptions.js'; +import { EditorOption, RenderMinimap } from '../../../common/config/editorOptions.js'; export class ScrollDecorationViewPart extends ViewPart { @@ -56,7 +56,7 @@ export class ScrollDecorationViewPart extends ViewPart { const options = this._context.configuration.options; const layoutInfo = options.get(EditorOption.layoutInfo); - if (layoutInfo.minimap.renderMinimap === 0 || (layoutInfo.minimap.minimapWidth > 0 && layoutInfo.minimap.minimapLeft === 0)) { + if (layoutInfo.minimap.renderMinimap === RenderMinimap.None || (layoutInfo.minimap.minimapWidth > 0 && layoutInfo.minimap.minimapLeft === 0)) { this._width = layoutInfo.width; } else { this._width = layoutInfo.width - layoutInfo.verticalScrollbarWidth; diff --git a/src/vs/editor/browser/viewParts/viewLines/domReadingContext.ts b/src/vs/editor/browser/viewParts/viewLines/domReadingContext.ts index 1a11700242e..c336dacbcf7 100644 --- a/src/vs/editor/browser/viewParts/viewLines/domReadingContext.ts +++ b/src/vs/editor/browser/viewParts/viewLines/domReadingContext.ts @@ -20,7 +20,8 @@ export class DomReadingContext { const rect = this._domNode.getBoundingClientRect(); this.markDidDomLayout(); this._clientRectDeltaLeft = rect.left; - this._clientRectScale = rect.width / this._domNode.offsetWidth; + const offsetWidth = this._domNode.offsetWidth; + this._clientRectScale = offsetWidth > 0 ? rect.width / offsetWidth : 1; } } diff --git a/src/vs/editor/browser/viewParts/viewLines/viewLine.ts b/src/vs/editor/browser/viewParts/viewLines/viewLine.ts index 927a9a39cb0..a3763b98430 100644 --- a/src/vs/editor/browser/viewParts/viewLines/viewLine.ts +++ b/src/vs/editor/browser/viewParts/viewLines/viewLine.ts @@ -704,7 +704,7 @@ function createNormalRenderedLine(domNode: FastDomNode | null, rend } export function getColumnOfNodeOffset(characterMapping: CharacterMapping, spanNode: HTMLElement, offset: number): number { - const spanNodeTextContentLength = spanNode.textContent!.length; + const spanNodeTextContentLength = spanNode.textContent.length; let spanIndex = -1; while (spanNode) { diff --git a/src/vs/editor/browser/viewParts/viewLines/viewLines.ts b/src/vs/editor/browser/viewParts/viewLines/viewLines.ts index ccf5bc01ef1..a55c710a568 100644 --- a/src/vs/editor/browser/viewParts/viewLines/viewLines.ts +++ b/src/vs/editor/browser/viewParts/viewLines/viewLines.ts @@ -245,12 +245,10 @@ export class ViewLines extends ViewPart implements IViewLines { return r; } public override onDecorationsChanged(e: viewEvents.ViewDecorationsChangedEvent): boolean { - if (true/*e.inlineDecorationsChanged*/) { - const rendStartLineNumber = this._visibleLines.getStartLineNumber(); - const rendEndLineNumber = this._visibleLines.getEndLineNumber(); - for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) { - this._visibleLines.getVisibleLine(lineNumber).onDecorationsChanged(); - } + const rendStartLineNumber = this._visibleLines.getStartLineNumber(); + const rendEndLineNumber = this._visibleLines.getEndLineNumber(); + for (let lineNumber = rendStartLineNumber; lineNumber <= rendEndLineNumber; lineNumber++) { + this._visibleLines.getVisibleLine(lineNumber).onDecorationsChanged(); } return true; } @@ -541,7 +539,7 @@ export class ViewLines extends ViewPart implements IViewLines { // only proceed if we just did a layout return; } - if (this._asyncUpdateLineWidths.isScheduled()) { + if (!this._asyncUpdateLineWidths.isScheduled()) { // reading widths is not scheduled => widths are up-to-date return; } diff --git a/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts b/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts index dca6206ec1f..55ddb01f83d 100644 --- a/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts +++ b/src/vs/editor/browser/viewParts/viewLinesGpu/viewLinesGpu.ts @@ -240,7 +240,7 @@ export class ViewLinesGpu extends ViewPart implements IViewLines { const module = this._device.createShaderModule({ label: 'Monaco shader module', - code: this._renderStrategy.value!.wgsl, + code: this._renderStrategy.value.wgsl, }); // #endregion Shader module diff --git a/src/vs/editor/browser/viewParts/whitespace/whitespace.ts b/src/vs/editor/browser/viewParts/whitespace/whitespace.ts index 5e4aaddb3da..546d268130c 100644 --- a/src/vs/editor/browser/viewParts/whitespace/whitespace.ts +++ b/src/vs/editor/browser/viewParts/whitespace/whitespace.ts @@ -90,14 +90,6 @@ export class WhitespaceOverlay extends DynamicViewOverlay { return; } - const startLineNumber = ctx.visibleRange.startLineNumber; - const endLineNumber = ctx.visibleRange.endLineNumber; - const lineCount = endLineNumber - startLineNumber + 1; - const needed = new Array(lineCount); - for (let i = 0; i < lineCount; i++) { - needed[i] = true; - } - this._renderResult = []; for (let lineNumber = ctx.viewportData.startLineNumber; lineNumber <= ctx.viewportData.endLineNumber; lineNumber++) { const lineIndex = lineNumber - ctx.viewportData.startLineNumber; diff --git a/src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts index b2baac71ac6..2c00b9246ad 100644 --- a/src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditor/codeEditorWidget.ts @@ -599,8 +599,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE if (!this._modelData) { return -1; } - const maxCol = this._modelData.model.getLineMaxColumn(lineNumber); - return CodeEditorWidget._getVerticalOffsetAfterPosition(this._modelData, lineNumber, maxCol, includeViewZones); + return CodeEditorWidget._getVerticalOffsetAfterPosition(this._modelData, lineNumber, Number.MAX_SAFE_INTEGER, includeViewZones); } public getLineHeightForPosition(position: IPosition): number { @@ -678,6 +677,13 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE this._modelData.viewModel.revealRange('api', revealHorizontal, viewRange, verticalType, scrollType); } + public revealAllCursors(revealHorizontal: boolean, minimalReveal?: boolean): void { + if (!this._modelData) { + return; + } + this._modelData.viewModel.revealAllCursors('api', revealHorizontal, minimalReveal); + } + public revealLine(lineNumber: number, scrollType: editorCommon.ScrollType = editorCommon.ScrollType.Smooth): void { this._revealLine(lineNumber, VerticalRevealType.Simple, scrollType); } @@ -784,7 +790,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE } if (isSelection) { - this._setSelectionImpl(something, source); + this._setSelectionImpl(something, source); } else if (isRange) { // act as if it was an IRange const selection: ISelection = { diff --git a/src/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.ts b/src/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.ts index c5dac3172be..9660b641fdd 100644 --- a/src/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.ts +++ b/src/vs/editor/browser/widget/diffEditor/components/accessibleDiffViewer.ts @@ -617,14 +617,14 @@ class View extends Disposable { if (item.modifiedLineNumber !== undefined) { let html: string | TrustedHTML = this._getLineHtml(modifiedModel, modifiedOptions, modifiedModelOpts.tabSize, item.modifiedLineNumber, this._languageService.languageIdCodec); if (AccessibleDiffViewer._ttPolicy) { - html = AccessibleDiffViewer._ttPolicy.createHTML(html as string); + html = AccessibleDiffViewer._ttPolicy.createHTML(html); } cell.insertAdjacentHTML('beforeend', html as string); lineContent = modifiedModel.getLineContent(item.modifiedLineNumber); } else { let html: string | TrustedHTML = this._getLineHtml(originalModel, originalOptions, originalModelOpts.tabSize, item.originalLineNumber, this._languageService.languageIdCodec); if (AccessibleDiffViewer._ttPolicy) { - html = AccessibleDiffViewer._ttPolicy.createHTML(html as string); + html = AccessibleDiffViewer._ttPolicy.createHTML(html); } cell.insertAdjacentHTML('beforeend', html as string); lineContent = originalModel.getLineContent(item.originalLineNumber); diff --git a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/copySelection.ts b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/copySelection.ts new file mode 100644 index 00000000000..f138cbfc9de --- /dev/null +++ b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/copySelection.ts @@ -0,0 +1,77 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { addDisposableListener } from '../../../../../../base/browser/dom.js'; +import { DisposableStore } from '../../../../../../base/common/lifecycle.js'; +import { Range } from '../../../../../common/core/range.js'; +import { DetailedLineRangeMapping } from '../../../../../common/diff/rangeMapping.js'; +import { ITextModel } from '../../../../../common/model.js'; +import { IClipboardService } from '../../../../../../platform/clipboard/common/clipboardService.js'; +import { RenderLinesResult } from './renderLines.js'; + +export interface IEnableViewZoneCopySelectionOptions { + /** The view zone HTML element that contains the deleted codes. */ + domNode: HTMLElement; + + /** The diff entry for the current view zone. */ + diffEntry: DetailedLineRangeMapping; + + /** The original text model, to get the original text based on selection. */ + originalModel: ITextModel; + + /** The render lines result that can translate DOM positions to model positions. */ + renderLinesResult: RenderLinesResult; + + /** The clipboard service to write the selected text to. */ + clipboardService: IClipboardService; +} + +export function enableCopySelection(options: IEnableViewZoneCopySelectionOptions): DisposableStore { + const { domNode, renderLinesResult, diffEntry, originalModel, clipboardService } = options; + const viewZoneDisposable = new DisposableStore(); + + viewZoneDisposable.add(addDisposableListener(domNode, 'copy', (e) => { + e.preventDefault(); + const selection = domNode.ownerDocument.getSelection(); + if (!selection || selection.rangeCount === 0) { + return; + } + + const domRange = selection.getRangeAt(0); + if (!domRange || domRange.collapsed) { + return; + } + + const startElement = domRange.startContainer.nodeType === Node.TEXT_NODE + ? domRange.startContainer.parentElement + : domRange.startContainer as HTMLElement; + const endElement = domRange.endContainer.nodeType === Node.TEXT_NODE + ? domRange.endContainer.parentElement + : domRange.endContainer as HTMLElement; + + if (!startElement || !endElement) { + return; + } + + const startPosition = renderLinesResult.getModelPositionAt(startElement, domRange.startOffset); + const endPosition = renderLinesResult.getModelPositionAt(endElement, domRange.endOffset); + + if (!startPosition || !endPosition) { + return; + } + + const adjustedStart = startPosition.delta(diffEntry.original.startLineNumber - 1); + const adjustedEnd = endPosition.delta(diffEntry.original.startLineNumber - 1); + + const range = adjustedEnd.isBefore(adjustedStart) ? + Range.fromPositions(adjustedEnd, adjustedStart) : + Range.fromPositions(adjustedStart, adjustedEnd); + + const selectedText = originalModel.getValueInRange(range); + clipboardService.writeText(selectedText); + })); + + return viewZoneDisposable; +} diff --git a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts index a5b5d8c9540..62bf7ece01a 100644 --- a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts +++ b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/diffEditorViewZones.ts @@ -199,7 +199,7 @@ export class DiffEditorViewZones extends Disposable { originalModelTokenizationCompleted.read(reader); // Update view-zones once tokenization completes const deletedCodeDomNode = document.createElement('div'); - deletedCodeDomNode.classList.add('view-lines', 'line-delete', 'monaco-mouse-cursor-text'); + deletedCodeDomNode.classList.add('view-lines', 'line-delete', 'line-delete-selectable', 'monaco-mouse-cursor-text'); const originalModel = this._editors.original.getModel()!; // `a.originalRange` can be out of bound when the diff has not been updated yet. // In this case, we do an early return. @@ -241,10 +241,11 @@ export class DiffEditorViewZones extends Disposable { new InlineDiffDeletedCodeMargin( () => assertReturnsDefined(zoneId), marginDomNode, + deletedCodeDomNode, this._editors.modified, a.diff, this._diffEditorWidget, - result.viewLineCounts, + result, this._editors.original.getModel()!, this._contextMenuService, this._clipboardService, @@ -273,7 +274,7 @@ export class DiffEditorViewZones extends Disposable { marginDomNode, setZoneId(id) { zoneId = id; }, showInHiddenAreas: true, - suppressMouseDown: true, + suppressMouseDown: false, }); } diff --git a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/inlineDiffDeletedCodeMargin.ts b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/inlineDiffDeletedCodeMargin.ts index fa63055ff08..22541178471 100644 --- a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/inlineDiffDeletedCodeMargin.ts +++ b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/inlineDiffDeletedCodeMargin.ts @@ -18,6 +18,8 @@ import { EndOfLineSequence, ITextModel } from '../../../../../common/model.js'; import { localize } from '../../../../../../nls.js'; import { IClipboardService } from '../../../../../../platform/clipboard/common/clipboardService.js'; import { IContextMenuService } from '../../../../../../platform/contextview/browser/contextView.js'; +import { enableCopySelection } from './copySelection.js'; +import { RenderLinesResult } from './renderLines.js'; export class InlineDiffDeletedCodeMargin extends Disposable { private readonly _diffActions: HTMLElement; @@ -38,10 +40,11 @@ export class InlineDiffDeletedCodeMargin extends Disposable { constructor( private readonly _getViewZoneId: () => string, private readonly _marginDomNode: HTMLElement, + private readonly _deletedCodeDomNode: HTMLElement, private readonly _modifiedEditor: CodeEditorWidget, private readonly _diff: DetailedLineRangeMapping, private readonly _editor: DiffEditorWidget, - private readonly _viewLineCounts: number[], + private readonly _renderLinesResult: RenderLinesResult, private readonly _originalTextModel: ITextModel, private readonly _contextMenuService: IContextMenuService, private readonly _clipboardService: IClipboardService, @@ -64,12 +67,13 @@ export class InlineDiffDeletedCodeMargin extends Disposable { let currentLineNumberOffset = 0; const useShadowDOM = _modifiedEditor.getOption(EditorOption.useShadowDOM) && !isIOS; // Do not use shadow dom on IOS #122035 - const showContextMenu = (x: number, y: number) => { + const showContextMenu = (anchor: { x: number; y: number }, baseActions?: Action[], onHide?: () => void) => { this._contextMenuService.showContextMenu({ domForShadowRoot: useShadowDOM ? _modifiedEditor.getDomNode() ?? undefined : undefined, - getAnchor: () => ({ x, y }), + getAnchor: () => anchor, + onHide, getActions: () => { - const actions: Action[] = []; + const actions: Action[] = baseActions ?? []; const isDeletion = _diff.modified.isEmpty; // default action @@ -135,7 +139,7 @@ export class InlineDiffDeletedCodeMargin extends Disposable { const { top, height } = getDomNodePagePosition(this._diffActions); const pad = Math.floor(lineHeight / 3); e.preventDefault(); - showContextMenu(e.posx, top + height + pad); + showContextMenu({ x: e.posx, y: top + height + pad }); })); this._register(_modifiedEditor.onMouseMove((e: IEditorMouseEvent) => { @@ -147,18 +151,12 @@ export class InlineDiffDeletedCodeMargin extends Disposable { } })); - this._register(_modifiedEditor.onMouseDown((e: IEditorMouseEvent) => { - if (!e.event.leftButton) { return; } - - if (e.target.type === MouseTargetType.CONTENT_VIEW_ZONE || e.target.type === MouseTargetType.GUTTER_VIEW_ZONE) { - const viewZoneId = e.target.detail.viewZoneId; - - if (viewZoneId === this._getViewZoneId()) { - e.event.preventDefault(); - currentLineNumberOffset = this._updateLightBulbPosition(this._marginDomNode, e.event.browserEvent.y, lineHeight); - showContextMenu(e.event.posx, e.event.posy + lineHeight); - } - } + this._register(enableCopySelection({ + domNode: this._deletedCodeDomNode, + diffEntry: _diff, + originalModel: this._originalTextModel, + renderLinesResult: this._renderLinesResult, + clipboardService: _clipboardService, })); } @@ -168,10 +166,10 @@ export class InlineDiffDeletedCodeMargin extends Disposable { const lineNumberOffset = Math.floor(offset / lineHeight); const newTop = lineNumberOffset * lineHeight; this._diffActions.style.top = `${newTop}px`; - if (this._viewLineCounts) { + if (this._renderLinesResult.viewLineCounts) { let acc = 0; - for (let i = 0; i < this._viewLineCounts.length; i++) { - acc += this._viewLineCounts[i]; + for (let i = 0; i < this._renderLinesResult.viewLineCounts.length; i++) { + acc += this._renderLinesResult.viewLineCounts[i]; if (lineNumberOffset < acc) { return i; } diff --git a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/renderLines.ts b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/renderLines.ts index 6d54628cc0d..fc04faf7104 100644 --- a/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/renderLines.ts +++ b/src/vs/editor/browser/widget/diffEditor/components/diffEditorViewZones/renderLines.ts @@ -8,13 +8,15 @@ import { applyFontInfo } from '../../../../config/domFontInfo.js'; import { ICodeEditor } from '../../../../editorBrowser.js'; import { EditorFontLigatures, EditorOption, FindComputedEditorOptionValueById } from '../../../../../common/config/editorOptions.js'; import { FontInfo } from '../../../../../common/config/fontInfo.js'; +import { Position } from '../../../../../common/core/position.js'; import { StringBuilder } from '../../../../../common/core/stringBuilder.js'; import { ModelLineProjectionData } from '../../../../../common/modelLineProjectionData.js'; import { IViewLineTokens, LineTokens } from '../../../../../common/tokens/lineTokens.js'; import { LineDecoration } from '../../../../../common/viewLayout/lineDecorations.js'; -import { RenderLineInput, renderViewLine } from '../../../../../common/viewLayout/viewLineRenderer.js'; +import { CharacterMapping, ForeignElementType, RenderLineInput, RenderLineOutput, renderViewLine } from '../../../../../common/viewLayout/viewLineRenderer.js'; import { ViewLineRenderingData } from '../../../../../common/viewModel.js'; import { InlineDecoration } from '../../../../../common/viewModel/inlineDecorations.js'; +import { getColumnOfNodeOffset } from '../../../../viewParts/viewLines/viewLine.js'; const ttPolicy = createTrustedTypesPolicy('diffEditorWidget', { createHTML: value => value }); @@ -27,6 +29,7 @@ export function renderLines(source: LineSource, options: RenderOptions, decorati let maxCharsPerLine = 0; let renderedLineCount = 0; const viewLineCounts: number[] = []; + const renderOutputs: RenderLineOutputWithOffset[] = []; for (let lineIndex = 0; lineIndex < source.lineTokens.length; lineIndex++) { const lineNumber = lineIndex + 1; const lineTokens = source.lineTokens[lineIndex]; @@ -37,7 +40,7 @@ export function renderLines(source: LineSource, options: RenderOptions, decorati let lastBreakOffset = 0; for (const breakOffset of lineBreakData.breakOffsets) { const viewLineTokens = lineTokens.sliceAndInflate(lastBreakOffset, breakOffset, 0); - maxCharsPerLine = Math.max(maxCharsPerLine, renderOriginalLine( + const result = renderOriginalLine( renderedLineCount, viewLineTokens, LineDecoration.extractWrapped(actualDecorations, lastBreakOffset, breakOffset), @@ -47,14 +50,16 @@ export function renderLines(source: LineSource, options: RenderOptions, decorati options, sb, noExtra, - )); + ); + maxCharsPerLine = Math.max(maxCharsPerLine, result.maxCharWidth); + renderOutputs.push(new RenderLineOutputWithOffset(result.output.characterMapping, result.output.containsForeignElements, lastBreakOffset)); renderedLineCount++; lastBreakOffset = breakOffset; } viewLineCounts.push(lineBreakData.breakOffsets.length); } else { viewLineCounts.push(1); - maxCharsPerLine = Math.max(maxCharsPerLine, renderOriginalLine( + const result = renderOriginalLine( renderedLineCount, lineTokens, actualDecorations, @@ -64,7 +69,9 @@ export function renderLines(source: LineSource, options: RenderOptions, decorati options, sb, noExtra, - )); + ); + maxCharsPerLine = Math.max(maxCharsPerLine, result.maxCharWidth); + renderOutputs.push(new RenderLineOutputWithOffset(result.output.characterMapping, result.output.containsForeignElements, 0)); renderedLineCount++; } } @@ -75,14 +82,15 @@ export function renderLines(source: LineSource, options: RenderOptions, decorati domNode.innerHTML = trustedhtml as string; const minWidthInPx = (maxCharsPerLine * options.typicalHalfwidthCharacterWidth); - return { - heightInLines: renderedLineCount, + return new RenderLinesResult( + renderedLineCount, minWidthInPx, viewLineCounts, - }; + renderOutputs, + source, + ); } - export class LineSource { constructor( public readonly lineTokens: LineTokens[], @@ -170,10 +178,83 @@ export class RenderOptions { } } -export interface RenderLinesResult { - minWidthInPx: number; - heightInLines: number; - viewLineCounts: number[]; +export class RenderLinesResult { + constructor( + public readonly heightInLines: number, + public readonly minWidthInPx: number, + public readonly viewLineCounts: number[], + private readonly _renderOutputs: RenderLineOutputWithOffset[], + private readonly _source: LineSource, + ) { } + + /** + * Returns the model position for a given DOM node and offset within that node. + * @param domNode The span node within a view-line where the offset is located + * @param offset The offset within the span node + * @returns The Position in the model, or undefined if the position cannot be determined + */ + public getModelPositionAt(domNode: HTMLElement, offset: number): Position | undefined { + // Find the view-line element that contains this span + let viewLineElement: HTMLElement | null = domNode; + while (viewLineElement && !viewLineElement.classList.contains('view-line')) { + viewLineElement = viewLineElement.parentElement; + } + + if (!viewLineElement) { + return undefined; + } + + // Find the container that has all view lines + const container = viewLineElement.parentElement; + if (!container) { + return undefined; + } + + // Find the view line index based on the element + // eslint-disable-next-line no-restricted-syntax + const viewLines = container.querySelectorAll('.view-line'); + let viewLineIndex = -1; + for (let i = 0; i < viewLines.length; i++) { + if (viewLines[i] === viewLineElement) { + viewLineIndex = i; + break; + } + } + + if (viewLineIndex === -1 || viewLineIndex >= this._renderOutputs.length) { + return undefined; + } + + // Map view line index back to model line + let modelLineNumber = 1; + let remainingViewLines = viewLineIndex; + for (let i = 0; i < this.viewLineCounts.length; i++) { + if (remainingViewLines < this.viewLineCounts[i]) { + modelLineNumber = i + 1; + break; + } + remainingViewLines -= this.viewLineCounts[i]; + } + + if (modelLineNumber > this._source.lineTokens.length) { + return undefined; + } + + const renderOutput = this._renderOutputs[viewLineIndex]; + if (!renderOutput) { + return undefined; + } + + const column = getColumnOfNodeOffset(renderOutput.characterMapping, domNode, offset) + renderOutput.offset; + + return new Position(modelLineNumber, column); + } +} + +class RenderLineOutputWithOffset extends RenderLineOutput { + constructor(characterMapping: CharacterMapping, containsForeignElements: ForeignElementType, public readonly offset: number) { + super(characterMapping, containsForeignElements); + } } function renderOriginalLine( @@ -186,7 +267,7 @@ function renderOriginalLine( options: RenderOptions, sb: StringBuilder, noExtra: boolean, -): number { +): { output: RenderLineOutput; maxCharWidth: number } { sb.appendString('